Accepted is not paid
By the end of this track you can make an authenticated call and explain the async model.
0/4 finished
Step 1
The idea
Daraja answers in two steps. The first response, with ResponseCode "0", only means "request accepted". The customer may still cancel, or not answer. The real outcome is the ResultCode in the callback, or in a status query. ResultCode 0 means success.
Step 2
How it works
Stage 1: the acknowledgement
When you start a payment, Daraja replies within a second or two. ResponseCode "0" means it accepted the request and will try. Nothing has been paid. Save the CheckoutRequestID: it is the handle you use to match the result later.
{ "MerchantRequestID": "29115-34620561-1", "CheckoutRequestID": "ws_CO_29102026143012345678", "ResponseCode": "0", "ResponseDescription": "Success. Request accepted for processing", "CustomerMessage": "Success. Request accepted for processing"}Stage 2: the result
Later, Daraja POSTs the outcome to your callback URL. Here the customer cancelled the prompt, so ResultCode is 1032 and there is no receipt. Only ResultCode 0 means the money moved.
{ "Body": { "stkCallback": { "MerchantRequestID": "29115-34620561-1", "CheckoutRequestID": "ws_CO_29102026143012345678", "ResultCode": 1032, "ResultDesc": "Request cancelled by user" } }}Codes you will see often
0: success. The callback includes the receipt number and amount.1: the customer doesn't have enough money.1032: the customer cancelled the prompt.1037: the phone couldn't be reached, or nobody answered in time.2001: wrong PIN.
What your code should store
Store the payment as accepted after stage 1. Move it to confirmed or failed only from stage 2, or from a status query if the callback never comes.
Step 3
Try it
$ mpesa explain 1032
With the MCP server, ask your agent to use mpesa_explain_code
Step 4
Common mistakes
- Marking an order paid on
ResponseCode "0". - Confusing
ResponseCode(the request was accepted) withResultCode(the payment outcome). - Forgetting to save the
CheckoutRequestID, then having no way to match the callback.
Go deeper
Your code marks an order paid when ResponseCode is "0". What goes wrong?
Answer in your own words first.
Show the answerHide the answer
Orders get marked paid when the customer cancelled.