Escrow notifications use an
event_id, event, created_at, data envelope with
persistent retries and tenant-scoped replay. Deduplicate by event ID and verify the
CaaS signature. See escrow webhooks.Payments webhooks
Configure your endpoint
Set your webhook URL (and enable wallet/deposit events) in the Payments dashboard under Developers → Webhooks. The dashboard shows your signing secret (whsec_…) once — store
it to verify signatures.
Headers on every delivery
Events & exact payloads
There are two payload shapes: checkout/remittance events are flat; wallet (WaaS) events wrap the data in anevent + data envelope.
- payment.confirmed / payment.failed
- wallet.deposit.detected
- wallet.deposit.confirmed
- wallet.deposit.hash_resolved
- wallet.transfer.*
Sent for Crypto Gateway checkout sessions. Flat payload:
network, tx_hash, paid_at and metadata are omitted when not applicable.
payment.failed carries the same shape with status: "failed" and no paid_at.Deposit data — field reference
Verify the signature
Compute the HMAC over the raw body and compare in constant time:Test it
Send a test event and rotate your signing secret from the Payments dashboard (Developers → Webhooks). Rotating invalidates the old secret — update your verifier immediately.CaaS webhooks
Register your webhook endpoints and choose which events to receive from your CaaS dashboard.Delivery & verification (every event)
Every webhook is an HTTPPOST with a JSON body and these headers:
Signature verification (Node)
Conventions
- Delivery is best-effort — settlement already happened on-chain; the notification
never blocks it. Only webhooks subscribed to that event type receive it. Return
2xx. - Amounts are decimal strings with 6 dp (e.g.
"5.000000"). tx_hashis the real on-chain transaction identifier, never an internal operation ID. EVM events use an EVM hash; native TRON USDT and Solana SPL events also include the same native identifier intx_id(network: "mainnet"for TRON andnetwork: "mainnet-beta"for Solana).- Timestamps are RFC3339 UTC.
- On
*.settled/*.failed, empty fields are omitted, not null (reasonabsent on success;amount_*/token/tx_hashabsent on a pre-broadcast failure). Treat missing = unknown.
Transaction events
- transfer.received
- transfer.settled
- transfer.failed
- swap.settled
- swap.failed
Fires when a wallet belonging to your business receives funds (incl. cross-merchant).
Not sent if the recipient is an unaffiliated phone — they get an SMS instead. Delivered
to the recipient merchant.For a confirmed native TRON USDT deposit, the same event is emitted after a solidified
TRC-20 For a finalized Solana USDC or USDT deposit, the same durable receipt event is emitted
after the scanner stores the balance delta. This requires Solana receipt monitoring to be
enabled for your Rach environment; readiness confirms that configuration, not scanner-worker
progress or a specific delivery. It is also delivered to every current wallet member.
Deduplicate on
Transfer log. Deduplicate on transfer_id; it is the durable deposit ID, not merely
the transaction hash. amount_usdc remains only for compatibility with older consumers — use
amount together with token: "USDT" as the authoritative amount and asset.transfer_id: the Solana signature is an audit reference, but one chain
transaction can contain more than one credit.Account / membership events
Best practices
- Respond fast (
2xx) then work async — Rach retries non-2xxdeliveries. - Be idempotent — dedupe on
X-Webhook-ID(Payments, ordeposit_idfor deposits). - Credit only when safe — for deposits, wait for
safe_to_credit: true.

