| Message shown | HTTP | Cause and fix |
| Invalid request | 405 | The request was not a POST. Post the form; do not link to the URL. |
| We could not verify this payment request | 403 | Unknown or suspended Merchant ID, or the signature does not match. See Signing. (The sandbox adds a hint.) |
| Request expired | 400 | timestamp is more than 30 minutes from our clock. Generate it when you build the form and sync your server clock. |
| Invalid invoice reference | 400 | invoice_id must be 1 to 64 characters of letters, digits, . _ -. |
| Only KES payments are supported | 400 | Send currency=KES. |
| Amount must be between KES 1 and KES 250,000 | 400 | Check amount. |
| Invalid return_url / cancel_url | 400 | Use a full http(s) URL without a username or password. |
| notify_url must be a public HTTPS URL | 400 | Use HTTPS on a public host (a tunnel while developing). No localhost, private IPs, or plain http. |
| M-Pesa payments are temporarily unavailable for this merchant | 400 | Live only: the merchant licence has expired. Renew on Merchant Gateway. |
| This merchant is not ready to accept M-Pesa payments yet | 400 | Live only: no paybill or till is connected on Payout Destinations. |
| Message | Meaning |
| Enter a valid Safaricom number | The phone number format is not valid. |
| Too many attempts | 5 prompts were already sent for this checkout. Start a new one. |
| Please wait a few seconds… | Prompts must be 15 seconds apart (sandbox: 5). |
| This invoice is already paid | The checkout for this invoice and amount is already paid. |
| This checkout has expired | More than 1 hour passed. Start a new checkout. |
| Could not send the M-Pesa prompt | Live only: Safaricom rejected the request. Check the number and your Daraja credentials. |
| Other text from M-Pesa | Passed through as the failure reason (for example the customer cancelled or had insufficient funds). |