Referencia de Eventos
Referencia de Eventos
Venflow emite eventos que cubren el ciclo de vida de clientes, suscripciones, facturas y pagos, además de eventos a nivel de organización (como el vencimiento de las credenciales del gateway).
Tipos de Eventos
Eventos a nivel de cliente
| Evento | Descripción |
|---|---|
USER_CREATE_EVENT | Nuevo cliente creado |
SUBSCRIPTION_CREATE_EVENT | Suscripción creada |
SUBSCRIPTION_UPDATED_EVENT | La suscripción cambió de estado (por ejemplo active → past_due) |
SUBSCRIPTION_CANCELLED_EVENT | Suscripción cancelada |
INVOICE_CREATE_EVENT | Factura generada |
INVOICE_UPDATE_EVENT | Estado de factura actualizado |
PAYMENT_SUCCESS_EVENT | Pago exitoso |
PAYMENT_FAILED_EVENT | Pago fallido |
PAYMENT_REMINDER_PRE_EVENT | Recordatorio antes de la fecha de cobro |
PAYMENT_REMINDER_POST_EVENT | Recordatorio después de un cobro fallido o de un pago manual pendiente |
Eventos a nivel de organización
A diferencia de los anteriores, estos eventos no incluyen el objeto client porque corresponden a la organización, no a un cliente puntual.
| Evento | Descripción |
|---|---|
GATEWAY_API_KEY_EXPIRING_EVENT | La API key del gateway está por vencer |
GATEWAY_API_KEY_EXPIRED_EVENT | La API key del gateway venció y fue desactivada |
Campo común: livemode
Además de los campos propios de cada tipo, todo payload incluye livemode:
| Campo | Tipo | Descripción |
|---|---|---|
livemode | boolean | true cuando el evento viene de tu organización real. false cuando viene de tu organización sandbox, donde nada movió dinero. |
Si tu handler escribe en tu contabilidad, haz que ignore (o registre aparte) todo lo
que llegue con livemode: false.
USER_CREATE_EVENT
Se envía cuando se crea un nuevo cliente durante el flujo de checkout. Solo se dispara para clientes nuevos, no cuando se reutiliza un cliente existente.
{
"eventType": "USER_CREATE_EVENT",
"client": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "cliente@email.com",
"name": "Juan",
"lastName": "Pérez"
}
}SUBSCRIPTION_CREATE_EVENT
Se envía cuando se crea una suscripción durante el flujo de checkout, después de la activación del plan.
{
"eventType": "SUBSCRIPTION_CREATE_EVENT",
"client": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "cliente@email.com",
"name": "Juan",
"lastName": "Pérez"
},
"subscription": {
"id": "550e8400-e29b-41d4-a716-446655440001",
"status": "active",
"externalId": "EXT123456"
}
}Campos de subscription
| Campo | Tipo | Descripción |
|---|---|---|
id | string (UUID) | ID único de la suscripción |
status | string | Estado: active, inactive, cancelled, pending |
externalId | string | null | ID externo de la asociación cliente-organización |
SUBSCRIPTION_UPDATED_EVENT
Se envía cuando una suscripción cambia de estado y ese cambio no está cubierto por
SUBSCRIPTION_CREATE_EVENT ni por SUBSCRIPTION_CANCELLED_EVENT. El caso habitual es la
morosidad: pasa de active a past_due cuando un cobro falla, y vuelve a active cuando se
recupera.
Es el único evento que incluye previousStatus, así que puedes saber de dónde venía la
suscripción sin guardar el estado anterior por tu cuenta.
{
"eventType": "SUBSCRIPTION_UPDATED_EVENT",
"client": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "cliente@email.com",
"name": "Juan",
"lastName": "Pérez"
},
"subscription": {
"id": "550e8400-e29b-41d4-a716-446655440001",
"status": "past_due",
"previousStatus": "active",
"externalId": "EXT123456"
}
}Campos de subscription
| Campo | Tipo | Descripción |
|---|---|---|
id | string (UUID) | ID de la suscripción |
status | string | Estado al que pasó |
previousStatus | string | Estado del que venía |
externalId | string | null | ID externo de la asociación cliente-organización |
Este evento no cubre todas las transiciones. Hoy se emite en los cambios entre active,
past_due y pending. Programar una cancelación, deshacerla o reactivar una suscripción no lo
disparan, así que no lo uses como fuente única de verdad del estado: consulta
GET /v1/subscriptions/{id} cuando necesites el estado exacto.
SUBSCRIPTION_CANCELLED_EVENT
Se envía cuando una suscripción es cancelada. Incluye el motivo de cancelación.
{
"eventType": "SUBSCRIPTION_CANCELLED_EVENT",
"client": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "cliente@email.com",
"name": "Juan",
"lastName": "Pérez"
},
"subscription": {
"id": "550e8400-e29b-41d4-a716-446655440001",
"status": "cancelled",
"externalId": "EXT123456",
"cancellationReason": {
"type": "payment_failure",
"message": "Retry window exceeded"
}
}
}Campos de cancellationReason
| Campo | Tipo | Descripción |
|---|---|---|
type | string | Por qué se canceló: payment_failure o scheduled_cancellation |
scheduledDate | string | undefined | Fecha ISO en la que estaba programada la cancelación (solo en scheduled_cancellation) |
message | string | undefined | Mensaje descriptivo de la cancelación |
Cancelar desde el panel o desde la API no emite este evento. Hoy solo se dispara cuando la
cancelación la decide el sistema: porque se agotó la ventana de reintentos de cobro
(payment_failure) o porque llegó la fecha de una cancelación programada
(scheduled_cancellation). Si necesitas reaccionar a una cancelación hecha a mano, hazlo desde
tu propio código en el momento de llamar a POST /v1/subscriptions/{id}/cancel.
INVOICE_CREATE_EVENT
Se envía cuando se genera una factura durante el proceso de pago de suscripción. La factura se crea con estado open.
{
"eventType": "INVOICE_CREATE_EVENT",
"client": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "cliente@email.com",
"name": "Juan",
"lastName": "Pérez"
},
"subscription": {
"id": "550e8400-e29b-41d4-a716-446655440001",
"status": "active",
"externalId": "EXT123456"
},
"invoice": {
"id": "550e8400-e29b-41d4-a716-446655440002",
"status": "open",
"total": "3907.85",
"amountDue": "3907.85",
"totalUsd": "5.79",
"exchangeRate": "674.9305"
}
}Campos de invoice
| Campo | Tipo | Descripción |
|---|---|---|
id | string (UUID) | ID único de la factura |
status | string | Estado: open, paid, overdue, uncollectible, cancelled |
total | string | Monto total de la factura, en VES (Bs) — lo que el gateway cobra |
amountDue | string | Monto pendiente de pago, en VES (Bs) |
totalUsd | string | null | Mismo total en USD (neto = base + IVA − descuento), independiente de la tasa BCV. Puede ser null si la referencia en USD no está disponible |
exchangeRate | string | null | Tasa BCV (USD→VES) usada para este cobro: total ≈ totalUsd × exchangeRate. Puede ser null en facturas históricas |
Los dos viajan juntos: o
totalUsdyexchangeRatellegan los dos con valor, o llegan los dos ennull. Nunca vas a recibir una tasa sin el monto en dólares al que aplica, ni al revés.
INVOICE_UPDATE_EVENT
Se envía cuando cambia el estado de una factura. Los estados que lo disparan son:
paid: la factura fue pagada exitosamente (amountDuepasa a"0")uncollectible: el cobro no pudo completarse después de agotar los reintentoscancelled: la factura fue anulada manualmente, desde el dashboard o por API. En la API de facturas, este estado corresponde avoidopen: se reabrió manualmente el cobro de una factura que estaba en revisión, desde el dashboard o por API
Este evento llega con formas distintas bajo el mismo nombre. Ramifica por
invoice.status antes de leer el resto:
| Factura pagada | Factura incobrable | Factura anulada o reabierta | |
|---|---|---|---|
invoice.status | "paid" | "uncollectible" | "cancelled" o "open" |
invoice.amountDue | siempre "0" | el saldo real que quedó sin cobrar | el saldo real de la factura |
objeto subscription | presente si la factura pertenece a una suscripción; ausente si es un pago único | nunca presente, ni siquiera viniendo de una suscripción | presente si la factura pertenece a una suscripción; ausente si es un pago único, o si la suscripción está en un estado que este webhook no nombra (por ejemplo, todavía sin activar o en proceso de cancelarse) |
Verifica que el objeto subscription exista antes de leer event.subscription.id: no se incluye
en las facturas incobrables ni en algunas anuladas o reabiertas. Para asociar una factura con su
suscripción, guarda la relación al recibir INVOICE_CREATE_EVENT o consúltala por API con el
invoice.id.
El estado overdue aparece en el tipo del campo status pero no genera este webhook hoy.
Factura pagada
{
"eventType": "INVOICE_UPDATE_EVENT",
"client": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "cliente@email.com",
"name": "Juan",
"lastName": "Pérez"
},
"subscription": {
"id": "550e8400-e29b-41d4-a716-446655440001",
"status": "active",
"externalId": "EXT123456"
},
"invoice": {
"id": "550e8400-e29b-41d4-a716-446655440002",
"status": "paid",
"total": "3907.85",
"amountDue": "0",
"totalUsd": "5.79",
"exchangeRate": "674.9305"
}
}Factura incobrable
{
"eventType": "INVOICE_UPDATE_EVENT",
"client": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "cliente@email.com",
"name": "Juan",
"lastName": "Pérez"
},
"invoice": {
"id": "550e8400-e29b-41d4-a716-446655440002",
"status": "uncollectible",
"total": "3907.85",
"amountDue": "3907.85",
"totalUsd": "5.79",
"exchangeRate": "674.9305"
}
}Fíjate en lo que no está: no hay objeto subscription. Es a propósito, y pasa siempre en
este estado, aunque la factura sea de una suscripción.
Factura anulada
{
"eventType": "INVOICE_UPDATE_EVENT",
"client": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "cliente@email.com",
"name": "Juan",
"lastName": "Pérez"
},
"subscription": {
"id": "550e8400-e29b-41d4-a716-446655440001",
"status": "active",
"externalId": "EXT123456"
},
"invoice": {
"id": "550e8400-e29b-41d4-a716-446655440002",
"status": "cancelled",
"total": "3907.85",
"amountDue": "3907.85",
"totalUsd": "5.79",
"exchangeRate": "674.9305"
}
}amountDue refleja el saldo pendiente al momento de la anulación, ya que anular una factura no
la marca como cobrada. A partir de ese momento, la factura no se cobra ni se considera deuda.
Factura reabierta
Se envía cuando una factura en revisión vuelve a estar disponible para cobro:
{
"eventType": "INVOICE_UPDATE_EVENT",
"client": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "cliente@email.com",
"name": "Juan",
"lastName": "Pérez"
},
"subscription": {
"id": "550e8400-e29b-41d4-a716-446655440001",
"status": "active",
"externalId": "EXT123456"
},
"invoice": {
"id": "550e8400-e29b-41d4-a716-446655440002",
"status": "open",
"total": "3907.85",
"amountDue": "3907.85",
"totalUsd": "5.79",
"exchangeRate": "674.9305"
}
}Si posteriormente se confirma el cobro pendiente o la factura se cobra en un nuevo intento,
recibirás también los eventos de pago habituales: PAYMENT_SUCCESS_EVENT y
INVOICE_UPDATE_EVENT con estado paid.
En ambos casos, el objeto subscription puede no incluirse aunque la factura pertenezca a una
suscripción (ver la tabla anterior).
Moneda:
totalyamountDuevan en VES (Bs);totalUsdes el mismo total en USD (independiente de la tasa BCV) yexchangeRatees la tasa BCV que los relaciona (total ≈ totalUsd × exchangeRate).totalUsdyexchangeRatepueden sernullsi no están disponibles, y en ese caso lo son los dos: nunca llega una tasa sin su monto en dólares, ni al revés.
PAYMENT_SUCCESS_EVENT
Se envía cuando un pago se completa exitosamente. Si el pago se originó desde una sesión de checkout, incluye los datos de la sesión y su metadata.
{
"eventType": "PAYMENT_SUCCESS_EVENT",
"client": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "cliente@email.com",
"name": "Juan",
"lastName": "Pérez"
},
"payment": {
"id": "550e8400-e29b-41d4-a716-446655440003",
"status": "completed",
"retries": 1,
"gatewayUUID": "TXN000000123456",
"bankReference": "003812449021",
"errorMessage": null,
"bank": "Banco Nacional de Crédito",
"amount": "3907.85",
"amountUsd": "5.79",
"exchangeRate": "674.9305",
"paymentMethod": "domiciliado"
},
"session": {
"id": "660e8400-e29b-41d4-a716-446655440000",
"metadata": {
"order_id": "ORD-12345",
"campaign": "summer_promo"
}
}
}Campos de payment
| Campo | Tipo | Descripción |
|---|---|---|
id | string (UUID) | ID de la transacción |
status | string | Estado: pending, completed, failed |
retries | number | Número de intentos realizados |
gatewayUUID | string | Referencia de la transacción en el gateway de pago |
bankReference | string | null | La referencia que el banco del pagador imprime en su estado de cuenta — la única que puedes cruzar contra un extracto bancario, y por lo tanto la que usa una conciliación. Es distinta de gatewayUUID, que es el ID interno del procesador. Es null cuando el medio de pago no emitió referencia. En Pago Móvil el gatewayUUID siempre trajo esta misma referencia, porque ese medio no tiene ID de procesador. |
errorMessage | string | null | Mensaje de error (siempre null en pagos exitosos) |
bank | string | null | Pagos automáticos: banco del método de pago almacenado del cliente. Pagos manuales: banco seleccionado por el pagador en el formulario (Débito Inmediato) o reportado por el gateway (Pago Móvil). null cuando el banco no pudo resolverse — por ejemplo, si el código no existe en nuestra tabla de bancos o el pago se originó antes de que esta información estuviera disponible. |
amount | string | Monto cobrado, en VES (Bs) — lo que el gateway debita |
amountUsd | string | null | Mismo cobro en USD (neto = base + IVA − descuento), independiente de la tasa BCV. Puede ser null si la referencia en USD no está disponible |
exchangeRate | string | null | Tasa BCV (USD→VES) usada para este cobro: amount ≈ amountUsd × exchangeRate. Puede ser null si no está disponible |
paymentMethod | string | null | Vía por la que se cobró el pago: domiciliado, debito_inmediato, pago_movil o tarjeta (ver la tabla siguiente). Siempre está presente; es null cuando no se puede saber la vía |
Los dos viajan juntos: o
amountUsdyexchangeRatellegan los dos con valor, o llegan los dos ennull— la misma regla que enPAYMENT_FAILED_EVENT. Y la tasa viene congelada en la factura, no es la del día: si conviertesamountUsdcon la tasa de hoy te va a dar otro número.
Valores de paymentMethod
| Valor | Significado |
|---|---|
domiciliado | Cobro automático contra la cuenta o el teléfono que el cliente registró (domiciliación). También aplica cuando un cobro automático quedó en revisión y luego se marcó como pagado (desde el dashboard o con mark_paid del API): en ese caso se da por bueno ese cobro automático |
debito_inmediato | El cliente pagó con Débito Inmediato |
pago_movil | El cliente pagó con Pago Móvil |
tarjeta | El cliente pagó con tarjeta de débito o crédito |
null | No se puede saber la vía. Ocurre, por ejemplo, cuando la factura se marcó como pagada a mano y el dinero no entró por un cobro que Venflow haya registrado: sin intentos previos, después de intentos automáticos fallidos o con un cobro automático todavía en curso. Tu integración debe aceptar null |
Lista cerrada: trata
paymentMethodcomo una lista de valores fijos. Si en el futuro se agrega una vía nueva, se anunciará antes de empezar a enviarla.
No confundir con el API REST: en el API REST,
payment_methodes el ID (UUID) del método de pago guardado del cliente. ElpaymentMethodde este webhook es otra cosa: la vía por la que entró el dinero.
Solo en pagos exitosos: por ahora,
paymentMethodsolo viene enPAYMENT_SUCCESS_EVENT.PAYMENT_FAILED_EVENTno lo incluye.
Campos de session (opcional)
| Campo | Tipo | Descripción |
|---|---|---|
id | string (UUID) | ID de la sesión de checkout |
metadata | object | null | Metadata personalizada asociada a la sesión |
Nota: El campo
sessionsolo está presente en pagos que se originan desde una sesión de checkout. Los pagos recurrentes de suscripciones no incluyen este campo.
PAYMENT_FAILED_EVENT
Se envía cuando un pago falla. Puede ocurrir en múltiples etapas del procesamiento (validación, cobro de suscripción, verificación). Es posible recibir múltiples eventos de fallo para la misma transacción si hay reintentos.
{
"eventType": "PAYMENT_FAILED_EVENT",
"client": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "cliente@email.com",
"name": "Juan",
"lastName": "Pérez"
},
"payment": {
"id": "550e8400-e29b-41d4-a716-446655440003",
"status": "failed",
"retries": 2,
"gatewayUUID": "TXN000000123456",
"bankReference": "003812449021",
"errorMessage": "Insufficient funds",
"bank": "Banco Nacional de Crédito",
"amount": "3907.85",
"amountUsd": "5.79",
"exchangeRate": "674.9305"
},
"session": {
"id": "660e8400-e29b-41d4-a716-446655440000",
"metadata": {
"order_id": "ORD-12345",
"campaign": "summer_promo"
}
}
}Nota: Al igual que
PAYMENT_SUCCESS_EVENT, el camposessionsolo está presente cuando el pago se origina desde una sesión de checkout.
Campos del plan de reintentos (solo en cobros recurrentes)
Cuando el fallo ocurre cobrando una suscripción ya activa, el evento trae además estos dos campos. No aparecen en los fallos de checkout ni en los cobros de validación.
| Campo | Tipo | Descripción |
|---|---|---|
attemptCount | number | Cuántos intentos de cobro lleva este ciclo, contando el que acaba de fallar |
nextPaymentAttempt | string | null | Cuándo está agendado el siguiente intento (ISO 8601). null significa que no habrá más intentos: la factura se marca incobrable y la suscripción se cancela |
{
"eventType": "PAYMENT_FAILED_EVENT",
"client": { "...": "..." },
"payment": {
"id": "550e8400-e29b-41d4-a716-446655440003",
"status": "failed",
"errorMessage": "Insufficient funds",
"attemptCount": 2,
"nextPaymentAttempt": "2026-10-04T09:00:00.000Z"
}
}Si te interesa avisarle al cliente antes de perder la suscripción, nextPaymentAttempt: null es
la señal: es el último fallo antes de la cancelación.
Moneda:
amountes lo que se intentó cobrarle al banco, en VES (Bs).amountUsdes ese mismo monto en USD, tal como quedó guardado en la factura.exchangeRatees la tasa BCV que los relaciona:amount ≈ amountUsd × exchangeRate.
La tasa viene congelada en la factura, no es la del día. Es la tasa con la que se calculó ese cobro. Si conviertes
amountUsdcon la tasa de hoy te va a dar otro número: usa siempre elexchangeRateque llega en el evento. Esto es a propósito.
Cuándo llegan en
null:amountUsdyexchangeRatevienen ennullen tres casos. Uno, facturas viejas creadas antes de que existiera la columna en dólares. Dos, los cobros de validación — el cargo de prueba de Bs 1,00 que confirma que una cuenta bancaria existe, que no tiene factura ni precio en dólares detrás. Tres, un fallo tan temprano que la factura todavía no existía; ahíamountllega en"0". Nunca llega una tasa sin su monto en dólares, ni un monto en dólares sin su tasa: o vienen los dos con valor, o vienen los dos ennull.
Corrección —
amounten el primer cobro de un checkout de suscripción. Ese caso puntual traía el precio del plan, que está en dólares, mientras todos los demás traían bolívares. Era un error y quedó corregido:amountahora trae bolívares siempre.Esto no cambia ningún cobro. No cambia cuánto se le cobra al cliente, ni los correos que recibe, ni el evento de pago exitoso. Cambia un solo dato, de este evento, en este escenario.
Qué hacer: si tu integración lee
amountcomo dólares en un fallo de checkout, ajústala — una suscripción de USD 5,79 pasa de"5.79"a"3907.85". Si ya lo tratabas como bolívares, no tienes nada que hacer: hasta ahora recibías un dato incorrecto en ese caso y ahora recibes el correcto. El monto en dólares no se pierde, viaja enamountUsd, y conexchangeRateal lado puedes reconstruir el valor anterior dividiendo.
PAYMENT_REMINDER_PRE_EVENT
Se envía cuando Venflow le recuerda al cliente que se acerca la fecha de cobro, según los recordatorios configurados en tu organización, y solo si ese recordatorio tiene activado el canal de webhook. Sirve para avisarle al cliente también por tus propios canales.
A diferencia del resto de los eventos de cliente, no incluye el objeto subscription: el
recordatorio describe una fecha de cobro, no un cambio en la suscripción.
{
"eventType": "PAYMENT_REMINDER_PRE_EVENT",
"client": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "cliente@email.com",
"name": "Juan",
"lastName": "Pérez"
},
"reminder": {
"type": "pre_payment",
"daysOffset": 3,
"billingDate": "2026-10-01 00:00:00+00"
}
}PAYMENT_REMINDER_POST_EVENT
Mismo formato que el anterior, pero para recordatorios posteriores: después de un cobro fallido, o para un pago manual que sigue pendiente.
{
"eventType": "PAYMENT_REMINDER_POST_EVENT",
"client": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "cliente@email.com",
"name": "Juan",
"lastName": "Pérez"
},
"reminder": {
"type": "post_failure",
"daysOffset": 2,
"billingDate": "2026-10-01 00:00:00+00"
}
}Campos de reminder
| Campo | Tipo | Descripción |
|---|---|---|
type | string | Qué clase de recordatorio es: pre_payment, post_failure o manual_payment |
daysOffset | number | Días de separación respecto a billingDate que configuraste para este recordatorio |
billingDate | string | Fecha de cobro a la que se refiere el recordatorio. Es una marca de tiempo con zona horaria, tal como se guarda, no una fecha suelta |
Los dos eventos se distinguen por el eventType, pero el type de adentro es más específico:
PAYMENT_REMINDER_POST_EVENT llega tanto con post_failure como con manual_payment. Si tratas
esos dos casos distinto, ramifica por reminder.type, no por el eventType.
Estos eventos no incluyen los objetos subscription, invoice ni payment.
GATEWAY_API_KEY_EXPIRING_EVENT
Evento a nivel de organización. Se envía cuando la API key del gateway de pago está próxima a vencer, como recordatorio para que la organización renueve sus credenciales antes de que dejen de funcionar.
Se emite por cada umbral de aviso configurado (por defecto 3 días y 1 día antes del vencimiento). Cada umbral se envía una sola vez por ventana de vencimiento; al renovar la key, los avisos vuelven a habilitarse para el nuevo período.
{
"eventType": "GATEWAY_API_KEY_EXPIRING_EVENT",
"organizationId": "wc8opaq1y1j5",
"configId": "550e8400-e29b-41d4-a716-446655440000",
"bankId": "660e8400-e29b-41d4-a716-446655440000",
"expiresAt": "2026-07-16T16:16:19.742Z",
"daysRemaining": 3
}Campos
| Campo | Tipo | Descripción |
|---|---|---|
organizationId | string | ID de la organización dueña de la configuración |
configId | string (UUID) | ID de la configuración del gateway (gateway_bank_config) |
bankId | string (UUID) | ID del banco asociado a la configuración |
expiresAt | string (ISO 8601) | Fecha y hora exacta de vencimiento de la API key |
daysRemaining | number | Días restantes hasta el vencimiento al momento del aviso |
Nota: El payload nunca incluye la
apiKeyni elapiSecret.
GATEWAY_API_KEY_EXPIRED_EVENT
Evento a nivel de organización. Se envía cuando la API key del gateway ya venció y el sistema la desactivó automáticamente. A partir de este momento, la organización no podrá procesar cobros hasta cargar credenciales nuevas.
{
"eventType": "GATEWAY_API_KEY_EXPIRED_EVENT",
"organizationId": "fse0srailt3v",
"configId": "550e8400-e29b-41d4-a716-446655440000",
"bankId": "660e8400-e29b-41d4-a716-446655440000",
"expiresAt": "2026-06-12T17:47:13.325Z"
}Campos
| Campo | Tipo | Descripción |
|---|---|---|
organizationId | string | ID de la organización dueña de la configuración |
configId | string (UUID) | ID de la configuración del gateway (gateway_bank_config) |
bankId | string (UUID) | ID del banco asociado a la configuración |
expiresAt | string (ISO 8601) | Fecha y hora en que la API key venció |
Nota: El payload nunca incluye la
apiKeyni elapiSecret. Además del webhook, la organización recibe un email a sus administradores y el equipo de Venflow recibe un aviso interno por Slack.
Orden de Eventos en un Checkout
Durante un flujo de checkout típico, los eventos se emiten en este orden:
1. USER_CREATE_EVENT → Cliente creado (solo si es nuevo)
2. SUBSCRIPTION_CREATE_EVENT → Suscripción activada
3. INVOICE_CREATE_EVENT → Factura generada
4. PAYMENT_SUCCESS_EVENT → Pago completado
5. INVOICE_UPDATE_EVENT → Factura marcada como pagadaFlujo de Error
PAYMENT_FAILED_EVENTpuede ocurrir en cualquier etapa del procesamiento de pago- Se pueden recibir múltiples
PAYMENT_FAILED_EVENTpara la misma transacción (reintentos) - Si el cobro falla definitivamente, se envía
INVOICE_UPDATE_EVENTcon estadouncollectibleseguido deSUBSCRIPTION_CANCELLED_EVENTcon razónpayment_failure
Valores de Estado
| Objeto | Campo | Valores Posibles |
|---|---|---|
subscription | status | active, past_due, pending, trialing, waiting_start, cancelled |
payment | status | pending, completed, failed |
invoice | status | open, paid, overdue, uncollectible, cancelled |
Qué significa cada estado de suscripción
| Estado | Significado |
|---|---|
trialing | Está en período de prueba. Todavía no se le ha cobrado nada. |
waiting_start | Tiene fecha de inicio futura. Aún no empieza a cobrarse. |
pending | Lista para cobrarse, pero todavía sin un cobro exitoso. |
active | Al día. |
past_due | Falló un cobro y se está reintentando. Sigue siendo cobrable. |
cancelled | Terminada. No se cobra más. |
Trata este campo como texto libre, no como una lista cerrada. La lista de arriba es la que
emitimos hoy, pero el estado interno tiene más valores y podemos empezar a exponer alguno nuevo.
Si tu código hace switch sobre status, incluye siempre una rama por defecto que no rompa —
en vez de asumir que el valor que llegó es uno de los seis.
Programar una cancelación no emite ningún webhook. Cuando cancelas al final del período, el
SUBSCRIPTION_CANCELLED_EVENT llega recién el día en que la cancelación se ejecuta, con
cancellationReason.type: "scheduled_cancellation". Si necesitas enterarte en el momento en que
se agenda, consulta GET /v1/subscriptions/{id} y mira cancel_at_period_end.