MobileWalletPartner Gateway Docs

Webhooks & callbacks

How delivery, signing, and retries work — so you don't have to poll.

If your partner record has a callbackUrl configured, the gateway POSTs you a notification the moment a transaction reaches a terminal status — you don't need to poll GET /api/v1/transactions/{orderId} unless you want to.

Configuring your callback

Set your callbackUrl and (optionally) a callbackSecret via the Partner Dashboard's Webhooks page, or PUT /api/v1/partner/webhook. A freshly-generated secret is returned exactly once — store it immediately; it's never shown again (the gateway only ever keeps a hash of it... same "shown once" convention as a credential's AppKey).

Payload

{
  "transactionId": "0192b7a4-6f1e-7c3a-9d2b-4e5f6a7b8c9d",
  "partnerOrderId": "deposit-2026-10-10-001",
  "status": "GW-01-SUCCESS",
  "statusMessage": null
}

status is the same GW-xxx code you'd get back from a status poll — see the error/status reference.

Verifying the signature

If you configured a callbackSecret, every delivery carries:

X-Signature: <hex-encoded HMAC-SHA256, lowercase>
signature = lowercase_hex( HMAC_SHA256(
  key:     your callbackSecret,
  message: the exact raw request body bytes
))

Unlike the inbound request signature, there's no timestamp component here — the gateway itself controls when it sends, so there's no replay window to protect against on an outbound call it initiated.

import hashlib
import hmac

expected = hmac.new(callback_secret.encode(), request_body_bytes, hashlib.sha256).hexdigest()
is_valid = hmac.compare_digest(expected, request.headers["X-Signature"])

If you didn't configure a callbackSecret, deliveries arrive unsigned — fine for local testing, not recommended for production.

Delivery, retries, and dead-lettering

Your endpoint has 10 seconds to respond with any 2xx status. Anything else — a non-2xx status, a timeout, a connection failure — counts as a failed attempt and schedules a retry on a fixed backoff:

AttemptDelay before this attempt
1immediately
21 minute
35 minutes
430 minutes
52 hours
66 hours
724 hours

After attempt 7 fails, delivery stops — this is the dead letter; there's no separate notification or alert. An admin (or, for your own partner's deliveries, you) can inspect the delivery history and manually trigger a fresh redelivery (a new attempt 1) once your endpoint is fixed. One failing delivery attempt never blocks any other delivery — each is isolated.

Testing your handler without a real transaction

In Sandbox, you can re-fire the callback for an already-resolved transaction on demand, as many times as you like, without re-running a whole create-and-wait flow each time.

On this page