Webhook events

INFI uses canonical, stable event names. The name is delivered in the X-Infi-Event header and in the body’s event field, always in the same format (lowercase, dot-separated).

Compare by exact equality

The event names listed below are stable across versions. You can compare directly: if (req.headers['x-infi-event'] === 'transaction.paid') { ... }. No normalization needed.

PIX charges (type: "transaction")

Events of the lifecycle of an incoming charge.

EventWhen it occurs
transaction.paidPayment confirmed and credited to balance.
transaction.failedPayment failure (timeout, payer refusal).
transaction.cancelledCharge cancelled before payment.
transaction.expiredDeadline expired with no payment.
transaction.refundedFull refund. Merchant balance debited.
transaction.partially_refundedPartial refund.
transaction.infractionMED (Special Refund Mechanism) opened — balance preventively blocked.
transaction.disputeDispute opened by the payer.
transaction.protestProtest registered against the transaction.
transaction.blockedFunds blocked by court order or compliance.
transaction.chargebackChargeback applied — balance permanently debited.

PIX withdrawals (type: "transfer")

Events of the lifecycle of a transfer (withdrawal) initiated by your API key or via the dashboard.

EventWhen it occurs
transfer.createdWithdrawal created, awaiting processing.
transfer.processingWithdrawal being processed at the bank.
transfer.pending_approvalWithdrawal over the limit — awaits manual internal approval.
transfer.approvedWithdrawal manually approved, moves to processing.
transfer.rejectedWithdrawal manually rejected. Balance returned.
transfer.paidWithdrawal successfully completed.
transfer.failedWithdrawal failed (invalid PIX key, etc.). Balance returned.
transfer.cancelledWithdrawal cancelled before processing. Balance returned.
transfer.refundedRecipient returned the amount (PIX Reversal). Balance re-credited.
transfer.partially_refundedRecipient returned part of the amount. Balance re-credited proportionally.

Headers on every POST

HeaderDescription
X-Infi-EventCanonical event name (e.g., transaction.paid).
X-Infi-TimestampUnix timestamp in seconds, part of the signature.
X-Infi-Signaturesha256=<hex> — HMAC-SHA256 over ${timestamp}.${rawBody}. See Signature.
X-Infi-Event-IdUnique event ID (evt_<ts>_<rand>). Use for dedup across multiple URLs and manual resends.

Optional fields (PIX)

For events where the payment was actually settled, the webhook carries PIX data from the SPI/BACEN network:

FieldWhere it appearsContent
endToEndIdtransaction.paid / transaction.refunded / transaction.partially_refunded / transfer.paid / transfer.refunded / transfer.partially_refundedBACEN-standard E2E ID (format E<ISPB><YYYYMMDDhhmm><id>). Unique per PIX.
payertransaction.* (PIX in — who paid you)Object with name, document, documentType and bankAccount.
beneficiarytransfer.* (PIX out — who received your withdrawal)Object with name, document, documentType and bankAccount.
refundEndToEndIdtransfer.refunded / transfer.partially_refunded onlyE2E ID of the refund PIX (different from the endToEndId of the original PIX).

Structure of payer and beneficiary:

{
  "name": "Maria Santos",
  "document": "98765432100",
  "documentType": "cpf",
  "bankAccount": {
    "ispb": "18236120",
    "branch": "1",
    "account": "914453272"
  }
}
Privacy (LGPD)

The payer.* and beneficiary.* fields contain personal data (name, CPF/CNPJ, bank account). Treat them as any personal data: store only what’s necessary, with restricted access, and respect the holder’s right to deletion. INFI delivers this data because it comes from the PIX network — you are the controller for subsequent processing.

Events that do not carry these fields: transaction.failed, transaction.cancelled, transaction.expired, transfer.created, transfer.processing, transfer.pending_approval, transfer.approved, transfer.rejected, transfer.failed, transfer.cancelled. The fields are omitted from the JSON when unavailable (not returned as null).

Example: 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"
    }
  }
}

Example: 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"
    }
  }
}

The refund amount (partial or full) is automatically debited from your INFI balance. No additional action needed. transaction.partially_refunded has the same schema.

Example: 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"
    }
  }
}

Example: transfer.refunded (withdrawal return)

{
  "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"
    }
  }
}

When the recipient returns a PIX you sent, the balance is automatically re-credited. transfer.partially_refunded has the same schema with amountCents equal to the partially returned amount.

Example: transfer.failed

{
  "event": "transfer.failed",
  "eventId": "evt_1715000600000_9abc1234",
  "transactionId": "...",
  "status": "failed",
  "amountCents": 5000,
  "feeCents": 4,
  "netCents": 4996,
  "paidAt": null,
  "timestamp": "1715000600"
}

For withdrawals ending in failed, cancelled or rejected, the balance is automatically returned. No action on your side beyond marking the operation. These events do not carry endToEndId or beneficiary (no settlement happened).

Categories for multi-webhook

You can configure one URL per category or mix as you like using event filters. See Configuring for full setup.

CategoryCovered events
cashin (payments)transaction.paid, transaction.failed, transaction.cancelled, transaction.expired
refund (refunds)transaction.refunded, transaction.partially_refunded
dispute (disputes / holds)transaction.infraction, transaction.dispute, transaction.protest, transaction.blocked
chargebacktransaction.chargeback
cashout (withdrawals)transfer.* (all 10 events)