Webhooks

Webhooks

Los webhooks notifican a tu aplicación en tiempo real cuando ocurren eventos — pagos, cambios de suscripción, reembolsos y más.

Configurar Webhooks

Vía Dashboard

Para activar webhooks para tu cuenta, dentro de tu cuenta de Recurrente, ve a:

ConfiguraciónDesarrolladores y API.

Ahí haz clic en “Webhooks”, y continúa a añadir el endpoint a donde quieres que sean enviados los requests.

Vía API

$curl -X POST https://app.recurrente.com/api/webhook_endpoints \
> -H "X-PUBLIC-KEY: ..." \
> -H "X-SECRET-KEY: ..." \
> -H "Content-Type: application/json" \
> -d '{
> "url": "https://tusitio.com/webhooks/recurrente",
> "description": "Webhook de producción"
> }'

Tipos de Eventos Webhook

Recurrente envía webhooks para los siguientes eventos:

payment_intent.succeeded

Se emite con un cobro exitoso con tarjeta (crédito o débito). Los fondos ya están en tu balance de Recurrente.

Ejemplo de respuesta:

1{
2 "id": "pa_id123",
3 "event_type": "payment_intent.succeeded",
4 "api_version": "2024-04-24",
5 "checkout": {
6 "id": "ch_id123",
7 "status": "paid",
8 "payment": {
9 "id": "pa_laybj3zw",
10 "paymentable": {
11 "type": "OneTimePayment",
12 "id": "on_arognqni",
13 "tax_name": null,
14 "tax_id": null,
15 "address": null,
16 "phone_number": null
17 }
18 },
19 "payment_method": {
20 "id": "pay_m_7v5ie3pw",
21 "type": "card",
22 "card": {
23 "last4": "4242",
24 "network": "visa"
25 }
26 },
27 "transfer_setups": [],
28 "metadata": {}
29 },
30 "created_at": "2024-02-16T03:01:13.260Z",
31 "failure_reason": null,
32 "amount_in_cents": 10000,
33 "currency": "GTQ",
34 "fee": 450,
35 "vat_withheld": 160,
36 "vat_withheld_currency": "GTQ",
37 "customer": {
38 "email": "hello@example.com",
39 "full_name": "Max Rodriguez",
40 "id": "us_id123"
41 },
42 "product": {
43 "id": "prod_id123"
44 },
45 "invoice": {
46 "id": "inv_123",
47 "tax_invoice_url": null
48 }
49}

payment_intent.failed

Cobro fallido con tarjeta.

Ejemplo de respuesta:

1{
2 "id": "pa_id123",
3 "event_type": "payment_intent.failed",
4 "api_version": "2024-03-13",
5 "checkout": {
6 "id": "ch_id123"
7 },
8 "created_at": "2024-02-16T03:01:13.260Z",
9 "failure_reason": "Tu banco ha rechazado la transacción. Llama a tu banco y pide que autoricen esta transacción.",
10 "amount_in_cents": 10000,
11 "currency": "GTQ",
12 "fee": 0,
13 "vat_withheld": 0,
14 "vat_withheld_currency": "GTQ",
15 "customer": {
16 "email": "hello@example.com",
17 "full_name": "Max Rodriguez",
18 "id": "us_id123"
19 },
20 "product": {
21 "id": "prod_id123"
22 }
23}

subscription.create

Si el producto es recurrente, se emite además del payment.succeeded este evento con la información de la suscripción.

Ejemplo de respuesta:

1{
2 "api_version": "2024-04-24",
3 "created_at": "2025-10-13T13:59:27.931Z",
4 "customer_email": "example@example.com",
5 "customer_id": "us_1234",
6 "customer_name": "Pedro Pérez",
7 "event_type": "subscription.create",
8 "id": "su_123",
9 "payment": {
10 "id": "pa_123",
11 "paymentable": {
12 "address": null,
13 "id": "su_123",
14 "phone_number": "+50255555555",
15 "tax_id": "",
16 "tax_name": null,
17 "type": "Subscription"
18 }
19 },
20 "product": {
21 "address_requirement": "none",
22 "billing_info_requirement": "optional",
23 "cancel_url": "",
24 "custom_terms_and_conditions": "Términos y condiciones",
25 "description": "Suscripción de prueba",
26 "has_dynamic_pricing": false,
27 "id": "prod_123",
28 "metadata": {},
29 "name": "Plan de Prueba",
30 "phone_requirement": "required",
31 "prices": [
32 {
33 "amount_in_cents": 999,
34 "billing_interval": "month",
35 "billing_interval_count": 1,
36 "charge_type": "recurring",
37 "currency": "GTQ",
38 "free_trial_interval": "month",
39 "free_trial_interval_count": 0,
40 "id": "price_123",
41 "periods_before_automatic_cancellation": null
42 }
43 ],
44 "status": "active",
45 "storefront_link": "https://app.recurrente.com/s/recurrente/plan-de-prueba",
46 "success_url": ""
47 }
48}

subscription.past_due

Se emite cuando el cobro automático de una suscripción falla por primera vez.

Nota: En una suscripción, cuando un pago falla, Recurrente intenta cobrarlo de nuevo 3 y 5 días después. Si ambos re-intentos son fallidos, en ese momento se cancela la suscripción.

subscription.paused

Se emite cuando se pausa la suscripción. Una suscripción pausada no se volverá a cobrar hasta que sea reactivada.

subscription.cancel

Se emite cuando el cobro automático de una suscripción falla por tercera vez.

Nota: En una suscripción, cuando un pago falla, Recurrente intenta cobrarlo de nuevo 3 y 5 días después. Si ambos re-intentos son fallidos, en ese momento se cancela la suscripción.

bank_transfer_intent.pending

Se emite cuando se inicia un cobro con transferencia bancaria. En cuanto se reciba el dinero en la cuenta, se emitirá bank_transfer_intent.succeeded. De lo contrario, se emitirá bank_transfer_intent.failed.

bank_transfer_intent.succeeded

Se emite con un cobro exitoso con transferencia bancaria. Los fondos ya están en tu balance de Recurrente.

bank_transfer_intent.failed

Se emite con un cobro fallido con transferencia bancaria. Esto sucede cuando no se reciben los fondos en la cuenta de banco, o se recibe el monto incorrecto.

setup_intent.succeeded

Se emite cuando se inicia exitosamente una suscripción con un período de prueba. También se emite cuando se tokeniza una tarjeta sin cobrarla.

setup_intent.cancelled

Se emite cuando no se logra tokenizar una tarjeta sin cobrarla. Esto sucede cuando el primer pago de una suscripción con período de prueba, falla.

Payload del Webhook

Cada POST del webhook incluye un cuerpo JSON con los datos del evento. La estructura varía según el tipo de evento.

Mejores Prácticas

  • Retorna 2xx rápidamente — Confirma la recepción antes de hacer procesamiento pesado
  • Maneja duplicados — Los webhooks pueden ser entregados más de una vez; usa el ID del evento para idempotencia
  • Verifica la fuente — Valida que las solicitudes vengan de los servidores de Recurrente
  • Procesa de forma asíncrona — Usa una cola para procesamiento pesado después de confirmar recepción

Reintentos

Si tu endpoint no responde con un código 2xx, Recurrente reintentará enviar el webhook:

  • Inmediatamente después del primer fallo
  • 1 minuto después
  • 5 minutos después
  • 30 minutos después
  • 2 horas después
  • 6 horas después