Skip to content

M-Pesa integration: what the documentation does not tell you

Callback validation, duplicate handling, timeouts and reconciliation - the production concerns that decide whether payments actually work.

By Brian Ochieng,

The Daraja API documentation will get you to a successful STK push in an afternoon. It will not prepare you for the transactions that fail in ways your happy path never imagined. Here is what production actually requires.

Never trust the callback alone

Your callback URL is a public endpoint. Anyone can post to it. Validate every callback against your own record of the transaction: does this checkout request ID exist, is it still pending, does the amount match what was ordered? Then query the transaction status API to confirm independently before releasing goods.

Callbacks arrive twice, or late, or never

All three happen. Design accordingly:

  • Make callback processing idempotent - keyed on the M-Pesa receipt number, so the second delivery is a no-op.
  • Run a reconciliation job that polls pending transactions older than a few minutes and resolves them from the status API.
  • Keep a pending state that survives an app restart, so a customer returning to the page sees the truth.

Handle the human timeouts

The STK prompt appears on the customer's phone and waits for a PIN. They might be driving, have a dead battery, or simply ignore it. Your UI needs a clear pending state with an honest message, a resend option after a sensible interval, and a graceful expiry that does not leave an order stuck forever.

Test with real money

The sandbox does not reproduce every production behaviour. Before launch, run a set of live transactions of one shilling each: successful payment, cancelled prompt, wrong PIN, timeout, insufficient funds. Watch what your system does in each case. Every one of those paths will occur in the first week.

Reconciliation is a feature, not a script

Finance needs to match M-Pesa statements against orders without a developer. Build a reconciliation view: transactions with no matching order, orders with no matching transaction, amount mismatches, and a way to resolve each manually with a note. This gets used every single day, and building it late means someone does it in a spreadsheet in the meantime.

The integration is the easy part. Everything around the integration is the work.

Brian Ochieng

Trenax

Working on something this touches on? We are happy to talk it through, whether or not it turns into a project.

Book a call

Tell us what is not working

Thirty minutes, no deck. You will leave with an honest read on feasibility, a price band and a timeline - whether or not you work with us.

We reply within one business day.

Have a project in mind?

Free 30-minute discovery call.

Book a call