Skip to main content

Migrating Webhooks from v3 to v4

This page walks through moving a sub-merchant's webhook delivery from v3 to v4. Webhook version is set per sub-merchant via the webhook_version field — stored as v100v400 (defaulting to v300, i.e. v3) and displayed as v1.0.0–v4.0.0 in Command Center. It isn't something you toggle yourself; [email protected] makes the change once you've confirmed your endpoint is ready.

Deploy and Verify Before Requesting the Flip

You can't run v3 and v4 side by side: webhook_version is a single per-sub-merchant setting, and the moment it flips to v4, v3 deliveries stop entirely — there is no phased or parallel rollout. If your endpoint isn't already updated to read the v4 format and validate the v4 signature, every webhook fails from the first delivery after the flip. Failed deliveries are retried for roughly 16 hours and then abandoned permanently — they are not recoverable by flipping back.

  1. Deploy and verify your v4 parsing and signature logic first.
  2. Prove it in test mode (below) before requesting anything on your live sub-merchant.
  3. Only then ask [email protected] to flip your live webhook_version to v4.

If you need to roll back after flipping, request it the same way — but any events that failed and expired while your endpoint was unprepared are gone; rolling back does not recover them. Confirm the expected turnaround for a rollback request with Nimbbl before you flip, since it is not fixed.

What Changes

v3v4
DeliveryFull payload sent as-isSame payload Base64-encoded and signed, then sent inside {payload, signature, sub_merchant_id, version}
Top-level versionPresent, inside the payloadMoved out of the payload, up to the top level
Top-level nimbbl_signaturePresentRemoved — replaced by the top-level signature
transaction.signature_versionPresentRemoved
transaction.signaturePresentRemoved
Signature algorithmHMAC-SHA256 of concatenated fields (invoice_id|transaction_id|...)HMAC-SHA256 of the entire compact JSON string (the Base64-decoded payload)

The event payload itself — event_type, transaction, and the rest — is unchanged between versions; only the outer delivery shape, the top-level version field, and the signature move.

Migration Steps

  1. Update your endpoint to read the new format. Instead of reading the webhook body directly as the event payload, read payload, signature, sub_merchant_id, and version from the POST body.
  2. Base64-decode payload to recover the compact JSON string — this is your existing event payload, minus version and the two removed fields below.
  3. Switch signature validation from the v3 field-based formula to HMAC-SHA256(compact_json_string, access_secret), compared against the top-level signature field. See Validating Payment Response with Signature for code samples in Java, C#, PHP, and Python.
  4. Stop reading the top-level version field, nimbbl_signature, and transaction.signature_version from the payload — version has moved up to the top level, and the other two are gone in v4.
  5. Test in test mode. Ask [email protected] to set webhook_version to v4 for your test sub-merchant, then trigger test transactions and confirm your updated endpoint validates and processes events correctly.
  6. Go live. Once test-mode traffic validates cleanly, ask [email protected] to flip webhook_version to v4 on your live sub-merchant.
One Field, Two Versions

webhook_version is a single per-sub-merchant setting — a sub-merchant is on v3 or v4 at any given time, not both. Complete and verify your endpoint changes before requesting the live cutover.