Skip to content
Joseph Gitonga
<-All notes

M-Pesa STK push callback not received? Check these in order

2026-11-01 / 5 min / payments / m-pesa / stk-push / callbacks

Your customer paid but the callback never came. Why M-Pesa STK push callbacks go missing, what to check in order, and the fix that stops relying on them.

Get help with thisPayments: M-Pesa, cards, reconciliation and monitoring

The customer says they paid. They have the M-Pesa message to prove it. Your order still says unpaid, because the callback your system was waiting for never came.

This is the most common way an M-Pesa integration fails in production, and it is rarely random. Here is what should happen, the order to check things in, and the change that stops a missing callback becoming a missing payment.

What should happen

An STK push (M-Pesa Express) payment has three moments:

  1. Your system sends the payment request. Safaricom accepts it and returns a checkout request ID.
  2. The customer sees the prompt on their phone and enters their PIN, cancels, or ignores it.
  3. Safaricom calls your callback URL with the result: a result code, and for a successful payment, the M-Pesa receipt number.

The first moment is not a payment. An accepted request only means the prompt was sent. Only the third moment, or a status query, tells you whether money moved.

Check these in order

1. Is the callback URL reachable from outside?

Most missing callbacks were never deliverable. Call the exact callback URL from a machine outside your network.

  • It must be public HTTPS with a valid certificate. Not localhost, not a private IP, not a tunnel address that expired when your laptop slept.
  • It must not sit behind a login, a basic-auth prompt or a redirect.
  • A firewall, WAF or security plugin must not be blocking the request.

2. Did the request reach your server?

Search your access logs around the payment time. This splits the problem in two.

  • Nothing in the logs: go back to step 1, then step 3.
  • The request arrived but returned an error: your handler crashed, timed out or rejected the payload. Respond quickly and do the heavy work after acknowledging, so a slow database does not turn into a lost callback.

3. Is it pointing at the right environment?

Live payments must use the live callback URL. A common failure is a production shortcode sending callbacks to a sandbox, staging or old server address that is still in configuration.

4. Did your code match it to the order?

The callback carries the checkout request ID from step 1. If your system did not store that ID against the order when it sent the prompt, the callback arrives and has nothing to attach to. It looks exactly like a missing callback, but the logs will show it arriving.

5. Did the payment actually fail?

A non-zero result code means the payment did not complete. Two you will see often:

  • 1032: the customer cancelled the prompt.
  • 1037: the customer could not be reached, for example their phone was off or out of coverage.

These are normal outcomes, not bugs. Mark the order as not paid and offer a retry. Never mark an order paid on request acceptance alone.

The fix that holds: stop depending on the callback

Even a correct integration will miss a callback eventually. Networks fail, servers restart, deployments happen at the wrong second. The durable design treats the callback as one source of evidence, not the only one.

  • Store the checkout request ID against the order the moment the prompt is sent.
  • Query the status when no callback has arrived after a few minutes, using that checkout request ID, and update the order from the answer.
  • Apply each payment once. Use the M-Pesa receipt number as the key, so a late callback after a status query, or a repeated callback, cannot credit the order twice.
  • Reconcile daily against the M-Pesa statement, which catches anything both paths missed. The note on reconciling M-Pesa payments covers how.

What not to do

  • Do not ask the customer to pay again while the first payment is unknown. If both go through, you now owe a refund and an apology.
  • Do not treat “no callback” as “failed”. Unknown is its own state until the status query or the statement answers it.
  • Do not hide the problem in support. If customers are sending M-Pesa messages to prove they paid, the system needs fixing, not the support script.

When to get help

If callbacks go missing more than occasionally, or you cannot tell which orders are paid without checking the statement by hand, the confirmation path needs work. That is the core of payments integration and reconciliation work: callbacks verified and applied once, status checks when they do not arrive, and alerts before customers have to tell you.


Read next