data so you can act without a follow-up GET.
Setup
- Open Settings → Developers → Webhooks
- Set a URL for live and/or sandbox
- Subscribe to event types from the catalog
- Store the signing secret (shown once; regenerate anytime)
- Optionally send a test ping from the dashboard
Envelope
Every delivery uses the same outer shape. Metadata comes first;data is always the last key.
Money in data
Webhook money fields are JSON numbers in major units, always written with 6 decimal places:
amount,fee,transfer_fee,total_debit→200.000000,0.310000, …- Each has a companion integer:
amount_minor,fee_minor,transfer_fee_minor,total_debit_minor(Ledger minor units) scaleis always present (usually2; stablecoins use6)
*_minor when you need exact integer math.
What else is in data
Regardless of event type, money events aim to include enough fields to drive decisions:
- Identity —
object,id,business_id,stan,status - Rates —
fx_rate,rate(human label like1 USD = 1,523.0769 NGN), and aratesobject - Rails —
method(e.g.Bank transfer · NIP),rail,channel,scheme - Counterparty — full
beneficiary(orsenderon payins), including routing where stored - Documents — on payouts with supporting files,
documents[]with signed S3url+url_expires_at(24h) - Timeline —
timeline.stepswith stage, label, state (done/current/upcoming/failed), and timestamps
Guarantees
- Successful non-GET state changes enqueue a durable event
- Deliveries are signed (Signatures)
- Failed deliveries retry (Retries)
- Events can be polled with
GET /v1/events, fetched by id withGET /v1/events/{id}, and pinged withPOST /v1/ping - Money events are idempotent on
(tenant, environment, type, data.id)so partner settle retries do not duplicate deliveries