Catálogo de eventos
El evento de webhook que Skip emite hoy, con su esquema de payload y los estados de orden.
Todo payload de webhook tiene la forma:
{
"event": "order.changed",
"data": { /* la orden y su estado */ }
}event identifica el tipo. Hoy Skip emite un único tipo, order.changed; el resultado concreto de la orden viaja en data.status. data matchea el schema de abajo.
order.changed
Se dispara cuando se crea una orden y en cada cambio posterior de su estado (por ejemplo pending → paid). Como el nombre del evento es siempre el mismo, tu handler decide qué hacer según data.status.
Los cambios internos de la orden que no alteran su estado (cobros de la 2ª cuota, cobro de comisiones, liquidación al prestador) no generan webhooks.
{
"event": "order.changed",
"data": {
"hash": "2f88b330-f3ed-5521-aa1f-9d15af1fce8d",
"reference": "CLINIC-ORDER-12345",
"status": "paid",
"total_amount": 100000,
"paid_amount": 100000,
"pending_amount": 0,
"created_at": "2026-04-15T10:00:00Z",
"updated_at": "2026-04-15T10:15:00Z",
"customer": {
"rut": "12345678-9",
"first_name": "María",
"last_name": "González",
"email": "maria@example.com"
}
}
}Notas sobre el payload:
- Los montos (
total_amount,paid_amount,pending_amount) son numéricos, no strings. referencees tu referencia externa de la orden (la que enviaste al crearla); puede venir vacía ("").- No hay campo
event_id,paid_at,refunded_atnireason. Para deduplicar usa la tupla(hash, status)— ver Idempotencia.
Estados de data.status
Los estados que se emiten hoy:
status | Significado |
|---|---|
pending | Orden creada, aún sin pago. Es el estado del primer order.changed (el de la creación). |
paid | Orden completamente pagada en los libros de SkipPay. Para AAPD dispara al completar el checkout: el 30% se capturó y el préstamo por el 70% quedó autorizado — Skip asume el cobro posterior al paciente. Se emite exactamente una vez por orden; trátalo como la confirmación autoritativa del pago. El cobro efectivo del 70% (aprobación ISAPRE, cobro anticipado) es interno de Skip y no re-emite este evento. |
refunded | Se reembolsó la orden completa. |
Estados definidos en el schema pero que hoy no se emiten (no construyas flujos que los esperen):
status | Significado reservado |
|---|---|
partially_paid | Pago parcial de la orden. |
partially_refunded | Reembolso parcial de la orden. |
cancelled | Orden cancelada antes del pago. |
Idempotencia
Skip crea a lo más una notificación paid por orden. Aun así, la misma notificación puede entregarse más de una vez (por ejemplo, tu endpoint hizo timeout pero el procesamiento original tuvo éxito y SkipPay reintentó — en ese caso el payload es idéntico). Haz tu handler idempotente deduplicando por (data.hash, data.status): si ya procesaste esa combinación, trátala como no-op.
No hay señal de abandono o rechazo
Hoy no existe un evento que avise que el paciente abandonó el flujo o que el préstamo fue rechazado — la orden simplemente se queda en pending y no llega ningún order.changed nuevo. Detéctalo por ausencia de un order.changed con status = paid dentro de tu ventana esperada, o consultando el estado de la orden por API. Ver Webhooks de AAPD → Abandono y fallos.
Eventos internos que no se envían a partners
Skip maneja varios eventos internos (intentos de cobro de la 2ª cuota, financiamiento del préstamo) que no se envían a partners. Skip los agrega y los refleja como cambios en el data.status del order.changed.
Roadmap de eventos granulares
Lo de esta sección todavía no se emite. El contrato vigente es el order.changed de arriba. Se documenta como diseño-objetivo; no integres contra estos eventos hasta que este aviso se retire.
Esto todavía no se emite. A futuro Skip planea emitir eventos con nombre por tipo de transición, en lugar de un único order.changed:
order.paid— orden completamente pagada.order.partially_paid— 30% capturado, préstamo en trámite.order.refunded— reembolso total o parcial (incluiríarefunded_amount,refunded_at,reason).order.failed— la solicitud de préstamo falla o el paciente cancela (incluiríareason∈loan_rejected,loan_canceled,card_declined,customer_canceled). Esto cubriría la señal de abandono/rechazo que hoy no existe.order.cancelled— orden cancelada explícitamente antes del pago.
Cuando esto se implemente, esta página se actualizará con los payloads definitivos y el mecanismo de idempotencia (event_id).