E-commerce11 min read

M-Pesa Daraja C2B webhooks: idempotency done right (Nairobi, 2026)

Mohamed Bah·Fondateur, Kolonell
August 11, 2026
Share:
M-Pesa Daraja C2B webhooks: idempotency done right (Nairobi, 2026)

M-Pesa Daraja C2B webhooks: idempotency done right (Nairobi, 2026)

E-commerce

The verdict in three sentences

A mobile money webhook is never delivered exactly once: M-Pesa Daraja can send up to 4 callbacks and Safaricom expects a fast acknowledgement. Without protection you credit the same order multiple times and the observed duplicate rate climbs to 0.3-1.2%. The fix has three parts: an idempotency key, a dedup table with a TTL, and an HTTP 200 response in under a few seconds.

Why operators resend

The webhook protocol is built for reliability: if the operator gets no quick acknowledgement, it assumes failure and retries. Your server must therefore process each event at most once, even if it arrives four times. That is the definition of idempotency.

ProviderMax attemptsRetry windowExpected timeout
M-Pesa Daraja4~variable< 5 s
Airtel Money4-524 h< 3 s
Flutterwave3+~24 h< 15 s
Paystack3+~72 h< 2 s
MTN MoMo524 h< 3 s

The dedup table: the core of the design

Store a unique identifier per event (the operator TransID or CheckoutRequestID). Before crediting, check whether it exists. If it does, return 200 and do nothing. If not, insert it in the same SQL transaction as the credit.

FieldRoleTypical value
event_idUnique key (PK)operator TransID
order_idLinked orderinternal ref
statusprocessed / pendingprocessed
received_atTimestampnow()
ttlDedup expiry24-72 h

A 24 to 72-hour TTL is enough: no operator retries beyond that. Purge old rows to keep the table lean.

Respond fast, process later

The classic trap: doing all the work (credit, email, SMS) before responding, which blows past the timeout and triggers a retry. Best practice: validate, deduplicate, return 200, then process the rest on a background queue. This cuts observed duplicates by more than 90%.

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.

James, who runs a restaurant in Nairobi, receives 1,400 M-Pesa payments a month. Without deduplication, at a 0.8% duplicate rate, that is 11 orders credited twice, on an average basket of KES 1,600, costing about KES 17,600 a month in refunds, disputes and staff time. Adding a dedup table with an idempotency key brings the rate to ~0% and recovers roughly KES 211,000 a year. The build takes less than a day.

FAQ

What is an idempotency key in practice?

It is a unique, stable identifier for a given operation (often the operator transaction ID). It guarantees that processing the same event twice produces exactly the same result as processing it once.

How many times does Daraja resend a callback?

In 2026 the order of magnitude is up to 4 callbacks while your server fails to acknowledge quickly. Other operators like MTN MoMo can go up to 5 within 24 hours.

What TTL should the dedup table use?

Between 24 and 72 hours. That is longer than the retry window of every common operator, so you stay covered without letting the table grow forever.

Why respond within a couple of seconds?

Beyond that, the operator treats the call as failed and retries, multiplying duplicates. Acknowledge first, then handle the credit, email and SMS on a queue.

Let's talk about your project. We make your M-Pesa and card webhooks idempotent, with a tested dedup table and queue. WhatsApp +221 77 596 93 33.

Tags:#webhook#idempotence#orange money#m-pesa#daraja#reconciliation#fiabilite paiement#backend
Share:

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.