Catálogo de eventos
Los 20 tipos de evento que Vipter envía por webhook, cuándo se dispara cada uno y lo que viene en data.object, con un ejemplo completo de pedido, suscripción, cliente y checkout abandonado.
Todo evento llega en el mismo sobre. El tipo está en type y en el encabezado Vipter-Event-Type, y el objeto en data.object. Cada tipo pertenece a una familia, y la familia define el formato del objeto:
| Familia | Tipos | data.object.object |
|---|---|---|
| Pedidos | order.* (5) | "order" |
| Suscripciones | subscription.* (11) | "subscription" |
| Clientes | customer.* (2) | "customer" |
| Checkout abandonado | checkout.* (2) | "checkout_abandonment" |
Reglas que valen para todas las familias:
- Todos los campos listados en las tablas vienen siempre en el objeto. Cuando no hay valor, el campo viene
null, nunca ausente. La excepción es el evento de prueba. - Los montos de dinero vienen en centavos, como número entero:
19700es R$ 197,00. La moneda está en el campocurrencydel mismo objeto. - Las fechas dentro de
data.objectson texto ISO 8601. Elcreateddel sobre usa otro formato: segundos Unix. - Los IDs de los ejemplos son ficticios. Trata todo ID como texto opaco y no dependas del prefijo ni del tamaño.
- Un endpoint recibe solo los tipos marcados en él. Sin ninguno marcado, recibe todos, incluso los tipos que se creen en el futuro. Ignora con 2xx los tipos que tu sistema no usa.
Pedidos
| Evento | Cuándo se envía |
|---|---|
order.paid | Se aprobó el pago de un pedido: compra en el checkout (tarjeta aprobada o PIX, el pago instantáneo de Brasil, pagado), renovación de suscripción, upsell de 1 clic, venta con la tarjeta guardada hecha desde el panel, cobro extra en una suscripción, o pedido marcado como pagado por el equipo. |
order.failed | Se rechazó el cobro de un pedido. Sale una vez por pedido: los nuevos rechazos en el mismo pedido no generan otro evento. |
order.refunded | El pedido se reembolsó por completo, desde el panel, por el proveedor o marcado como reembolsado por el equipo. |
order.partially_refunded | Se reembolsó parte del pedido. Puede llegar más de una vez para el mismo pedido, una por cada reembolso parcial. |
order.charged_back | El comprador disputó la compra con el banco de la tarjeta (contracargo). |
Detalles que el código garantiza:
- Las renovaciones llegan como
order.paidconrecurrence: "subsequent"ysubscription_idcompletado, además delsubscription.renewedde la suscripción. - Estado manual. Cuando alguien del equipo marca el pedido como pagado o reembolsado, el evento sale con
status_source: "manual". Después de eso, los cambios que el proveedor informe sobre ese pedido no generan eventos. Consulta estado manual. - El estado del objeto es el actual. Un pedido que Vipter solo conoce después, por la sincronización periódica, puede generar
order.paidya con otrostatus, comorefunded. Leestatusen lugar de deducirlo por el tipo del evento. - El pedido no trae UTMs, origen de la campaña ni vendedor. Esos datos quedan en el panel.
El objeto order
| Campo | Tipo | Contenido |
|---|---|---|
object | texto | Siempre "order". |
id | texto | ID del pedido. |
customer_id | texto o null | ID del cliente. |
customer_email | texto o null | Correo del comprador. |
subscription_id | texto o null | Suscripción que generó el pedido, en las renovaciones y los cobros extra. |
status | texto | pending, pre_authorized, authorized, failed, canceled, refund_pending, partially_refunded, refunded o charged_back. Consulta estados de pedido. |
total_amount | entero | Total cobrado, en centavos. |
currency | texto | Código ISO 4217, como BRL. |
refunded_amount | entero o null | Total ya devuelto, en centavos. |
order_type | texto o null | checkout, renewal, api, trial_setup o card_setup. |
recurrence | texto o null | none (compra única), initial (primer cobro de una suscripción), subsequent (renovación) o unscheduled. |
offer_id | texto o null | Oferta del primer ítem. |
payment_method | texto o null | credit_card, debit_card, pix, boleto (boleto bancario de Brasil) o wallet. |
provider_slug | texto o null | Proveedor que procesó el pago, como pagarme. |
paid_at | fecha o null | Cuándo se aprobó el pago. |
items | lista | Los ítems del pedido. Consulta abajo. |
external_order_id | texto o null | Referencia externa del pedido, cuando existe. |
status_source | texto | manual cuando el equipo definió el estado en el panel, provider en los demás casos. |
created_at, updated_at | fecha o null | Creación y último cambio del pedido. |
downloads | lista | Solo en order.paid que no es renovación. Los enlaces de descarga del comprador. Lista vacía cuando el pedido no tiene productos con archivos. |
Cada ítem de items trae estos campos. Trata los campos adicionales como opcionales:
| Campo | Tipo | Contenido |
|---|---|---|
offer_id, offer_name | texto o null | Oferta vendida. |
product_id, product_name | texto o null | Producto de la oferta. |
billing_cycle | texto o null | Ciclo de la oferta. none para una venta única. |
quantity | entero | Unidades. En un paquete de 3, viene 3. |
unit_amount, total_amount | entero | Precio por unidad y total de la línea, en centavos. |
currency | texto | Moneda de la línea. |
installments | entero o null | Número de cuotas. |
role | texto | Cuando existe: main para el producto principal, bump para un order bump. Un ítem sin role es el producto principal. |
pack_label | texto | Cuando existe: el nombre del paquete vendido. |
bump_id | texto | Cuando existe: el order bump que generó la línea. |
Cada entrada de downloads trae product_id, product_name, expires_at (fecha o null) y files, una lista de { "name", "url" }. Los enlaces se abren en el dominio del checkout de la tienda y dejan de funcionar después de un reembolso o contracargo. Consulta entrega digital.
Ejemplo: order.paid
{
"id": "evt_3f9a1c7e5b2d4f6a8c0e1b3d",
"object": "event",
"type": "order.paid",
"created": 1790604191,
"livemode": true,
"api_version": "2026-09-01",
"data": {
"object": {
"object": "order",
"id": "ord_5c1e8a2b9d4f4e7a8b3c6d1e2f7a9b0c",
"customer_id": "cus_8b2d4f6a1c3e5a7b9d0f2e4c",
"customer_email": "ana.souza@example.com",
"subscription_id": null,
"status": "authorized",
"total_amount": 19700,
"currency": "BRL",
"refunded_amount": null,
"order_type": "checkout",
"recurrence": "none",
"offer_id": "ofr_a3454b7c008d455fbc5c3fc436c1879d",
"payment_method": "credit_card",
"provider_slug": "pagarme",
"paid_at": "2026-09-28T14:03:09.000Z",
"items": [
{
"offer_id": "ofr_a3454b7c008d455fbc5c3fc436c1879d",
"offer_name": "Acesso vitalício",
"product_id": "prd_5df6381e9a0b4c2d8e7f6a5b4c3d2e1f",
"product_name": "Curso de Fotografia",
"billing_cycle": "none",
"quantity": 1,
"unit_amount": 19700,
"total_amount": 19700,
"currency": "BRL",
"installments": 1
}
],
"external_order_id": null,
"status_source": "provider",
"created_at": "2026-09-28T14:02:51.000Z",
"updated_at": "2026-09-28T14:03:09.000Z",
"downloads": [
{
"product_id": "prd_5df6381e9a0b4c2d8e7f6a5b4c3d2e1f",
"product_name": "Curso de Fotografia",
"expires_at": null,
"files": [
{
"name": "Apostila.pdf",
"url": "https://pay.vipter.com/d/EXEMPLO-TOKEN/0b7e2c4a-9d1f-4e3b-8a6c-5f2d1e0c9b8a"
}
]
}
]
}
}
}Suscripciones
| Evento | Cuándo se envía |
|---|---|
subscription.created | Se creó una suscripción, normalmente por la compra de una oferta recurrente en el checkout. |
subscription.renewed | Se renovó la suscripción. El cobro de la renovación llega por separado, como order.paid. |
subscription.dunning | El cobro de la renovación falló y la suscripción entró en morosidad (status: "dunning"). |
subscription.reactivated | La suscripción volvió a estar activa: salió de la morosidad, o la reactivó el equipo o el suscriptor. |
subscription.upgraded | El suscriptor cambió de plan, a un monto mayor o igual al anterior. |
subscription.downgraded | El suscriptor cambió de plan, a un monto menor que el anterior. |
subscription.payment_method_changed | Se cambió la tarjeta usada en los cobros de la suscripción. |
subscription.paused | Se pausó la suscripción. |
subscription.resumed | La suscripción pausada volvió a estar activa. |
subscription.cancelled | Se canceló la suscripción. |
subscription.expired | La suscripción terminó (status: "expired"). |
Detalles que el código garantiza:
- Los cambios hechos por el equipo en el panel (cancelar, pausar, reanudar, reactivar, cambiar de plan) y por el suscriptor en el portal del cliente (cancelar, reactivar, cambiar de plan) generan el evento en el momento. El aviso del proveedor sobre el mismo cambio puede generar otro evento del mismo tipo, con otro
id. Consulta idempotencia. - Programar la cancelación para el final del período no genera un evento en el momento de programarla. El objeto pasa a tener
cancel_at_period_end: true, que aparece en el próximo evento de la suscripción. - En los cambios de plan desde el panel y desde el portal del cliente, Vipter compara
current_amountantes y después: mayor o igual se convierte ensubscription.upgraded, menor se convierte ensubscription.downgraded.
El objeto subscription
| Campo | Tipo | Contenido |
|---|---|---|
object | texto | Siempre "subscription". |
id | texto | ID de la suscripción. |
customer_id, customer_email, customer_name | texto o null | El suscriptor. |
status | texto | trialing, active, dunning, paused, cancelled o expired. |
current_offer_id, offer_name | texto o null | Plan actual. Cambia en un cambio de plan. |
product_id, product_name | texto o null | Producto del plan. |
billing_cycle | texto o null | daily, biweekly, monthly, quarterly, half_yearly, yearly o custom. |
currency | texto o null | Moneda de los cobros. |
current_amount | entero o null | Monto de cada cobro, en centavos. |
current_period_start, current_period_end | fecha o null | Período pagado actual. |
next_billing_at | fecha o null | Próximo cobro. |
trial_start, trial_end | fecha o null | Período de prueba gratis, cuando lo hubo. |
cycles_completed | entero o null | Ciclos ya cobrados. |
cycle_limit | entero o null | Número máximo de ciclos, o null si no hay límite. |
cancel_at_period_end | booleano o null | true cuando la cancelación está programada para el final del período. |
cancelled_at | fecha o null | Cuándo se canceló la suscripción. |
cancellation_reason | texto o null | Motivo informado en la cancelación. |
payment_instrument_id | texto o null | ID de la tarjeta guardada que se usa en los cobros. |
created_at, updated_at | fecha o null | Creación y último cambio de la suscripción. |
Ejemplo: subscription.renewed
{
"id": "evt_7d0b2e4f6a8c1e3b5d7f9a0c",
"object": "event",
"type": "subscription.renewed",
"created": 1790611502,
"livemode": true,
"api_version": "2026-09-01",
"data": {
"object": {
"object": "subscription",
"id": "sub_23e6db9f0a1b4c5d8e7f6a5b4c3d2e1f",
"customer_id": "cus_8b2d4f6a1c3e5a7b9d0f2e4c",
"customer_email": "ana.souza@example.com",
"customer_name": "Ana Souza",
"status": "active",
"current_offer_id": "ofr_0c9b8a7f6e5d4c3b2a1f0e9d8c7b6a5f",
"offer_name": "Plano mensal",
"product_id": "prd_1a2b3c4d5e6f4a7b8c9d0e1f2a3b4c5d",
"product_name": "Clube de Receitas",
"billing_cycle": "monthly",
"currency": "BRL",
"current_amount": 4990,
"current_period_start": "2026-09-28T16:05:00.000Z",
"current_period_end": "2026-10-28T16:05:00.000Z",
"next_billing_at": "2026-10-28T16:05:00.000Z",
"trial_start": null,
"trial_end": null,
"cycles_completed": 4,
"cycle_limit": null,
"cancel_at_period_end": false,
"cancelled_at": null,
"cancellation_reason": null,
"payment_instrument_id": "pi_4e6a8c0b2d4f6a8c0e2b4d6f",
"created_at": "2026-05-28T16:05:00.000Z",
"updated_at": "2026-09-28T16:05:02.000Z"
}
}
}Clientes
| Evento | Cuándo se envía |
|---|---|
customer.created | Vipter registró un cliente nuevo: agregado por el equipo en el panel, o visto por primera vez en una suscripción o en la sincronización periódica con el proveedor. |
customer.updated | Alguien del equipo editó el cliente en el panel. Cada vez que se guarda el formulario, sale un evento. |
No cuentes con customer.created para enterarte de cada comprador nuevo: no sale en todos los caminos de compra. Para reaccionar a una compra, usa order.paid, que trae customer_id y customer_email. Los cambios que el comprador hace en el portal del cliente, como el nombre y el teléfono, no generan customer.updated.
El objeto customer
| Campo | Tipo | Contenido |
|---|---|---|
object | texto | Siempre "customer". |
id | texto | ID del cliente. |
email | texto | Correo. |
name | texto o null | Nombre. |
phone | texto o null | Teléfono, como +5511987654321. |
document_type | texto o null | cpf, cnpj, passport o tax_id. CPF y CNPJ son los números de contribuyente de Brasil para personas y empresas. El número del documento no viene en el evento. |
metadata | objeto o null | Metadatos del cliente. |
created_at, updated_at | fecha o null | Creación y último cambio. |
Ejemplo: customer.created
{
"id": "evt_1c3e5a7b9d0f2e4c6a8b0d2f",
"object": "event",
"type": "customer.created",
"created": 1790604190,
"livemode": true,
"api_version": "2026-09-01",
"data": {
"object": {
"object": "customer",
"id": "cus_8b2d4f6a1c3e5a7b9d0f2e4c",
"email": "ana.souza@example.com",
"name": "Ana Souza",
"phone": "+5511987654321",
"document_type": "cpf",
"metadata": null,
"created_at": "2026-09-28T14:02:50.000Z",
"updated_at": "2026-09-28T14:02:50.000Z"
}
}
}El evento de prueba
El botón Enviar evento de prueba crea un customer.created con un objeto reducido. Tiene solo estos campos y "test": true:
{
"object": "customer",
"id": "cust_test",
"email": "test@example.com",
"name": "Test Customer",
"test": true,
"created_at": "2026-09-28T14:10:00.000Z"
}Descarta los eventos con data.object.test === true antes de grabar cualquier cosa. Cada clic crea un evento nuevo, con otro id. Consulta Reintentos, desactivación y reenvío.
Checkout abandonado
| Evento | Cuándo se envía |
|---|---|
checkout.abandoned | El comprador completó el correo en el checkout, no intentó pagar y quedó sin actividad. El registro se crea después de 15 minutos sin actividad, y el evento sale 60 minutos después del registro, si no compró en el intervalo. La verificación se ejecuta cada 10 minutos, así que el horario real varía. Sale una vez por registro. |
checkout.recovered | Un checkout abandonado cuyo checkout.abandoned ya había salido terminó en una compra pagada del mismo comprador y del mismo producto, hasta 7 días después del abandono. |
Una tarjeta rechazada y un PIX generado y no pagado no cuentan como abandono. Varias visitas del mismo comprador al mismo producto se convierten en un solo registro, con session_count mayor que 1. Las reglas completas están en Recuperación de checkout abandonado.
El objeto checkout_abandonment
| Campo | Tipo | Contenido |
|---|---|---|
object | texto | Siempre "checkout_abandonment". |
id | texto | ID del registro de abandono. Es el mismo en los dos eventos. |
customer | objeto | id (null si el comprador todavía no es cliente), email, name, phone y country. |
offer_id, offer_name | texto o null | Oferta del checkout. |
product_id, product_name | texto o null | Producto de la oferta. |
quantity | entero | Unidades: el tamaño del paquete, o 1. |
pack_label | texto o null | Nombre del paquete, cuando el enlace era de un paquete. |
amount | entero o null | Monto del producto que vio el comprador, con el precio del paquete, antes de cupones y envío. En centavos. |
currency | texto o null | Moneda del checkout. |
locale | texto o null | Idioma en que estaba el checkout, como pt. |
utm | objeto o null | Los parámetros utm_source, utm_medium, utm_campaign, utm_content, utm_term y utm_id que vinieron con el comprador. |
referrer | texto o null | Página desde donde llegó el comprador. |
checkout_session_id | texto | Sesión de checkout más reciente. |
session_count | entero | Cuántas visitas se juntaron en este registro. |
recovery_url | texto | Enlace que vuelve a abrir el checkout con los datos del comprador completados. Consulta enlace de recuperación. |
first_seen_at | fecha | Inicio de la primera visita. |
abandoned_at | fecha | Cuándo se registró el abandono. |
checkout.recovered trae el mismo objeto y cuatro campos más:
| Campo | Tipo | Contenido |
|---|---|---|
resolution | texto | Siempre "recovered". |
order_id | texto | El pedido pagado que cerró el abandono. |
resolved_at | fecha | Cuándo se cerró el abandono. |
recovered_by_link | booleano | true si el comprador abrió el recovery_url antes de comprar. |
Ejemplo: checkout.abandoned
{
"id": "evt_9e1a3c5e7b9d0f2a4c6e8b0d",
"object": "event",
"type": "checkout.abandoned",
"created": 1790609400,
"livemode": true,
"api_version": "2026-09-01",
"data": {
"object": {
"object": "checkout_abandonment",
"id": "6f1d2c3b-4a5e-4f6a-9b8c-7d6e5f4a3b2c",
"customer": {
"id": null,
"email": "bruno.lima@example.com",
"name": "Bruno Lima",
"phone": "+5521998765432",
"country": "BR"
},
"offer_id": "ofr_7b8c9d0e1f2a4b3c8d7e6f5a4b3c2d1e",
"offer_name": "Kit 3 unidades",
"product_id": "prd_9f8e7d6c5b4a4f3e8d2c1b0a9f8e7d6c",
"product_name": "Chá Detox",
"quantity": 3,
"pack_label": "Kit com 3",
"amount": 24900,
"currency": "BRL",
"locale": "pt",
"utm": {
"utm_source": "instagram",
"utm_medium": "stories",
"utm_campaign": "black-friday"
},
"referrer": "https://l.instagram.com/",
"checkout_session_id": "cs_2b4d6f8a0c2e4a6b8d0f2a4c",
"session_count": 2,
"recovery_url": "https://pay.vipter.com/kit-cha?pack=3&rec=EXEMPLO-TOKEN",
"first_seen_at": "2026-09-28T13:12:40.000Z",
"abandoned_at": "2026-09-28T13:40:05.000Z"
}
}
}Qué hacer después
- Entiende los campos del sobre y cómo tratar las repeticiones.
- Verifica la firma antes de procesar cualquier evento.
Visión general para desarrolladores
Lo que puedes integrar con Vipter hoy (webhooks firmados, parámetros de URL del checkout, el script de UTMs y esta documentación en Markdown), lo que no existe y por dónde empezar.
Formato del sobre
La solicitud que Vipter hace a tu endpoint, campo por campo, con los encabezados, el plazo de respuesta, cómo tratar los eventos repetidos y lo que Vipter garantiza sobre el orden.