Guides
Gateway notification URLs & security
Gateway notification URLs for merchants configuring gateways, and how CentraPoint verifies every notification.
On this page
Who this page is for#
This page is for organisation administrators configuring gateways, and for developers who want to understand the security model.
Notification URL format#
https://app.centrapoint.co.za/api/webhooks/{type}?provider={providerId}{type}is the gateway type, e.g.payfast,paystack,mpesa. Each gateway page lists its type.{providerId}identifies the gateway configuration in your organisation, and therefore which credentials verify the notification. Two configurations of the same gateway (for example sandbox and live) have different URLs.- Both GET and POST are accepted, because some gateways (e.g. Pesapal IPN) notify with GET.
Where to find your URL#
In the dashboard, open Settings → Payment providers. Each configured gateway shows its Notification / webhook URL with a copy button. Always copy it from there rather than typing it by hand.
Where to paste it#
Many gateways receive the URL automatically with every checkout, so nothing needs to be pasted. Others need it configured in their own portal:
| Gateway | Type | Setup |
|---|---|---|
| PayFast | payfast | Automatic (sent with each checkout). Set the same passphrase in PayFast and CentraPoint. |
| Netcash Pay Now | netcash_paynow | Paste in the Netcash portal as the Pay Now Notify URL, with &secret=<Notify secret> appended. |
| Ozow | ozow | Automatic (sent with each checkout). |
| Yoco | yoco | Register once via Yoco's webhooks API and paste the returned whsec_ secret. |
| Peach Payments | peach | Automatic; also configure in the Peach dashboard if you enable webhook signing. |
| PayGate (PayWeb3) | paygate | Automatic (sent with each checkout). |
| Paystack | paystack | Paste in Paystack → Settings → API Keys & Webhooks. |
| Flutterwave | flutterwave | Paste in Flutterwave → Settings → Webhooks, with a secret hash matching CentraPoint. |
| DPO Pay | dpo | Ask DPO to configure it for account-level push notifications (optional). |
| Pesapal | pesapal | Automatic: registered as a GET IPN when the IPN ID field is blank. |
| M-Pesa (Daraja) | mpesa | Automatic (sent with each STK Push). Optional callback secret. |
| MTN MoMo | mtn_momo | Automatic (X-Callback-Url). Host must match your API user's callback host. |
Netcash mandate postback URL#
Netcash debit orders use a separate URL for mandate status updates (for example when a customer signs an e-mandate). Configure it in Netcash under Debit orders → Mandate postback URL:
https://app.centrapoint.co.za/api/netcash/mandate-postback?provider={providerId}&secret={postbackSecret}The secret must match the provider's Mandate postback secret; it is required because Netcash does not sign postbacks.
Security model#
A notification URL is public, so anyone could send a fake "payment complete" to it. CentraPoint therefore never trusts a notification body on its own. Before a status changes, the notification must pass the gateway-specific checks below, and the reported amount and currency must match the transaction.
Signature verification#
Where the gateway signs notifications, the signature is recomputed over the exact raw bytes received and compared in constant time:
- PayFast: MD5 signature including your passphrase, plus optional source-IP check and server confirmation ("VALID").
- Paystack:
x-paystack-signature= HMAC-SHA512 of the body with your secret key. - Flutterwave:
verif-hashheader must equal your configured secret hash. - Yoco: Standard Webhooks HMAC-SHA256 signature (
webhook-signatureheader). - Ozow (SHA512 hash), PayGate (MD5 checksum) and Peach Payments(HMAC-SHA256 signature): recomputed with your private key, encryption key or secret token.
- Unsigned gateways (M-Pesa, MTN MoMo, Netcash Pay Now): an optional shared secret appended to the URL as
?secret=or&secret=, checked on every call.
Server-side re-verification#
For gateways that support status queries, CentraPoint asks the gateway's API for the payment's real status and uses that answer, not the notification body. This is the only protection for gateways whose notifications carry no status or no signature (DPO Pay, Pesapal, M-Pesa, MTN MoMo), and an extra layer for signed or secret-protected ones (Paystack, Flutterwave, Yoco, Ozow, PayGate, Peach Payments, Netcash Pay Now).
The return URL is never trusted#
The payer's browser returning to /payment/return proves nothing: it can be opened by anyone. CentraPoint only uses it as a prompt to re-query the gateway for pending payments. Your integration should follow the same rule: never mark an order paid because a browser reached a page; confirm with the Transactions API on your server.
Responses and retries#
- Verified notifications (including duplicates) are acknowledged with
200, or the exact acknowledgement the gateway expects (for example a JSON body for M-Pesa and Pesapal). - Failed verification returns
4xx(e.g. invalid signature, unknown provider, amount mismatch). A temporary problem querying the gateway returns5xx, so gateways that retry will try again. - Notification URLs are rate-limited to 300 requests per minute per source IP and bodies up to 1 MB.
- Every attempt, including failures and the reason, is visible in the dashboard under Webhook log.
- Missed notifications are covered by a background check: card and mobile-money payments still
pendingafter 5 minutes are re-queried with the gateway (for up to 24 hours) on gateways that support status verification.
Troubleshooting#
| Symptom in Webhook log | Likely cause |
|---|---|
| Unknown provider / Missing or unknown ?provider= | The URL was typed by hand or copied from another provider configuration. Copy it again from Settings → Payment providers. |
| Invalid signature | Passphrase / secret key / secret hash in CentraPoint does not match the gateway portal, or the wrong mode (test vs live) key is configured. |
| Invalid callback / notify secret | The ?secret= value in the portal URL does not match the provider setting. |
| Amount mismatch / Currency mismatch | The gateway reported a different amount than the transaction. The payment is not applied; contact the gateway. |
| No notifications at all | The URL is not configured in the gateway portal (for gateways that need it), or the gateway cannot reach it (must be public HTTPS). |
Your own integration#
If you build around CentraPoint, apply the same principles to your system: authenticate every inbound message, re-query the source of truth (the Transactions API) before acting, compare amounts and currencies, and make your fulfilment idempotent so repeated checks never ship an order twice.