Skip to content

Webhooks ​

Los eventos se entregan por HTTP POST a sus endpoints activos.

Catálogo de eventos ​

typecuándo
payment.succeededpago confirmado
payment.settledpago liquidado — planeado, aún no se dispara (hoy no hay confirmación automática de liquidación; ver Liquidación)
payment.cancelledpago cancelado
payment.failedpago rechazado

Internamente, payment.captured se entrega públicamente como payment.succeeded. payment.authorized no genera webhook.

Envelope ​

json
{
  "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), weekend y holiday (con country y name). Un array vacío significa que la fecha cayó directo, sin ajustes.
  • No hay campo de "D+N". Use estimated_date; el reason explica el camino. No sume días por su cuenta.
  • Fuera de la cobertura del calendario, el objeto settlement se 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.succeeded trae la previsión; la plataforma no emite hoy un evento que confirme que el crédito efectivamente ocurrió en estimated_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):

js
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_lettered y 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 cada id una 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:

json
{
  "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.succeeded de 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.succeeded de 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.