The verdict in three sentences
The webhook is the moment the operator tells you "the customer paid" — if it's poorly secured, anyone can forge it and create phantom orders. A verified signature (x-signature / HMAC) and an idempotency key on transaction_id stop forgery and double processing. Without deduplication, expect 2 to 5 % duplicate events (network replays, operator retries) that otherwise ship or charge twice.
The essential security controls
A reliable webhook always chains the same steps: verify the signature, check the clock, deduplicate, respond fast. Returning 200 in under a few seconds stops the operator from replaying the event thinking it failed.
| Control | 2026 parameter | Risk avoided |
|---|---|---|
| HMAC / x-signature | Verified on every call | Forged webhook |
| Clock tolerance | 5 min max | Old-message replay |
| Idempotency key | On transaction_id, 24 h TTL | Double charge / double ship |
| Operator IP whitelist | Fixed list | Unknown-origin calls |
| Fast response | 200 in < 5 s | Cascading retries |
| Max replays | 3 attempts | Infinite loop |
Idempotency: the heart of the matter
Idempotency guarantees that processing the same event twice yields the same result as once. Concretely: on receipt you store the transaction_id; if you see it again before the TTL expires, you respond 200 without reprocessing.
| Item | Recommended 2026 value |
|---|---|
| Idempotency key | Operator transaction_id |
| Storage TTL | 24 h |
| Replays tolerated | Up to 3 |
| Callback latency | < 5 s |
| Duplicate-event rate without dedup | 2 - 5 % |
| Status to return on duplicate | 200 (already processed) |
Mini case study
Need a professional website?
Kolonell builds websites that attract clients, optimized for the Sénégalese market. Free quote in 2 minutes.
Ibrahim runs a restaurant in Accra and takes payment via M-Pesa and Flutterwave. One night during a network outage, the operator replays 30 confirmations. Without idempotency, 30 already-paid orders would generate 30 duplicate kitchen tickets. With a key on the transaction_id and a 24 h TTL, the 30 replays simply return 200 already processed. On an average basket of KES 800, he avoids KES 24,000 of food cooked at a loss and a chaotic service.
FAQ
Why verify the signature if I already have an IP whitelist? They complement each other: the whitelist filters network origin, the HMAC signature proves the content wasn't altered. An attacker on the right network still can't forge a valid signature.
What do I do if the signature is invalid? Respond with an error code (401/400) and process nothing. Log the event: a spike of invalid signatures signals an intrusion attempt.
How long should I keep transaction_ids? A 24 h TTL amply covers operator replay windows. Beyond that, the event is archived but no longer treated as an active duplicate.
Can the customer be charged twice by the operator? The charge itself is handled by the operator, not your webhook. Your risk is processing the order twice (shipping, stock) — exactly what idempotency blocks.
Should I respond 200 even to a duplicate? Yes. A recognized duplicate must return 200 to tell the operator "received", otherwise it keeps replaying needlessly.
Let's talk about your project. We secure your M-Pesa, Paystack and Flutterwave webhooks with signatures, idempotency and logging. WhatsApp +221 77 596 93 33.
Mohamed Bah
Fondateur, Kolonell
Passionate about digital and entrepreneurship in Africa, Mohamed has been helping Sénégalese businesses with their digital transformation since 2020. Founder of Kolonell, he believes every SME deserves a professional and accessible online présence.
