Los webhooks notifican a tu aplicación en tiempo real cuando ocurren eventos — pagos, cambios de suscripción, reembolsos y más.
Para activar webhooks para tu cuenta, dentro de tu cuenta de Recurrente, ve a:
Configuración → Desarrolladores y API.
Ahí haz clic en “Webhooks”, y continúa a añadir el endpoint a donde quieres que sean enviados los requests.
Los webhooks no se envían para checkouts creados con llaves de test (pk_test_* / sk_test_*). En modo test, los pagos con la tarjeta 4242 4242 4242 4242 se aprueban directamente sin pasar por el flujo completo de procesamiento, por lo que no se generan eventos de webhook.
Para probar tu integración de webhooks de punta a punta, necesitas usar llaves de producción (pk_live_* / sk_live_*) con una tarjeta real.
Recurrente envía webhooks para los siguientes eventos:
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:
Cobro fallido con tarjeta.
Ejemplo de respuesta:
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:
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.
Se emite cuando se pausa la suscripción. Una suscripción pausada no se volverá a cobrar hasta que sea reactivada.
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.
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.
Se emite con un cobro exitoso con transferencia bancaria. Los fondos ya están en tu balance de Recurrente.
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.
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.
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.
Se emite con un cobro exitoso pagado con el balance de Recurrente del cliente. Los fondos ya están en tu balance. Este evento llega a la cuenta del comercio (la que cobró).
Se emite a la cuenta del pagador (la cuenta cuyo balance fue debitado) cuando paga exitosamente un checkout usando su balance de Recurrente. Solo lo recibes si configuraste un endpoint de webhook en la cuenta pagadora.
Nota: un mismo cobro con balance dispara dos webhooks independientes: balance_intent.succeeded al comercio y balance_intent.paid al pagador. El payload sigue la misma estructura que bank_transfer_intent.succeeded (incluye checkout, payment, customer, amount_in_cents, currency, product, tax_invoice_url).
Cada POST del webhook incluye un cuerpo JSON con los datos del evento. La estructura varía según el tipo de evento.
Si tu endpoint no responde con un código 2xx, Recurrente reintentará enviar el webhook:
Cada webhook enviado por Recurrente incluye una firma para que puedas verificar que es auténtico y no ha sido alterado. Recomendamos fuertemente verificar las firmas en producción.
Cada endpoint de webhook tiene un signing secret único. Lo puedes encontrar en el dashboard de Svix — accesible desde Configuración → Desarrolladores y API → Webhooks en tu cuenta de Recurrente. El secret tiene el formato whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw.
La forma más fácil de verificar firmas es usando las librerías de verificación de webhooks de Svix, disponibles para muchos lenguajes:
Debes usar el body crudo del request al verificar webhooks. Si parseas el JSON y lo re-serializas, la verificación de firma fallará.
Cada request de webhook incluye tres headers:
Paso 1. Construye el contenido firmado concatenando el svix-id, svix-timestamp, y el body crudo del request, separados por puntos:
Paso 2. Decodifica la porción en base64 de tu signing secret (todo después de whsec_) y úsalo como llave para un hash HMAC-SHA256 del contenido firmado:
Paso 3. Compara tu firma calculada con la del header svix-signature. El valor del header tiene el prefijo v1, — quita ese prefijo antes de comparar. Usa una comparación de tiempo constante para prevenir ataques de timing.
Paso 4. Opcionalmente, verifica que el svix-timestamp esté dentro de unos minutos del tiempo actual de tu servidor para prevenir ataques de replay.