Migrating Callbacks from v3 to v4
This page walks through moving a sub-merchant's callbacks from v3 to v4. The payment callback and checkout callback are versioned independently — payment_callback_version and checkout_callback_version — so you can migrate one before the other. Neither is self-serve; [email protected] makes the change once your endpoint is ready.
You can't run v3 and v4 side by side on either field: the moment payment_callback_version or checkout_callback_version flips to v4, v3 deliveries on that callback stop entirely. If your endpoint isn't already updated to read the v4 shape and validate the v4 signature, every callback on that surface fails from the first delivery after the flip.
- Deploy and verify your v4 parsing and signature logic first.
- Prove it in test mode (below) before requesting anything on your live sub-merchant.
- Only then ask [email protected] to flip the live version field(s).
Confirm the expected turnaround for a rollback request with Nimbbl before you flip, since it is not fixed.
Payment Callback: What Changes
| v3 | v4 | |
|---|---|---|
| Delivery | response=<base64> query parameter (redirect only); full plain JSON body for no-redirect/webhook | payload/nimbbl_signature/version as query params (redirect) or the same fields as a JSON body (no-redirect/webhook) |
| Where the signature lives | Inside the decoded JSON, as nimbbl_signature | A separate field alongside payload, not inside the decoded JSON |
| Payload size | Full payload — transaction, order, and user objects | Compact — order and transaction summary. authorization_details for pre-authorization is present on both — it is not a v4 addition. |
| Signature input | Per-field concatenation (invoice_id|transaction_id|...) | Entire compact JSON string |
sub_merchant_id is not part of the unencrypted v4 payment callback response — it's added only when encryption is enabled for the sub-merchant. If you run multiple sub-merchants against one unencrypted callback URL, there's nothing in the response to tell you which access_secret to verify with; route by URL or enable encryption per sub-merchant.
Checkout Callback: What Changes
| v3 | v4 | |
|---|---|---|
Wrapper event_type | globalHandleCheckoutResponse | globalHandleCheckoutResponse (unchanged) |
| Payload | Full transaction and order objects nested inside payload | Lightweight status object: checkout_status, nimbbl_order_id, nimbbl_transaction_id, invoice_id, retry, reason, message |
| Signature | nimbbl_signature and transaction.signature inside the payload, per-field concatenation | nimbbl_signature at the top level (alongside payload and version), HMAC-SHA256 of the entire compact JSON string |
Migration Steps
- Update your endpoint(s) to parse the new shape.
- Payment callback: read
payload,nimbbl_signature, andversion(from query params on redirect, or JSON body otherwise) instead of the v3responseparameter or flat JSON body. - Checkout callback:
event_typestaysglobalHandleCheckoutResponse— no change needed there. Update yourcallback_handlerto read the nestedpayload.payload/payload.nimbbl_signature/payload.versioninstead of the v3 payload shape.payload.sub_merchant_idis present only when encryption is enabled.
- Payment callback: read
- Base64-decode the
payloadfield on each to recover the compact JSON. For the checkout callback, switch your UI logic from the oldstatusfield tocheckout_statusplus the newreasonvalues. - Switch signature validation from per-field concatenation to
HMAC-SHA256(compact_json_string, access_secret)— the same algorithm for both callbacks, both using the field namenimbbl_signature. See Validating Payment Response with Signature for code samples in Java, C#, PHP, and Python. - Handle pre-authorization if relevant.
transaction.authorization_detailson the payment callback is present on v3 as well as v4, so this isn't strictly a migration step — but if your sub-merchant uses manual capture, make sure you're already handling it, plus thepayment_authorizedreason on the checkout callback. See Pre-Auth and Capture. - If you use Transaction Enquiry, note that moving
payment_callback_versionto v4 also changes that endpoint:nimbbl_signatureandsignature_versionare both returned asnullthere for v4 sub-merchants. Update any code that validates the enquiry signature before you flip. - Test in test mode. Ask [email protected] to set
payment_callback_versionand/orcheckout_callback_versiontov4for your test sub-merchant, then run test transactions end to end. - Go live. Once test-mode traffic validates cleanly, ask [email protected] to flip the corresponding version field(s) on your live sub-merchant.
Because payment_callback_version and checkout_callback_version are separate fields, you can move one callback to v4 while the other stays on v3. If you rely on both together (e.g. checkout callback for UI, payment callback to confirm), test the combination you'll actually run in production before requesting the live cutover.