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). 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 the transaction’s source or destination is an external crypto wallet, that
source /
destination object also includes an onChainTransaction (transactionHash + network,
e.g. SOLANA) once the crypto transfer settles — use it to match the transfer on a
block explorer. The hash can land shortly after the terminal status, so a terminal webhook
payload may not include it yet; retrieve the transaction (GET /transactions/{id}) to read
it 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.