Saltearse al contenido

Eventos disponibles

Cada evento tiene un tipo que llega en el header X-Ingalca-Event-Type y en la clave event del body. Suscribite al que necesites filtrando en tu handler.

Eventos de pagos

EventoCuándo se dispara
payment.confirmedEl pago se completó con éxito (tarjeta aprobada en Dinelco/Bancard, o transferencia aprobada).
payment.failedEl provider rechazó el pago (tarjeta inválida, fondos insuficientes, etc.).
payment.rejectedUn operador rechazó manualmente un comprobante de transferencia.
payment.expiredEl pago no se completó antes de expires_at y se marcó expirado. Ver Expiración y confirmaciones tardías.
payment.cancelledVos cancelaste el pago vía API antes de su finalización.
payment.reversedSe ejecutó una reversa del pago (Dinelco o Bancard, antes del corte de liquidación).
payment.receipt_uploadedEl cliente subió un comprobante de transferencia (pendiente de aprobación).

Eventos de tarjetas

EventoCuándo se dispara
card.registeredEl catastro fue exitoso, ya tenés tokenId para cobrar.
card.failedEl catastro falló (tarjeta rechazada, OTP incorrecto).
card.deletedSe eliminó una tarjeta: por DELETE /v1/cards/{id} (borrado lógico) o por reemplazo automático al re-catastrar la misma tarjeta.

Estructura del body

Payload por evento

payment.*

{
"event": "payment.confirmed",
"payment_id": "pay_abc123def456",
"reference": "ORDEN-001",
"checkout_session_id": null,
"provider": "transferencia",
"payment_method": "transferencia",
"environment": "live",
"status": "confirmed",
"amount": "150000.00",
"currency": "PYG",
"customer_id": "user_42",
"metadata": { "order_id": 1042 },
"rejection_reason": null,
"provider_data": {
"operation_number": "0012345",
"authorization_number": "123456",
"response_code": "00"
},
"confirmed_at": "2026-05-02T14:32:10+00:00",
"failed_at": null,
"expires_at": "2026-05-02T14:50:00+00:00",
"expired_at": null,
"confirmed_after_expiry": false,
"recovered_from_status": null,
"created_at": "2026-05-02T14:30:00+00:00",
"timestamp": "2026-05-02T14:32:11+00:00"
}
CampoNotas
amountString decimal, no entero: "150000.00". Casteá antes de comparar.
environmentlive o test, según la API key con la que se creó el pago.
provider_dataDatos del proveedor para ese intento (operation_number, authorization_number, response_code, provider_status, session_id). Solo trae las claves con valor.
rejection_reasonEn payment.rejected, el motivo del rechazo manual del comprobante. En declines de tarjeta, el código + detalle del proveedor.
expires_atEl plazo del intento: hasta cuándo lo aceptamos. null si el pago no vence.
expired_atCuándo lo marcamos expirado. Ojo con el par de nombres: uno es el plazo, el otro el hecho consumado.
confirmed_after_expiryVer abajo.
recovered_from_statusVer abajo.
timestampMomento del envío de este intento de entrega, no del evento.

Si el pago nació de un checkout hospedado, checkout_session_id trae el cs_... de la sesión, payment_method el método usado, y reference es el de tu orden (el de la sesión) — no el interno del intento. Una sesión puede generar varios payment_id; conciliá por reference y deduplicá por X-Ingalca-Event-Id.

Para payment.reversed, vas a recibir el evento aún cuando la reversa la disparaste vos por API — el webhook confirma la transición de estado.

card.*

{
"event": "card.registered",
"card_id": "card_xyz789",
"customer_id": "user_42",
"provider": "dinelco",
"status": "registered",
"masked_number": "411111******1096",
"brand": "Visa",
"card_type": "credit",
"expiration": "12/30",
"created_at": "2026-05-02T14:32:10+00:00",
"last_synced_at": "2026-05-02T14:32:10+00:00",
"timestamp": "2026-05-02T14:32:11+00:00"
}

Expiración y confirmaciones tardías

Un pago con expires_at deja de ofrecerse cuando vence: cerramos la página hospedada, negamos la carga de nuevos iframes y rechazamos nuestros propios endpoints. Cuando eso pasa recibís payment.expired, con expired_at poblado.

Cuando una confirmación aterriza sobre un pago que ya habíamos dado por perdido, llega un payment.confirmed normal con dos campos que lo distinguen:

  • confirmed_after_expirytrue si el pago se confirmó después de su expires_at, o si se rescató de un estado no abierto.
  • recovered_from_status — el estado del que se lo rescató (expired, cancelled, failed), o null si venía en curso normalmente.
{
"event": "payment.confirmed",
"payment_id": "pay_abc123def456",
"reference": "ORDEN-1042",
"status": "confirmed",
"expires_at": "2026-05-02T14:50:00+00:00",
"expired_at": null,
"confirmed_after_expiry": true,
"recovered_from_status": "expired"
}

Qué hacer con eso depende de tu negocio. Si tenés stock, cupo o precio con vigencia, un confirmed_after_expiry: true significa que el pago entró fuera de la ventana que reservaste: el cupo pudo haberse liberado y revendido, o el precio pudo haber cambiado. Lo habitual es rutear esos casos a revisión manual en vez de despachar automático, y revertir el pago si ya no lo podés honrar.

Si tu flujo no tiene reservas por tiempo, podés ignorar los dos campos y tratarlo como cualquier payment.confirmed.

Cómo elegir qué escuchar

  • Si solo procesás pagos one-shot: payment.confirmed + payment.failed alcanzan.
  • Si aceptás transferencias: sumá payment.receipt_uploaded para enterarte cuando llegan, payment.rejected para los rechazos manuales.
  • Si trabajás con tarjetas guardadas: sumá card.registered y card.failed.
  • Si tenés política de devoluciones: sumá payment.reversed.

No hay forma (todavía) de filtrar qué eventos te llegan. Recibís todos y filtrás del lado tuyo. Si hay demanda, agregamos suscripciones por tipo.