Eventos de webhook
INFI usa nombres de evento canónicos y estables. El nombre se entrega en el header X-Infi-Event y en el campo event del cuerpo, siempre en el mismo formato (minúsculas, con puntos).
Los nombres de evento listados abajo son estables entre versiones. Puedes compararlos directamente: if (req.headers['x-infi-event'] === 'transaction.paid') { ... }. Sin necesidad de normalización.
Cobros PIX (type: "transaction")
Eventos del ciclo de un cobro recibido.
| Evento | Cuándo ocurre |
|---|---|
transaction.paid | Pago confirmado y acreditado al saldo. |
transaction.failed | Falla en el pago (timeout, rechazo del pagador). |
transaction.cancelled | Cobro cancelado antes del pago. |
transaction.expired | Plazo expiró sin pago. |
transaction.refunded | Reembolso total. Saldo del comerciante debitado. |
transaction.partially_refunded | Reembolso parcial. |
transaction.infraction | MED (Mecanismo Especial de Devolución) abierto — saldo bloqueado preventivamente. |
transaction.dispute | Disputa abierta por el pagador. |
transaction.protest | Protesto registrado contra la transacción. |
transaction.blocked | Fondos bloqueados por orden judicial o compliance. |
transaction.chargeback | Chargeback aplicado — saldo debitado en definitivo. |
Retiros PIX (type: "transfer")
Eventos del ciclo de una transferencia (retiro) iniciada por tu API key o por el panel.
| Evento | Cuándo ocurre |
|---|---|
transfer.created | Retiro creado, esperando procesamiento. |
transfer.processing | Retiro en procesamiento en el banco. |
transfer.pending_approval | Retiro por encima del límite — espera aprobación manual interna. |
transfer.approved | Retiro aprobado manualmente, sigue al procesamiento. |
transfer.rejected | Retiro rechazado manualmente. Saldo devuelto. |
transfer.paid | Retiro concluido con éxito. |
transfer.failed | Retiro falló (clave PIX inválida, etc.). Saldo devuelto. |
transfer.cancelled | Retiro cancelado antes del procesamiento. Saldo devuelto. |
transfer.refunded | El destinatario devolvió el monto (PIX Reversal). Saldo reacreditado. |
transfer.partially_refunded | El destinatario devolvió parte. Saldo reacreditado proporcionalmente. |
Headers en cada POST
| Header | Descripción |
|---|---|
X-Infi-Event | Nombre canónico del evento (p.ej. transaction.paid). |
X-Infi-Timestamp | Timestamp Unix en segundos, parte de la firma. |
X-Infi-Signature | sha256=<hex> — HMAC-SHA256 sobre ${timestamp}.${rawBody}. Ver Firma. |
X-Infi-Event-Id | ID único del evento (evt_<ts>_<rand>). Úsalo para dedup entre múltiples URLs y reenvíos manuales. |
Campos opcionales (PIX)
En eventos donde el pago fue efectivamente liquidado, el webhook trae datos del PIX desde la red SPI/BACEN:
| Campo | Dónde aparece | Contenido |
|---|---|---|
endToEndId | transaction.paid / transaction.refunded / transaction.partially_refunded / transfer.paid / transfer.refunded / transfer.partially_refunded | E2E ID estándar BACEN (formato E<ISPB><YYYYMMDDhhmm><id>). Único por PIX. |
payer | transaction.* (PIX recibido — quién te pagó) | Objeto con name, document, documentType y bankAccount. |
beneficiary | transfer.* (PIX enviado — quién recibió tu retiro) | Objeto con name, document, documentType y bankAccount. |
refundEndToEndId | transfer.refunded / transfer.partially_refunded solamente | E2E ID del PIX de devolución (distinto del endToEndId del PIX original). |
Estructura de payer y beneficiary:
{
"name": "Maria Santos",
"document": "98765432100",
"documentType": "cpf",
"bankAccount": {
"ispb": "18236120",
"branch": "1",
"account": "914453272"
}
}Los campos payer.* y beneficiary.* contienen datos personales (nombre, CPF/CNPJ, cuenta bancaria). Trátalos como cualquier dato personal: guarda solo lo necesario, con acceso restringido, y respeta el derecho de eliminación del titular. INFI entrega esos datos porque vienen de la red PIX — tú eres el controlador del tratamiento posterior.
Eventos que no traen esos campos: transaction.failed, transaction.cancelled, transaction.expired, transfer.created, transfer.processing, transfer.pending_approval, transfer.approved, transfer.rejected, transfer.failed, transfer.cancelled. Los campos se omiten del JSON cuando no están disponibles (no vienen como null).
Ejemplo: transaction.paid
{
"event": "transaction.paid",
"eventId": "evt_1715000000000_abcdef12",
"transactionId": "Q4t9aV...",
"status": "paid",
"amountCents": 1000,
"feeCents": 8,
"netCents": 992,
"paidAt": "2026-05-08T03:30:00.000Z",
"timestamp": "1715000000",
"endToEndId": "E18236120202605080330abc123",
"payer": {
"name": "Maria Santos",
"document": "98765432100",
"documentType": "cpf",
"bankAccount": {
"ispb": "18236120",
"branch": "1",
"account": "914453272"
}
}
}Ejemplo: transaction.refunded
{
"event": "transaction.refunded",
"eventId": "evt_1715003600000_def456",
"transactionId": "Q4t9aV...",
"status": "refunded",
"amountCents": 1000,
"feeCents": 8,
"netCents": 992,
"paidAt": null,
"timestamp": "1715003600",
"endToEndId": "E18236120202605080330abc123",
"payer": {
"name": "Maria Santos",
"document": "98765432100",
"documentType": "cpf",
"bankAccount": {
"ispb": "18236120",
"branch": "1",
"account": "914453272"
}
}
}El monto del reembolso (parcial o total) se debita automáticamente de tu saldo INFI. Sin acción adicional.
transaction.partially_refundedtiene el mismo schema.
Ejemplo: transfer.paid
{
"event": "transfer.paid",
"eventId": "evt_1715000300000_345678ab",
"transactionId": "...",
"status": "paid",
"amountCents": 5000,
"feeCents": 4,
"netCents": 4996,
"paidAt": "2026-05-08T03:35:00.000Z",
"timestamp": "1715000300",
"endToEndId": "E04838403202605080335ABCDEF",
"beneficiary": {
"name": "João Silva",
"document": "12345678901",
"documentType": "cpf",
"bankAccount": {
"ispb": "18236120",
"branch": "0001",
"account": "123456789"
}
}
}Ejemplo: transfer.refunded (devolución de retiro)
{
"event": "transfer.refunded",
"eventId": "evt_1715004000000_999",
"transactionId": "...",
"status": "transfer_refunded",
"amountCents": 5000,
"feeCents": 4,
"netCents": 4996,
"paidAt": null,
"timestamp": "1715004000",
"endToEndId": "E04838403202605080335ABCDEF",
"refundEndToEndId": "D18236120202605080500abc789",
"beneficiary": {
"name": "João Silva",
"document": "12345678901",
"documentType": "cpf",
"bankAccount": {
"ispb": "18236120",
"branch": "0001",
"account": "123456789"
}
}
}Cuando el destinatario devuelve un PIX que enviaste, el saldo se reacredita automáticamente.
transfer.partially_refundedtiene el mismo schema conamountCentsigual al valor parcialmente devuelto.
Ejemplo: transfer.failed
{
"event": "transfer.failed",
"eventId": "evt_1715000600000_9abc1234",
"transactionId": "...",
"status": "failed",
"amountCents": 5000,
"feeCents": 4,
"netCents": 4996,
"paidAt": null,
"timestamp": "1715000600"
}En retiros que terminan en
failed,cancelledorejected, el saldo se devuelve automáticamente. Sin acción adicional de tu lado más allá de marcar la operación. Estos eventos no traenendToEndIdnibeneficiary(no hubo liquidación).
Categorías para multi-webhook
Puedes configurar una URL por categoría o mezclar a tu gusto usando filtros de evento. Ver Configurando para el setup completo.
| Categoría | Eventos cubiertos |
|---|---|
cashin (pagos) | transaction.paid, transaction.failed, transaction.cancelled, transaction.expired |
refund (reembolsos) | transaction.refunded, transaction.partially_refunded |
dispute (disputas / holds) | transaction.infraction, transaction.dispute, transaction.protest, transaction.blocked |
chargeback | transaction.chargeback |
cashout (retiros) | transfer.* (los 10 eventos) |