Handling webhooks
Listen for transaction webhooks to track transaction status change until a terminal state is reached.Expected terminal statuses for outgoing transactions:
COMPLETED, FAILED, EXPIRED. However, transitions between these can occur (e.g., a bank return moves COMPLETED → FAILED, and destination.railDetails.status moves to RETURNED). Also listen for OUTGOING_PAYMENT.REFUND_COMPLETED and OUTGOING_PAYMENT.REFUND_FAILED to track refunds on failed transactions.- Outbound transactions: The originating account is debited at transaction creation. If the transaction ultimately fails, a refund is posted back to the originating account.
- Inbound transactions: The receiving account is credited only on success. Failures do not change balances.
1
Subscribe and verify signatures
Configure your webhook endpoint and verify signatures. See Webhooks.Sample webhook payload:
When funds move over an external rail, that
source / destination object includes a
railDetails describing the transfer. Its paymentRail determines the fields: an
ONCHAIN transfer carries transactionHash + network (e.g. SOLANA) to match on a block
explorer, an ACH transfer carries its traceNumber, a WIRE carries its imad,
and RTP / FEDNOW transfers carry their endToEndId. Rail identifiers can land shortly
after the terminal status, so a terminal webhook payload may not include them yet; retrieve
the transaction (GET /transactions/{id}) to read them once settled.2
Process events idempotently
Use the envelope
id, data.id, and timestamp to ensure idempotent handling, updating your internal ledger on each status transition.3
Recognize terminal states
When a transaction reaches a terminal state, finalize your reconciliation for that transaction.
Reconcile via queries
Additionally, you can list transactions for a time window and compare with your internal records.We recommend querying days from
00:00:00.000 to 23:59:59.999 in your preferred timezone.cURL
Troubleshooting
- Missing webhook: Check delivery logs in the dashboard and ensure your endpoint returns
2xx. Retries continue for 7 days. - Mismatched balances: Re-query the date range and verify terminal statuses; remember outbound failures are refunded, inbound failures do not change balances.
- Pagination gaps: Always follow
nextCursoruntilhasMoreisfalse.