Webhooks de suscripción
OrcaRail envía eventos de webhook sobre el ciclo de vida y la facturación de las suscripciones. Usa el mismo endpoint de webhook y la misma verificación de firmas que con los Payment Intents; los eventos de suscripción tienen la misma forma de payload: type y data.object.
Tipos de evento
| Evento | Descripción |
|---|---|
subscription.created | Se ha creado la suscripción |
subscription.updated | Se ha actualizado la suscripción |
subscription.canceled | Se ha cancelado la suscripción (de inmediato o al final del periodo) |
subscription.paused | Se ha pausado la suscripción |
subscription.resumed | Se ha reanudado la suscripción en pausa |
subscription.trial_will_end | La prueba termina en 3 días (recordatorio) |
subscription.payment_link.created | Se ha creado el enlace de pago de un ciclo |
subscription.payment_link.paid | Pago del ciclo confirmado (enlace pagado o cobro automático correcto) |
subscription.payment_link.payment_failed | Ha fallado el cobro automático de este ciclo |
subscription.past_due | La suscripción ha pasado a past_due (pago vencido o fallido) |
subscription.completed | Se han completado todos los ciclos (se alcanzó total_cycles) |
Estructura del payload
Todos los eventos de suscripción siguen la misma estructura:
{
"type": "subscription.payment_link.paid",
"data": {
"object": {
"id": "sub_550e8400e29b41d4a716446655440000",
"object": "subscription",
"status": "active",
"collection_method": "send_payment_link",
"amount": "10.00",
"currency": "usd",
"description": "Monthly Pro Plan",
"interval": "month",
"interval_count": 1,
"total_cycles": 12,
"completed_cycles": 3,
"current_period_start": "2025-03-01T00:00:00Z",
"current_period_end": "2025-04-01T00:00:00Z",
"latest_payment_link": {
"id": "...",
"status": "completed",
"link": "..."
},
"metadata": {},
"created": "2025-01-01T00:00:00Z",
"updated": "2025-03-15T00:00:00Z"
}
}
}
data.object es el objeto de suscripción completo (consulta la visión general). En subscription.payment_link.paid o subscription.payment_link.created, puedes usar data.object.latest_payment_link para el enlace del ciclo actual.
Ejemplo de gestor
const subscriptionHandlers = {
'subscription.created': (event) => {
console.log('New subscription:', event.data.object.id)
},
'subscription.updated': (event) => {
console.log('Subscription updated:', event.data.object.id)
},
'subscription.canceled': (event) => {
const sub = event.data.object
console.log('Canceled:', sub.id, sub.canceled_at)
},
'subscription.payment_link.paid': (event) => {
const sub = event.data.object
// Fulfill access for this cycle, extend license, etc.
console.log('Cycle paid:', sub.id, 'cycle', sub.completed_cycles)
},
'subscription.payment_link.payment_failed': (event) => {
const sub = event.data.object
// Notify payer, retry logic, or downgrade
console.log('Auto-charge failed:', sub.id)
},
'subscription.past_due': (event) => {
console.log('Past due:', event.data.object.id)
},
'subscription.completed': (event) => {
console.log('All cycles done:', event.data.object.id)
},
'subscription.trial_will_end': (event) => {
const sub = event.data.object
console.log('Trial ending soon:', sub.id, sub.trial_end)
},
}
// In your webhook route:
if (event.type.startsWith('subscription.')) {
const handler = subscriptionHandlers[event.type]
if (handler) await handler(event)
}
Idempotencia
Como con todos los webhooks, los eventos pueden entregarse más de una vez. Usa event.type + event.data.object.id (y opcionalmente el ID del ciclo o del enlace) para eliminar duplicados y procesar cada evento una sola vez.
Próximos pasos
- Visión general de webhooks: configuración del endpoint y verificación de firmas
- Eventos de webhook: eventos de Payment Intent
- Gestionar suscripciones: actualiza y cancela desde tu backend