Skip to main content

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.

Headers

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.