Common MTN MoMo API Errors and How to Fix Them
The most common MTN MoMo API errors are: 401 Unauthorized (wrong API credentials or expired token), 400 Bad Request (malformed payload or invalid parameters), callback not received (server not publicly accessible or URL misconfigured), timeout (customer did not confirm), and 500 Internal Server Error (MoMo-side issue, retry later). Most errors during development are caused by incorrect sandbox credentials, a callback URL that is not publicly reachable, or missing required fields in the request payload.
Authentication Errors
401 Unauthorized
The most common error during setup. Causes:
- Wrong API key. Double-check that you are using the correct subscription key from the MoMo Developer Portal. Copy-paste errors are common.
- Expired access token. MoMo tokens expire after a set period. Your code should handle token refresh automatically. If you are getting 401 on API calls that previously worked, your token has likely expired.
- Sandbox vs production mismatch. Sandbox credentials do not work against production endpoints, and vice versa. Make sure your base URL matches your credential environment.
- Incorrect API user/key. In the sandbox, you create an API user and API key programmatically. If these were not created correctly, authentication fails. Recreate them from scratch.
403 Forbidden
You are authenticated but not authorized for this operation. Causes:
- You are calling an API (e.g., Disbursements) that you have not subscribed to on the Developer Portal.
- Your production account has not been approved for the operation you are attempting.
Request Errors
400 Bad Request
Your request is malformed. Common causes:
- Missing required fields. The Request to Pay endpoint requires amount, currency, payer (with MSISDN), and external ID. Missing any of these returns a 400.
- Invalid phone number format. The MSISDN must be in the correct format for Rwanda. Try formats like 250780000000 (with country code, no plus sign) and verify against the API documentation.
- Invalid currency. Use "RWF" for Rwanda. Typos or wrong currency codes cause 400 errors.
- Duplicate external ID. Each transaction must have a unique reference. Reusing an external ID from a previous request may cause an error.
409 Conflict
A resource with the same ID already exists. Common when creating API users in the sandbox: if you reuse a reference ID, you get a 409. Generate a new UUID for each attempt.
422 Unprocessable Entity
The request is syntactically correct but semantically invalid. Check the response body for specific error details. Common cause: amount format issues (some APIs expect a string, others expect a number).
Callback Issues
Callback problems are the most frustrating category because the error is silent: nothing happens. Your server does not receive the expected POST request, and you have no error message to debug.
"My callback is not being received"
Checklist:
- Is your server publicly accessible? MoMo cannot reach localhost:3000. During development, use ngrok (
ngrok http 3000) to get a public URL. Verify ngrok is running and your URL is current (ngrok URLs change on restart with the free tier). - Is your callback URL correct in the API request? The callback URL must be HTTPS. Check for typos. Include the full path (e.g., https://your-domain.com/api/momo/callback).
- Is your server running and the route correct? Send a test POST to your callback URL manually (using curl or Postman) to verify your server responds.
- Are there firewall issues? If your server is behind a firewall, MoMo's requests may be blocked. Ensure incoming POST requests from MoMo's IP ranges are allowed.
- Is your server responding with 200 OK? If your callback handler crashes or returns an error, MoMo may not retry (or may retry on a schedule). Your handler should return 200 first, then process the callback asynchronously.
"I receive callbacks in sandbox but not in production"
Your production server must be deployed with HTTPS. The callback URL registered during production onboarding must match exactly. Verify your production server is accepting POST requests from external sources.
Transaction Errors
These errors come back in the callback or when you poll the transaction status.
FAILED: PAYER_NOT_FOUND (or similar)
The phone number does not have a MoMo account. Verify the number is correct and has an active MoMo wallet.
FAILED: NOT_ENOUGH_FUNDS
The customer does not have enough money in their MoMo wallet. Show a friendly message suggesting they top up and try again. Do not reveal the customer's balance.
FAILED: TRANSACTION_TIMED_OUT
The customer did not confirm the payment within the timeout period. They may not have seen the prompt, or they chose not to confirm. Allow them to retry.
FAILED: INTERNAL_PROCESSING_ERROR
An error on MoMo's side. This is not your fault. Implement retry logic with exponential backoff. If it persists, check MoMo's status page or contact their developer support.
PENDING (not transitioning to success or failure)
The transaction is stuck. This can happen if the USSD prompt was sent but the customer has not responded. Implement a timeout in your application (60 to 120 seconds) and show the customer a retry option. Also poll the status endpoint as a fallback.
A Debugging Strategy That Works
When something is broken in your MoMo integration, follow this order:
- Check the logs. Log every HTTP request you send (URL, headers, body) and every response you receive (status, body). The answer is almost always in the logs.
- Isolate the failure point. Is the error in authentication? In the payment request? In the callback? Test each step independently using curl or Postman before looking at your application code.
- Compare with the documentation. Open the MoMo API documentation and verify that your request matches the expected format exactly. Field names, data types, header names: all must match.
- Check the sandbox vs production environment. Many production errors are caused by using the wrong environment. Verify your base URL, credentials, and callback URL all point to the same environment.
- Test the callback independently. Send a manual POST request to your callback URL with a sample payload. If your server processes it correctly, the issue is on MoMo's side. If not, the issue is in your callback handler.
Detailed logging during development is the single most effective debugging tool. Every mobile money integration we have built at McTaba starts with comprehensive request and response logging. When something breaks (and it will), the logs tell you exactly where and why.
If you want structured, mentored support through this process, the McTaba mobile money integration course (approximately RWF 100,000) walks you through building a complete integration with error handling built in from the start. The debugging strategies you learn apply to MoMo, M-Pesa, Airtel Money, and any future mobile money API you encounter.
Key Takeaways
- ✓Most MoMo API errors during development are caused by three things: wrong credentials, unreachable callback URL, or malformed request payload. Check these first.
- ✓A 401 Unauthorized error almost always means your API credentials are wrong, your token has expired, or you are using sandbox credentials against the production endpoint (or vice versa).
- ✓If your callback is not being received, verify that your server is publicly accessible. MoMo cannot send callbacks to localhost. Use ngrok for development.
- ✓Always implement transaction status polling as a fallback for missed callbacks. Callbacks can fail due to network issues on either side.
- ✓Log every request and response during development. When something goes wrong, the logs tell you exactly where the flow broke.
Frequently Asked Questions
- Why does my MoMo sandbox work but production fails?
- Common causes: sandbox and production use different base URLs and credentials. Verify you updated all environment variables. Your callback URL must be HTTPS and publicly accessible in production. Your production credentials must be approved and active. Check each of these independently.
- How do I test error scenarios in the sandbox?
- The MoMo sandbox may support test phone numbers that simulate specific error scenarios (insufficient funds, timeout, etc.). Check the developer documentation for supported test scenarios. If not available, you can test error handling by sending malformed requests or using invalid phone numbers.
- What should I do if MoMo is down?
- Implement circuit breaker logic: if multiple requests fail with 500 errors, temporarily stop sending new requests and show users a maintenance message. Retry after a few minutes. MoMo downtime is usually brief. Log everything so you can reconcile transactions when the service returns.
Ready to build real-world apps?
Join the McTaba Labs full-stack marathon (4 months full-time · 6 months part-time). Learn M-Pesa, USSD, and WhatsApp engineering while shipping 8 production apps.
Apply to the McTaba Marathon