Webhooks

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 → partially_paid → paid). Como el nombre del evento es siempre el mismo, tu handler decide qué hacer según data.status.

{
  "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.
  • reference es tu referencia externa de la orden (la que enviaste al crearla); puede venir vacía ("").
  • No hay campo event_id, paid_at, refunded_at ni reason. Para deduplicar usa la tupla (hash, status, updated_at).

Estados de data.status

statusSignificado
pendingOrden creada, aún sin pago. También es el estado del primer order.changed (el de la creación).
partially_paidSe capturó la cuota del 30% pero el préstamo todavía no está completamente aprobado.
paidOrden completamente pagada. Para AAPD dispara cuando el préstamo se aprueba (30% y 70% liquidados en los libros de SkipPay). Trátalo como la confirmación autoritativa del pago.
partially_refundedSe reembolsó una parte de la orden.
refundedSe reembolsó la orden completa.
cancelledLa orden se canceló antes del pago. Raro en AAPD — usualmente solo vía intervención del equipo de Skip.

Idempotencia

El mismo estado de una orden puede llegar más de una vez (por ejemplo, tu endpoint hizo timeout pero el procesamiento original tuvo éxito y SkipPay reintentó). Haz tu handler idempotente deduplicando por (data.hash, data.status, data.updated_at): 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ía refunded_amount, refunded_at, reason).
  • order.failed — la solicitud de préstamo falla o el paciente cancela (incluiría reasonloan_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).

On this page