Webhooks and Postbacks

A postback is the message the gateway sends to your server when an operation reaches a result. This page explains how to receive it, when to acknowledge it, and how to keep a repeated delivery from changing your balances twice.

The Role of a Postback in Your Payment Flow

Payment Gateway Africa reports the outcome of each operation directly to the merchant. You give us an endpoint on your server in advance. When a pay-in or payout reaches a result, the gateway sends a notification to that endpoint.

Postbacks are addressed to your backend only. The gateway does not run a separate notification service for your customers. If a buyer should get an email, an in-app message or a receipt, your own system sends it after it has processed the postback.

Treat the postback as the trigger for business actions such as marking an order paid, releasing goods or updating a payout record. A customer returning to your site from the payment page is a navigation event. It is not proof of payment.

Full API reference and credentials are provided after merchant onboarding. This page describes the behaviour you should design for. Exact field names, verification details and endpoint paths are in the specification you receive with your project.

Pay-ins, Payouts and Settlement in Your Handler

Pay-ins, payouts and settlement are three separate flows. Keep them separate in your handler and in your database.

Pay-in: a customer pays you through a local method. The postback tells your system whether the collection succeeded, so you can fulfil or cancel the order.

Payout: you send funds to a recipient. Payouts are offered where available for the method and project. The postback tells you the result of that transfer, so you can close or retry the request on your side.

Settlement is the movement of your funds from the gateway to your account. Payment Gateway Africa dispatches merchant settlements on a same-day basis (T+0), but the time the funds post to your account depends on your bank. Settlements run separately from customer operations, so do not reconcile them against the records you keep for individual pay-in postbacks.

Your handler can receive postbacks for operations in any market enabled on your project: - Kenya (KES): M-Pesa - Egypt (EGP): mobile wallet payments by phone number - Ethiopia (ETB): CBE Birr, M-Pesa and local transfers - Senegal (XOF): Wave and Orange Money - Mali (XOF): Wave, Orange Money and Moov Money - Guinea (GNF): Orange Money - Tunisia (TND): D17 and Flouci The mobile money methods overview lists the supported wallets by country.

Setting Up an Endpoint That Accepts Results

Provide your postback URLs for pay-ins and payouts during setup. Each URL must be reachable from the public internet and accept the request method and format described in your specification.

Keep the endpoint focused. Its job is to receive the notification, check that it is authentic, store the result and reply. Heavy work such as sending emails, calling stock systems or generating invoices should run after the reply, from a queue or background job.

A short, predictable handler cuts down on failed acknowledgements. It also makes problems easier to trace when you compare your logs with the operation history in your project.

Hosted Payment Page and H2H API integrations deliver results in the same way. The integration guide explains how each connection path starts an operation. Postbacks then report the outcome regardless of the path you chose.

Checking That a Notification Is Genuine

Before you act on any result, check that it is authentic using the verification method set out in the specification issued to your project.

If verification fails, do not change any order, balance or payout record. Log the attempt with enough context to investigate, and respond according to the guidance in your specification.

Store your project credentials on the server only. Never place them in browser code, mobile app bundles or public repositories.

The security overview explains how responsibilities are divided between the gateway and your team.

When to Reply with HTTP 200

Your reply tells the gateway whether the notification was received. A 200 response means you have it. Retry rules are defined in your specification, so design your handler to accept the same postback more than once.

Send the 200 only after the result has been written to durable storage, such as a committed database transaction. If you reply first and your process then fails, the gateway considers the postback delivered and your system has no record of it.

The order of steps should be: 1. Receive the request. 2. Verify that the request is authentic. 3. Look up the operation by its identifier. 4. Record the new status in a committed write. 5. Return HTTP 200. 6. Start any follow-up work asynchronously.

Do not return an error to ask for a resend because a downstream system is slow. Record the status, acknowledge the postback, and handle the slow system from your own queue.

Designing for Repeated Deliveries

Because redelivery is possible, your handler will sometimes receive a notification it has already processed. Processing it again must not credit a customer a second time, ship a second order or mark a payout as sent twice.

Build idempotency around the operation identifier supplied in the postback: - Keep one record per operation, with a unique constraint on the identifier. - When a postback arrives, compare its status with the stored status. - If nothing has changed, return 200 without repeating side effects. - If the status has moved forward, apply the change once inside the same transaction that updates the record.

Link side effects to the status change, not to the arrival of a request. For example, credit the wallet balance in the same transaction that moves the record to a successful state. A repeated postback then finds the record already successful and has nothing further to do.

The conceptual example below uses neutral names. It is not the real schema. POST {YOUR_POSTBACK_URL} body: { operation_id, operation_type, status, amount, currency, auth_data } handler: if not is_authentic(request): log and stop begin transaction record = find(operation_id) for update if record.status == status: commit, respond 200, stop apply_status_change(record, status) commit respond 200 enqueue follow_up(operation_id)

Filling Gaps When a Notification Goes Missing

Networks fail and servers restart, so do not rely on postbacks as your only source of truth. If an operation stays in a pending state on your side for longer than your business allows, check its status through the API, using the deposit status request or a lost-transaction search, as described in the API overview.

Compare your records with the gateway's view on a regular schedule. Any operation where the two disagree is a candidate for investigation, not for an automatic retry of the payment.

When you contact support about a specific operation, include its identifier, the amount, the currency and the time your endpoint received or expected the postback.

Moving Your Postback Handler into Production

Before go-live, confirm each of the following: - The endpoint is public, uses the agreed format and replies quickly. - Authenticity checks run before any write. - HTTP 200 is returned only after a committed write. - A duplicate postback leaves balances and orders unchanged. - Pay-in, payout and settlement records are stored separately. - Deposit status checks or lost-transaction requests cover operations that never received a postback. - Logs record operation identifiers without exposing credentials.

In the test project, ask support to set the postback statuses you need, including a repeated notification, and check that the outcome does not change. The testing guide explains how to run these scenarios before real money moves.

When your handler passes these checks, you can request production access. To see which markets fit your plan, review the countries we cover.

Webhook questions

Do postbacks notify my customers?

No. Postbacks go to your server only. Any message to a buyer is sent by your own system after it has processed the result.

What happens if my endpoint returns something other than 200?

Follow the retry rules in your specification. Your handler must accept repeats without applying the change twice.

Should I reply first and save the result afterwards?

No. Write the result to durable storage first, then return 200. If you reply first and the write fails, the result can be lost.

Where are the verification method and field names documented?

They are in the specification issued to your project after merchant onboarding. This page covers behaviour only.

Do Hosted Payment Page and H2H API integrations receive postbacks differently?

No. Both connection paths report results to your registered endpoint. Only the way the operation starts is different.

Can I use pay-in postbacks to track settlement?

No. Settlement is a separate flow. Reconcile it independently from customer pay-ins and payouts.

Ready to go live?