Send a bank collection event
https://nexgapp.com/api/payments/bank/webhookSandboxThe URL NexG gives a bank as callback_url when it opens a collection. The bank posts every status change here, signed with the shared webhook secret. Only a verified event marks an order paid.
Today it works with the NexG Sandbox Bank on test deployments. On the production site it answers 503 no_bank_configured until a real bank is connected.
- Authentication
- Signed body (
X-Bank-Signature) - Rate limit cost
- No API bucket
- Caching
- Not cached
- Available since
- 10 November 2026
Headers
X-Bank-Signatureheader · stringRequiredt=<unix seconds>,v1=<hex HMAC-SHA256 of "<t>.<raw body>">, signed with the webhook secret. Sign every attempt afresh.
X-Bank-Event-Idheader · stringOptionalThe event id, repeated from the body for your logs.
Content-Typeheader · stringRequiredapplication/json
Request body
Collection event, sent as JSON.
idstringUnique per event, and the same on every retry. NexG records each id once.
typestringcollection.succeeded, collection.failed, collection.expired, collection.cancelled or collection.processing.
created_attimestampWhen the event happened.
livemodebooleanfalse for a sandbox bank.
data.idstringThe bank’s collection id, as returned when NexG opened it.
data.statusstringsucceeded, failed, expired, cancelled or processing.
data.merchant_referencestringNexG’s payment reference, such as NXP-261110-7FD3EEA0C8.
data.amountintegerIn cents. Must equal the amount NexG asked for.
data.currencystringMust be KES.
data.bank_referencestring or nullThe bank’s own reference for the transfer, kept on the payment.
data.failure_reasonstring or nullWhy it failed, in words a guest can read.
Errors
The webhook answers { "ok": false, "reason": "…" }. The status tells the sender whether to retry; see Webhooks.
- 400
bad_signatureThe signature did not verify, or t is more than five minutes from NexG’s clock. Do not resend the same bytes; sign again.
- 500
not_recordedNexG could not record the event right now. Retry with backoff, signing each attempt again.
- 503
no_bank_configuredBank payments are switched off on this deployment. Retry later.
Good to know
- A 200 means NexG is done with the event: handled, a duplicate, or permanently refused. Read result to see which, and do not retry any of them.
- result.duplicate is true for an event id NexG has already recorded. result.ignored is true for a status NexG does not act on (processing). result.reason explains a refusal: unknown_reference, collection_mismatch, currency_mismatch, invalid_amount, amount_mismatch, incomplete_event or unreadable.