Webhooks
Los eventos se entregan por HTTP POST a sus endpoints activos.
Catálogo de eventos
| type | cuándo |
|---|---|
payment.succeeded | pago confirmado |
payment.settled | pago liquidado — planeado, aún no se dispara (hoy no hay confirmación automática de liquidación; ver Liquidación) |
payment.cancelled | pago cancelado |
payment.failed | pago rechazado |
Internamente, payment.captured se entrega públicamente como payment.succeeded. payment.authorized no genera webhook.
Envelope
{
"id": "evt_9f8c...", "type": "payment.succeeded", "created": 1789990000,
"data": {
"payment": {
"id": "pay_9f8c...",
"amount": 510000,
"currency": "BRL",
"gross_amount": 510000,
"gross_currency": "BRL",
"fee_amount": 25000,
"fee_currency": "BRL",
"net_amount": 95000,
"net_currency": "USD",
"payment_method": "pix",
"status": "succeeded",
"reference": "pedido-123",
"failure_code": null,
"fx": {
"rate": 5.1,
"base": "USD",
"quote": "BRL",
"locked_at": 1800000000,
"valid_until": null,
"rate_history_id": 123
},
"settlement": {
"estimated_date": "2026-09-08",
"reason": [
{ "type": "cutoff", "note": "..." },
{ "type": "weekend", "date": "2026-09-05" },
{ "type": "holiday", "date": "2026-09-07", "country": "BR", "name": "..." }
]
}
}
}
}El payload público nunca incluye spot_rate, cobertura_centibps, source, median_3_stablecoin, percent_centibps ni porcentajes de regla.
Liquidación (settlement)
Presente solo en payment.succeeded. Dice cuándo debe caer el dinero y por qué esa fecha — para que usted cierre la caja sin recalcular el calendario bancario (BR/Febraban + US/Fedwire), el corte de las 15h (America/Sao_Paulo) y el rodaje de fin de semana por su cuenta.
estimated_date(AAAA-MM-DD, America/Sao_Paulo) es una ESTIMACIÓN, no una garantía. Refleja las reglas de calendario vigentes al momento de la confirmación.reason[]es el rastro cronológico de lo que movió la fecha:cutoff(pagado después de las 15h),weekendyholiday(concountryyname). Un array vacío significa que la fecha cayó directo, sin ajustes.- No hay campo de "D+N". Use
estimated_date; elreasonexplica el camino. No sume días por su cuenta. - Fuera de la cobertura del calendario, el objeto
settlementse omite — nunca enviamos una fecha sin cobertura. Trate la ausencia como "sin previsión", no como error. - No existe evento de confirmación de liquidación.
payment.succeededtrae la previsión; la plataforma no emite hoy un evento que confirme que el crédito efectivamente ocurrió enestimated_date. No asuma confirmación automática — si necesita conciliar el crédito real, hágalo desde su extracto bancario.
Firma
Cada entrega lleva el header:
Pagooz-Signature: t=1789990000,v1=<hex>v1 es el HMAC-SHA256, en hex, de "{t}.{body}" (el timestamp, un punto y el cuerpo bruto de la solicitud), usando el secret del endpoint. Verifique y rechace entregas cuyo t esté a más de 5 minutos del momento actual (tolerancia de replay).
Ejemplo funcional (Node):
const crypto = require("crypto");
function verifyPagoozSignature(rawBody, header, secret) {
const parts = Object.fromEntries(header.split(",").map((kv) => kv.split("=")));
const t = Number(parts.t);
if (!t || Math.abs(Date.now() / 1000 - t) > 300) return false; // 5 min
const expected = crypto.createHmac("sha256", secret)
.update(`${t}.${rawBody}`).digest("hex");
const a = Buffer.from(expected), b = Buffer.from(parts.v1 || "");
return a.length === b.length && crypto.timingSafeEqual(a, b);
}Entrega, retry e idempotencia del consumidor
- Una entrega solo tiene éxito con una respuesta
2xx. - Una falla dispara 5 intentos con backoff: inmediato, 1 minuto, 5 minutos, 30 minutos y 2 horas.
- Después de la 5ª falla, la entrega queda
dead_letteredy visible en el cockpit. - Entrega al menos una vez. El mismo evento puede llegar más de una vez (retry, renotificación, reentrega). Su consumidor debe ser idempotente por
event.id— procese cadaiduna sola vez.
Configuración en el cockpit
Una URL por tenant por entorno (sandbox y live). El cockpit lee el modo global de la sesión y guarda la URL de ese entorno. El secret de firma se muestra una sola vez, al crear/rotar. La tabla webhook_endpoints no se usa en esta versión; queda reservada para múltiples destinos en el futuro.
Conciliación y renotificación
Reenvío manual en el cockpit
El merchant puede reenviar una entrega fallida desde el cockpit. El payload reenviado mantiene el mismo event_id; el nuevo intento se registra en webhook_deliveries con origin = "manual".
Historial de entregas
El cockpit muestra las últimas entregas por entorno. Cada objeto:
{
"id": "whd_9f8c...", "event_id": "evt_9f8c...",
"attempt": 3, "status": "failed", "http_status": 503,
"response_body": "...",
"origin": "auto", "created": 1789990000, "next_attempt_at": 1789990300
}Le permite diagnosticar por su cuenta por qué una notificación no llegó.
Transferencia bancaria (TED) — confirmación por conferencia
Un cobro pagado por transferencia bancaria no se confirma por sistema: el pagador envía el comprobante en el checkout y Poolvo verifica la recepción antes de dar el cobro por pagado. Eso cambia lo que usted debe esperar como integrador:
- El
payment.succeededde una transferencia llega después de la conferencia, no en el momento en que el pagador dice que pagó. Entre una cosa y otra pueden pasar horas, y la conferencia ocurre en horario comercial. No trate la demora como falla ni reemita el cobro. - Mientras espera conferencia, el pago existe y no cuenta como pagado: no suma en su cierre de período y no genera webhook.
- El rechazo en la conferencia (comprobante que no cuadra) llega como
payment.failed. - Cuando el pago se confirma, el webhook es el mismo
payment.succeededde PIX y tarjeta, con los mismos campos. Usted no necesita tratamiento propio por método.
payment_methods en POST /v1/payment_links acepta pix y card. El cobro por transferencia bancaria se crea por el flujo de cotización (POST /v1/quotes con payment_method: "ted", y luego aceptando la cotización), y el objeto Payment devuelve payment_method: "ted" normalmente.
La liquidación se confirma fuera de la API
La previsión de liquidación viene en el payment.succeeded (ver Webhooks → Liquidación). La confirmación de que el crédito ocurrió la registra Poolvo por conferencia manual, y no está expuesta en la API hoy: no existe evento ni campo de estado de liquidación en el objeto Payment. payment.settled sigue planificado. Si necesita conciliar el crédito real, use su extracto bancario — no espere una notificación nuestra.