Webhooks — conceptos
Los webhooks son el mecanismo por el cual Max Pay notifica eventos al ERP del integrador en tiempo casi real. Sin webhooks, la única alternativa sería hacer polling, lo cual es ineficiente y latente.
Esta página cubre el modelo conceptual. Para implementar (crear endpoint, verificar firma HMAC, hacer test delivery), ver Empezar con webhooks. Para la referencia operativa (endpoints, pausar/reanudar, rotar secret), ver Webhooks → Configuración. Para el catálogo de eventos, ver Eventos.
Modelo
Si el endpoint del integrador no responde 2xx dentro de 10 segundos, Max Pay reintenta con backoff exponencial.
Entrega
Cada evento se envía como POST al URL configurado con:
Headers
| Header | Descripción |
|---|---|
X-MaxPay-Signature | Firma HMAC. Ver verificación |
X-MaxPay-Event | Tipo del evento. Ej: receivable.created |
X-MaxPay-Delivery-Id | UUID de esta entrega (cambia entre retries del mismo evento) |
Body
{
"id": "evt_b3f8a1c2d4e5f6789012345678901234",
"type": "receivable.created",
"createdAt": "2026-05-15T14:30:05-03:00",
"data": {
"receivable": { "id": 1234, "amount": 45000, "..." : "..." }
}
}
Los eventos son inmutables. Si la data subyacente cambia (ej. el comprobante se actualiza), se emite un evento nuevo (receivable.updated), no se modifica el original.
Verificación de firma
Toda entrega lleva la firma X-MaxPay-Signature:
X-MaxPay-Signature: t=1715812800,v1=5257a869e7ecebeda...
Donde:
t: Unix timestamp del momento de firma (mismo valor queX-MaxPay-Timestamp).v1: HMAC-SHA256 calculado sobre<timestamp>.<body>con elsecretdel webhook como clave.
El integrador debe recalcular el HMAC con su secret y compararlo en tiempo constante. Además, conviene rechazar entregas con timestamp viejo (típicamente > 5 minutos) para evitar replay attacks.
Para una implementación completa con código de ejemplo, ver Empezar con webhooks.
Sin verificar, cualquier atacante con tu URL pública puede inyectar eventos falsos en tu ERP. La verificación es la diferencia entre una integración robusta y un vector de ataque.
Reintentos
Si el endpoint responde algo distinto de 2xx, Max Pay reintenta con el siguiente cronograma:
| Intento | Demora desde el anterior |
|---|---|
| 1 | (inmediato) |
| 2 | 1 minuto |
| 3 | 5 minutos |
| 4 | 30 minutos |
| 5 | 2 horas |
| 6 | 12 horas |
Total: ~14 horas desde el evento original. Pasado ese plazo, la entrega se descarta y el webhook queda como FAILED. Para diagnosticar y reenviar entregas fallidas, ver Diagnóstico de entregas.
Deduplicación de eventos
Por el modelo "at-least-once" del retry, el integrador puede recibir el mismo evento más de una vez. El event.id es único e inmutable para cada evento, y se mantiene constante entre reintentos del mismo evento. La estrategia estándar es persistir los event.id ya procesados y descartar (respondiendo 200 OK) los que ya estén en la lista.
Para el patrón de implementación, ver Empezar con webhooks.
Orden y concurrencia
Los eventos cercanos en el tiempo pueden llegar fuera de orden por concurrencia interna. El integrador no debe asumir secuencia entre eventos distintos (ej. receivable.created puede llegar después de receivable.paid si los reintentos del primero se atrasaron).
Para handling de rollbacks: una transacción revertida se notifica como un movement.created con operationType: ROLLBACK que referencia al movement original. La lógica de conciliación del integrador debe contemplar este caso.