WebhooksRecurrencia
Webhook de recurrencia
Esta página describe el formato del webhook enviado por la plataforma siempre que haya una actualización en una recurrencia o en uno de sus cobros.
Descripción
El webhook de recurrencia se envía automáticamente siempre que el estado de la recurrencia o de un cobro cambia, permitiendo que el sistema del integrador acompañe todo el ciclo, desde la creación hasta la cancelación.
El envío va a los webhooks de tipo Suscripciones registrados en el panel y a la notificationUrl que usted informó en la creación.
Estándar de Zona Horaria
Todos los campos de fecha y hora enviados en los webhooks utilizan el estándar ISO 8601 en la zona horaria UTC (UTC+00:00), garantizando consistencia independientemente de la zona horaria del integrador. Para evitar discrepancias causadas por horarios locales o cambios de horario de verano, se recomienda mantener los valores en UTC para almacenamiento y procesamiento, realizando la conversión a la zona horaria local solo a nivel de presentación.
Validación Opcional del Webhook
Para aumentar la seguridad, los webhooks registrados directamente en el panel pueden incluir una firma enviada en el header X-Signature: <firma-en-base64>, permitiendo validar la autenticidad de la notificación recibida. Esta firma es generada por la plataforma utilizando HMAC con SHA-256 sobre el cuerpo del webhook, en formato JSON, usando un secreto compartido WEBHOOK_SECRET y codificada en Base64. El integrador puede reproducir el mismo cálculo en su sistema usando el mismo secreto y el payload recibido. Si la firma generada coincide con la enviada en el header, el webhook se considera legítimo e íntegro. Si son diferentes, la solicitud puede haber sido alterada o no enviada por la plataforma.
Esta validación está disponible solo para webhooks registrados en el panel. Los webhooks enviados a una URL informada dinámicamente mediante notificationUrl no incluyen la firma X-Signature.
La validación por firma es opcional, pero altamente recomendada siempre que el webhook sea configurado desde el panel para garantizar mayor seguridad en la comunicación.
Endpoint de Notificación
Si se informa, el webhook se enviará a la URL configurada en el campo notificationUrl al crear la recurrencia.
El endpoint debe estar accesible públicamente y responder con HTTP 200 para confirmar la recepción de la notificación.
Además, las notificaciones de recurrencia también pueden ocurrir vía webhook in-bound, registrado en el panel con el tipo Suscripciones. Un webhook registrado como Pagos no recibe evento de recurrencia.
Estado de la recurrencia
Los posibles valores para el campo status son:
- PENDING – Recurrencia creada, esperando la autorización del pagador o el primer cobro.
- ACTIVE – Primer cobro pagado. En tarjeta puede ocurrir ya en la creación; en Pix Automático, en el primer ciclo.
- CANCELLED – Recurrencia finalizada. No se genera ningún cobro nuevo.
- FAILED – La adquirente rechazó la tarjeta en la creación. La recurrencia no llega a existir para ella.
Estado del cobro
Los posibles valores para el campo invoice.status son:
- SCHEDULED – Cobro agendado para el ciclo, aún no cobrado.
- PAID – Cobro pagado. El importe entra en su saldo.
- REJECTED – Cobro rechazado en definitiva. La recurrencia se cancela junto.
Cómo se relacionan los dos
El cuerpo no tiene campo de evento. Cuando el campo invoice viene nulo, el aviso es sobre la recurrencia. Cuando viene con datos, es sobre un cobro.
El estado de la recurrencia es consecuencia de los cobros:
| El cobro llega como | La recurrencia queda |
|---|---|
| SCHEDULED | Sin cambio |
| PAID (el primero) | ACTIVE |
| PAID (los siguientes) | Sigue ACTIVE |
| REJECTED | CANCELLED |
To pick up a draggable item, press the space bar. While dragging, use the arrow keys to move the item. Press space again to drop the item in its new position, or press escape to cancel.
La recurrencia también se cancela sin pasar por ningún cobro: cuando el pagador rechaza la autorización, cuando usted llama a la ruta de cancelación y cuando el contrato se cancela o pausa en el panel de la adquirente. En los tres el aviso llega con invoice nulo, y el cobro que estaba agendado termina junto, sin aviso propio.
El mismo aviso puede llegar más de una vez, y el agendamiento y el pago de un ciclo comparten el mismo invoice.id. Para no procesar dos veces, use id + status + invoice.id + invoice.status.
Formato del payload
El cuerpo es el mismo en todos los eventos. Lo que cambia son los campos status e invoice.
{
"id": "recr_01HXYZ123ABC456DEF789",
"amount": 9900,
"currency": "BRL",
"method": "PIXAUTOMATIC",
"status": "ACTIVE",
"description": "Assinatura mensal",
"options": {
"frequency": "MONTHLY",
"freqInterval": 1,
"maxPeriods": null
},
"customer": {
"name": "John Doe",
"taxId": "12345678900",
"email": "john.doe@example.com",
"phone": "11999990000"
},
"pix": {
"emv": "00020101021226850014br.gov.bcb.pix2563api.gateway.test/pix/123e4567-e89b-12d3-a456-4266141740005204000053039865802BR6304ABCD",
"retryPolicy": "THREE_RETRIES_7_DAYS"
},
"card": null,
"invoice": {
"id": "rinv_01HXYZ987ZYX654",
"amount": 9900,
"status": "PAID",
"e2e": "E1234567890123456789012345678901",
"refusedMsg": null,
"periodNumber": 1,
"periodStart": "2026-01-05",
"periodEnd": "2026-02-05",
"paidAt": "2026-01-05T10:15:10.000Z",
"cancelledAt": null,
"lastTryAt": "2026-01-05T10:15:08.000Z",
"createdAt": "2026-01-05T10:12:33.120Z",
"updatedAt": "2026-01-05T10:15:10.000Z"
},
"orderId": null,
"cancelledAt": null,
"externalRef": "order_123456",
"notificationUrl": "https://example.com/webhook/recurrency",
"metadata": null,
"createdAt": "2026-01-05T10:12:33.120Z",
"updatedAt": "2026-01-05T10:15:10.000Z"
}{
"id": "recr_01HXYZ123ABC456DEF789",
"amount": 4990,
"currency": "BRL",
"method": "CREDIT_CARD",
"status": "CANCELLED",
"description": "Assinatura mensal",
"options": {
"frequency": "MONTHLY",
"freqInterval": 1,
"maxPeriods": null
},
"customer": {
"name": "John Doe",
"taxId": "12345678900",
"email": "john.doe@example.com",
"phone": "11999990000"
},
"pix": null,
"card": {
"brand": "VISA",
"holder": "JOHN DOE",
"number": "411111******1111",
"refusedMsg": null
},
"invoice": {
"id": "rinv_01HXYZ987ZYX654",
"amount": 4990,
"status": "REJECTED",
"e2e": null,
"refusedMsg": "Cartão sem limite disponível.",
"periodNumber": 4,
"periodStart": "2026-04-05",
"periodEnd": "2026-05-05",
"paidAt": null,
"cancelledAt": "2026-04-12T18:45:10.532Z",
"lastTryAt": "2026-04-12T18:45:10.000Z",
"createdAt": "2026-01-05T10:12:33.120Z",
"updatedAt": "2026-04-12T18:45:10.532Z"
},
"orderId": null,
"cancelledAt": "2026-04-12T18:45:10.532Z",
"externalRef": "order_123456",
"notificationUrl": "https://example.com/webhook/recurrency",
"metadata": null,
"createdAt": "2026-01-05T10:12:33.120Z",
"updatedAt": "2026-04-12T18:45:10.532Z"
}¿Algo mal en esta página? Habla con nosotros