Timeouts and unknown outcomes
By the end of this track you can send money without paying twice.
0/3 finished
Step 1
The idea
Sometimes you send a payout and get no answer. The money may or may not have moved. Never resend. Query Transaction Status first. With the MCP server, reusing the same idempotency key makes a retry safe.
Step 2
How it works
The dangerous moment
You sent a payout and the request timed out, or the result never came. Daraja may have never received it, or it may have paid already. From your side, both look the same: unknown.
1. Mark it unknown
Don't mark it failed, and don't let anyone click Send again. Store it as unknown so the next steps happen.
2. Ask what happened
Query Transaction Status (lesson O1). With no receipt, send the payout's ID in the OriginalConversationID field. Wait for the answer at your ResultURL.
3. Then decide
- It succeeded: mark it paid. Done.
- It failed, or Daraja has no record: now it is safe to send again.
- Still no answer: wait and query again. Unknown stays unknown until you know.
Idempotency keys
The kit's money tools take an idempotency_key. Sending again with the same key while the first attempt is accepted or unknown returns that attempt (duplicate: true) instead of paying twice; read its outcome with mpesa_get_result. Use one key per real-world payout, such as refund-order-1042.
Step 3
Common mistakes
- Retrying a payout automatically on a timeout.
- Making a new idempotency key for each retry. Then it protects nothing.
- Marking a timed-out payout as failed and refunding the customer another way.
Go deeper
The network dropped after you sent a KES 5,000 B2C. Your colleague wants to click Send again. What do you say?
Answer in your own words first.
Show the answerHide the answer
Don't. Check Transaction Status first; resend only once you know it failed, with the same idempotency key.