Concepto
Cada vez que un pago cambia de estado, INGALCA Pay le pega un POST a la URL que tengas configurada con un payload firmado. Esto te permite reaccionar al cambio en tu sistema sin tener que hacer polling.
Diagrama del flow
sequenceDiagram
participant Cliente
participant TuApp as Tu app
participant Ingalca as INGALCA Pay
participant Provider as Provider (Dinelco)
TuApp->>Ingalca: POST /v1/payments
Ingalca->>Provider: Crear sesión
Provider-->>Ingalca: OK + session_id
Ingalca-->>TuApp: pay_xxx (status=pending)
TuApp-->>Cliente: Mostrar checkout
Cliente->>Provider: Completar pago
Provider-->>Ingalca: Callback (server-to-server)
Ingalca->>Ingalca: Marcar payment confirmed
Note over Ingalca,TuApp: Acá entra el webhook
Ingalca->>TuApp: POST tu-url + firma HMAC
TuApp-->>Ingalca: 200 OK
TuApp-->>Cliente: Pantalla de éxito
Configurar tu URL
Vas a Configuración → Webhooks en el dashboard. Hay una URL por entorno:
webhook_url_test— recibe eventos de pagos creados consk_test_....webhook_url_live— recibe eventos de pagos creados consk_live_....
Tener URLs separadas es importante: querés que tu staging reciba los webhooks test y tu prod los live, sin mezclar.
Qué recibís
Un POST con Content-Type: application/json. Headers críticos:
| Header | Para qué |
|---|---|
X-Ingalca-Signature | Firma HMAC-SHA256 del body. Verificala siempre. |
X-Ingalca-Timestamp | Unix timestamp del envío. Sirve para evitar replays. |
X-Ingalca-Event-Id | ID único del evento. Usalo para idempotencia. |
X-Ingalca-Event-Type | Tipo del evento (payment.confirmed, etc.). |
Body de ejemplo:
{ "event_id": "evt_a1b2c3d4e5f6", "event_type": "payment.confirmed", "created_at": "2026-05-02T14:32:11+00:00", "data": { "payment_id": "pay_abc123def456", "reference": "ORDEN-001", "amount": 150000, "currency": "PYG", "status": "confirmed", "provider": "transferencia", "customer_id": "user_42", "confirmed_at": "2026-05-02T14:32:10+00:00" }}Qué tenés que hacer
- Verificar la firma antes de confiar en el payload. Cómo verificar →
- Responder rápido — devolvenos
2xxen menos de 10 segundos. Si te tomamos más tiempo, marcamos timeout y reintentamos. - Hacer la operación idempotente — el mismo evento puede llegar más de una vez. Cómo manejarlo →
Códigos de respuesta esperados
| Tu respuesta | Qué hacemos |
|---|---|
2xx | OK, marcamos como delivered. |
4xx | No reintentamos. Algo está mal en tu config — revisá tu URL/handler. |
5xx o timeout | Reintentamos con backoff (1m, 5m, 30m, 2h, 12h). Ver reintentos. |