0STK resultSuccess
The STK Push transaction completed and the customer's payment was received successfully.
Treat the transaction as paid, read the receipt from CallbackMetadata, and fulfil the order.
Search Safaricom's M-Pesa result and error codes by number or description. Every failed payment in Payments is decoded with the same reference.
27 codes
0STK resultSuccess
The STK Push transaction completed and the customer's payment was received successfully.
Treat the transaction as paid, read the receipt from CallbackMetadata, and fulfil the order.
1STK resultInsufficient balance
The customer does not have enough M-Pesa balance (including any available Fuliza overdraft) to cover the amount.
Show a friendly message asking the customer to top up their M-Pesa balance and retry the payment.
17STK resultUnable to process by Party B
The receiving shortcode (Party B) or Safaricom's system was temporarily unable to process the transaction.
Wait around 30-45 seconds and retry the request; if it persists, show a generic error.
26STK resultSystem busy
M-Pesa is under high load and rejected the request because the system was busy.
Back off and retry the request after about 30 seconds.
1001STK resultUnable to lock subscriber / transaction in progress
The customer already has an active USSD or M-Pesa session processing another transaction, so a new one cannot be started.
Ask the customer to finish or close the other session and retry after 1-3 minutes.
1019STK resultTransaction expired
The transaction exceeded its allowed processing window because the customer took too long to respond.
Let the customer re-initiate the payment and prompt them to approve promptly.
1025STK resultError while sending push / message too long
M-Pesa could not send the STK prompt, often because the TransactionDesc exceeds 182 characters or a temporary system issue occurred.
Keep TransactionDesc within 182 characters and retry the request.
9999STK resultError sending push (request character limit)
The push could not be delivered, commonly because the request message exceeds the 182-character limit.
Shorten the request fields (especially TransactionDesc) to stay within the character limit and retry.
1032STK resultRequest cancelled by user
The customer received the STK/USSD prompt but pressed Cancel instead of entering their PIN.
Show a friendly retry option so the customer can re-initiate the payment.
1037STK resultTimeout / user cannot be reached
The STK prompt could not reach the phone or the customer did not respond within the timeout, often due to the phone being off or poor coverage.
Ask the customer to check their network, restart the phone, or offer an alternate payment method, then retry.
2001STK resultWrong PIN / invalid initiator information
Authorization failed because the customer entered the wrong M-Pesa PIN (or the initiator credentials were invalid).
Allow the customer to re-enter the correct PIN (typically up to 3 attempts) and retry.
400.002.02API errorBad Request - Invalid BusinessShortCode / Invalid Amount
The synchronous request was rejected as malformed, commonly due to an invalid shortcode, invalid amount, or the payload being sent as form data instead of JSON.
Send the body as JSON, and verify BusinessShortCode and amount (positive whole-number KES) are valid.
400.002.05API errorInvalid Request Payload
The request payload is structurally invalid or missing required fields, so Daraja returns HTTP 400 before processing.
Validate the JSON schema and required parameters against the endpoint spec before sending.
400.008.02API errorInvalid PhoneNumber
The PhoneNumber/PartyA value is not a valid Safaricom MSISDN in the required 2547XXXXXXXX international format.
Normalize the phone number to the 12-digit 2547XXXXXXXX format before sending, on HTTP 400.
401.002.01API errorUnauthorized - invalid or expired access token
The OAuth access token is missing, malformed, or expired (tokens have a ~1 hour TTL), returning HTTP 401.
Request a fresh token and send it as an 'Authorization: Bearer <token>' header, refreshing before expiry.
404.001.03API errorInvalid Access Token
Daraja reports the access token as invalid on HTTP 404; often the token is actually fine but the shortcode is not authorized/whitelisted for that specific API.
Confirm the token is valid and current, and contact Safaricom to enable/whitelist the API on your production shortcode.
404.001.04API errorInvalid Authentication Header
The Authorization header is missing or incorrectly formatted, so the request cannot be authenticated (HTTP 404).
Ensure the header is exactly 'Authorization: Bearer <access_token>' with no extra whitespace.
500.001.1001API errorServer Error / merchant does not exist or insufficient funds
A server-side error (HTTP 500), commonly a nonexistent merchant/shortcode or, for B2C, insufficient funds in the business account.
Verify the shortcode/merchant configuration and business account balance, then retry or contact Safaricom support.
500.002.1001API errorService temporarily unavailable / under maintenance
The Daraja service is temporarily unavailable, throttled (spike arrest), or under maintenance, returning HTTP 500.
Implement exponential backoff and retry later; if persistent, check Safaricom status or support.
0C2B / B2CSuccess / Accepted
The C2B/B2C/Reversal/Transaction Status/Account Balance request was processed successfully (for C2B validation this is the 'Accept' response).
Return ResultCode 0 to accept, and process the result/receipt details from the confirmation callback.
2001C2B / B2CThe initiator information is invalid
For B2C and other secured APIs, the initiator username/encrypted SecurityCredential does not match the shortcode or has expired.
Re-encrypt the initiator password with Safaricom's RSA public cert, confirm the initiator belongs to the shortcode, and renew before expiry.
C2B00011C2B / B2CInvalid MSISDN (Reject)
During C2B validation the payer's phone number (MSISDN) is considered invalid by your validation logic.
Return this reject code when the MSISDN is unrecognized, or accept if you do not need to validate the payer number.
C2B00012C2B / B2CInvalid Account Number (Reject)
During C2B validation the account number / bill reference supplied by the payer does not exist in your system.
Return this reject code for unknown account references, or map/create the account before accepting.
C2B00013C2B / B2CInvalid Amount (Reject)
During C2B validation the paid amount fails your rules (for example wrong amount for the invoice).
Return this reject code when the amount is invalid, or relax the amount check if partial payments are allowed.
C2B00014C2B / B2CInvalid KYC Details (Reject)
During C2B validation the payer's KYC details do not meet your requirements.
Return this reject code when KYC checks fail, otherwise accept the transaction.
C2B00015C2B / B2CInvalid Shortcode (Reject)
During C2B validation the shortcode targeted by the payment is considered invalid.
Return this reject code for an unexpected shortcode, or verify your shortcode configuration.
C2B00016C2B / B2COther Error (Reject)
A catch-all C2B validation rejection for any other reason not covered by the specific reject codes.
Return this reject code for unclassified validation failures, and log the reason for follow-up.