Skip to content
NexG ConciergeDevelopers

Send a bank collection event

POSThttps://nexgapp.com/api/payments/bank/webhookSandbox

The 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 · stringRequired

    t=<unix seconds>,v1=<hex HMAC-SHA256 of "<t>.<raw body>">, signed with the webhook secret. Sign every attempt afresh.

  • X-Bank-Event-Idheader · stringOptional

    The event id, repeated from the body for your logs.

  • Content-Typeheader · stringRequired

    application/json

Request body

Collection event, sent as JSON.

  • idstring

    Unique per event, and the same on every retry. NexG records each id once.

  • typestring

    collection.succeeded, collection.failed, collection.expired, collection.cancelled or collection.processing.

  • created_attimestamp

    When the event happened.

  • livemodeboolean

    false for a sandbox bank.

  • data.idstring

    The bank’s collection id, as returned when NexG opened it.

  • data.statusstring

    succeeded, failed, expired, cancelled or processing.

  • data.merchant_referencestring

    NexG’s payment reference, such as NXP-261110-7FD3EEA0C8.

  • data.amountinteger

    In cents. Must equal the amount NexG asked for.

  • data.currencystring

    Must be KES.

  • data.bank_referencestring or null

    The bank’s own reference for the transfer, kept on the payment.

  • data.failure_reasonstring or null

    Why 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.

  • 400bad_signature

    The signature did not verify, or t is more than five minutes from NexG’s clock. Do not resend the same bytes; sign again.

  • 500not_recorded

    NexG could not record the event right now. Retry with backoff, signing each attempt again.

  • 503no_bank_configured

    Bank 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.