POST request to your configured webhook URL instead of making you poll for it.
Set your webhook URL and grab your webhook secret from Webhook Settings in the merchant dashboard.
Payload
string
The payer’s bank transfer narration/description, exactly as their bank sent it to us. Free text, not guaranteed unique, and not something you provided. Useful only as a human-readable label to show alongside a transaction — never for matching or deduplication.
string
Ours, and unique. ABCMPay’s own internal ID for the transaction (shown as “Order Number” in the dashboard). This is the value to store and to key your duplicate-detection off.
string
Unique per delivery attempt — even a retry of the same transaction gets a new one. Covered by the signature. See Replay protection.
string
ISO 8601 timestamp of this specific delivery attempt. Also covered by the signature.
Request headers
Verifying the signature
Every payload is signed with HMAC-SHA256 using your webhook secret, over the entire raw request body (not a re-serialized version of it — hash the bytes exactly as received).PHP
Replay protection
A valid signature only proves the request came from us — it doesn’t stop someone from capturing and resending an old, still-valid request later. Every delivery carries a uniquenonce and a sent_at timestamp, both covered by the signature above, so you can reject a resend even if its signature checks out.
Retries
If your endpoint doesn’t respond with a2xx status, the delivery is treated as failed and may be retried or manually resent from your dashboard. A retry (or a manual resend from Webhook Events) carries the same transaction_id as the original delivery, with a fresh nonce/sent_at — this is expected and is exactly why you should key duplicate-detection off transaction_id, not reference: it’s the one field guaranteed to stay identical across every delivery attempt of the same payment, and guaranteed distinct between different payments.
You can review delivery history (including HTTP status codes returned) from the Webhook Events page in your dashboard, which also shows both reference and transaction_id for each event so you can trace exactly what was sent.
Respond quickly (under a few seconds) and with a
2xx status as soon as you’ve accepted the payload — do slow work (emails, downstream API calls) after responding, not before.