Why webhooks matter
A mobile wallet payment is not settled when our API responds to you. The customer still has to
approve it on their handset — by entering their MPIN in a USSD prompt or approving in their wallet
app — and that can take seconds or minutes.
So a successful response to POST /Payment/deposit means the request was accepted, not that
money moved. The status you receive is Processing. The terminal outcome arrives later, and the
webhook is how you learn it.
Do not treat a successful HTTP response as a completed payment. Fulfil orders on the webhook, or on
a status query — never on the accept response alone.
Configuring an endpoint
Register an HTTPS endpoint in the merchant portal. You will be shown a signing secret beginning
whsec_ exactly once — store it somewhere your application can read it, and treat it like a
password.
Verifying the signature
Every delivery carries a signature computed with HMAC-SHA256 over your endpoint’s secret. Always
verify it before acting on a webhook. An unverified webhook endpoint is a URL anyone can post
payment notifications to.
How to verify
The signed string is the timestamp, a full stop, then the raw request body:
Compute HMAC-SHA256 of that string with your endpoint secret, hex-encode it, and compare it to the
v1 value using a constant-time comparison.
Verify against the raw request body, exactly as received. Parsing the JSON and re-serialising it
changes the bytes and the signature will not match.
Timestamp tolerance
We recommend rejecting deliveries whose timestamp is more than 300 seconds from your own clock.
The timestamp is part of the signed string, so an attacker cannot move it forward without
invalidating the signature.
Migrating from the legacy signature
The legacy X-Swich-Signature header contains only an HMAC over the payload, with no timestamp — so
a captured request replays indefinitely. Both headers are sent during the transition period.
Migrate to X-Swich-Signature-V2. The legacy header will be withdrawn on a date we will announce
in advance. Until then, no action is required for existing integrations to keep working.
Correlating with WayPay support
Every webhook body carries a data.traceId:
It identifies the server-side operation that produced the delivery. If a webhook looks wrong to you,
send us the TraceId — it is the fastest route to the exact processing trace on our side. The same
identifier appears as traceId on synchronous API responses and on status-inquiry results, so a
single payment can be followed end to end.
data field names are PascalCase (CurrentStatus, TraceId), while the envelope around it is
lowercase (id, type, created, livemode). A parser configured for camelCase will silently read
nulls out of data.
Responding
Return a 2xx status as soon as you have stored the event. Do the work afterwards, out of band.
If you return a non-2xx or time out, we retry with exponential backoff. Retries reuse the same
X-Swich-Event-Id.
Idempotency
You will occasionally receive the same event twice. That is a normal property of at-least-once
delivery, not a fault. A network failure after you responded — but before we recorded it — produces a
redelivery.
Deduplicate on X-Swich-Event-Id. Record the ids you have processed and ignore repeats. Crediting a
customer twice because a webhook arrived twice is the failure mode this prevents.
Ordering
Deliveries are not ordered. A completed event can arrive before a pending one for the same
transaction.
Always treat the transaction status inside the payload as authoritative, and never move a transaction
backwards out of a terminal state.
Order by the envelope’s created field (Unix seconds) and keep the newest. Discard any delivery whose
created is older than the one you have already applied.
The webhook is authoritative over the synchronous API response, not the other way round. A payout
can be confirmed by the provider while the original POST /Payment/withdraw call is still open, so a
later webhook saying Completed supersedes a synchronous response that said Failed or Processing.
If the two ever disagree, believe the webhook — or confirm with status inquiry.
Reconciliation
Webhooks are a notification mechanism, not a guarantee. Endpoints go down, DNS breaks, and deploys
happen mid-delivery.
For any transaction where you have not received a terminal event within a few minutes, query
GET /Transaction/{reference} and use that answer. Reconcile on a schedule rather than assuming
delivery.