MTN MoMo · Error reference
MTN MoMo API Error Codes and Failure Reasons Explained
MTN MoMo reports problems in two places: HTTP errors when your request is rejected outright, and a failure reason when a payment is accepted but doesn't complete.
Have a response you don't understand? Paste it into the Payment Error Code Lookup and it finds every known code inside.
How MTN MoMo reports errors
- HTTP status codes (400, 401, 409, 500…) come back immediately when MTN rejects the request itself.
- Failure reasons such as NOT_ENOUGH_FUNDS arrive later, in the "reason" field of the status response or callback, when status is FAILED.
- "reason" is a plain string in some versions and an object {"code": "...", "message": "..."} in others. Handle both.
How sure is this?
Each code below is labelled by how well it is documented. Of the 29 codes on this page: 14 are in MTN MoMo's own documentation, 14 are confirmed by several independent sources, and 1 are reported by only one source. Treat codes marked "Reported by one source" as a strong hint, and log the full response so you can check.
Payment outcomes
The status values that tell you whether the customer paid.
PaidSeen in: Status / callbackRetry: not neededIn the provider's docs
The customer approved the payment and the money moved.
What to do
- Confirm the amount and currency match your order, store financialTransactionId, then fulfil the order once.
Sources: MTN MoMo developer portal: sandbox use cases
PENDING Waiting for the customer
WaitingSeen in: Status / callbackRetry: Check the status before retryingIn the provider's docs
The prompt was sent and the customer hasn't approved or declined yet.
What to do
- Wait for the callback, or poll the status endpoint with backoff. The customer has about five minutes.
Sources: MTN MoMo developer portal: sandbox use cases
Failure reasons
Why a payment did not go through.
FAILED Payment did not complete
Not paidSeen in: Status / callbackRetry: Yes, as a new requestIn the provider's docs
The payment failed. The "reason" field says why.
How to fix it
- Read "reason" (a string or {code, message}) and handle that code. Mark the order unpaid.
Sources: MTN MoMo developer portal: sandbox use cases
Not paidSeen in: Status / callbackRetry: Yes, as a new requestConfirmed by several sources
The customer declined the payment prompt on their phone.
How to fix it
- Mark the order unpaid. Offer a "Try again" button; send a new Request to Pay with a new X-Reference-Id.
What to tell the customer
You cancelled the payment on your phone. You can try again whenever you are ready.
Sources: MTN MoMo developer portal: sandbox use cases
Not paidSeen in: Status / callbackRetry: Yes, as a new requestConfirmed by several sources
The customer did not approve the prompt before it timed out (about 5 minutes).
How to fix it
- Mark the order unpaid and let the customer retry with a new X-Reference-Id.
What to tell the customer
The payment request timed out. Please try again and approve the prompt on your phone.
Sources: MTN MoMo developer portal: sandbox use cases
Not paidSeen in: Status / callbackRetry: Yes, as a new requestIn the provider's docs
The payer does not have enough money in their MoMo wallet, including fees.
How to fix it
- Show the total amount including any fees before you send the request, so customers can top up first.
What to tell the customer
Your MoMo balance is too low for this payment. Top up and try again.
One MTN page writes this as "NOT ENOUGH_FUNDS" with a space. Normalise spaces to underscores before comparing.
Sources: MTN MoMo Developer Community: failure reasons · MTN MoMo developer portal: error codes
Not paidSeen in: Status / callbackRetry: Yes, as a new requestIn the provider's docs
The payer's transaction limit has been reached. Limits vary by country and account level.
How to fix it
- Let the customer pay with another number, or split the payment if your business allows it.
What to tell the customer
This payment is above your MoMo limit. Try a smaller amount or a different MoMo number.
Sources: MTN MoMo Developer Community: failure reasons · MTN MoMo developer portal: error codes
Not paidSeen in: Status / callbackRetry: Later, it is temporaryIn the provider's docs
The receiving account's limit has been reached. Limits vary by country.
How to fix it
- Check your merchant account limits with MTN, or reduce the amount.
What to tell the customer
This payment could not be completed right now. Please try a smaller amount or try later.
MTN's list writes this as "PAYEE LIMIT_REACHED" with a space. Normalise spaces to underscores before comparing.
Sources: MTN MoMo Developer Community: failure reasons · MTN MoMo developer portal: error codes
Not paidSeen in: Status / callbackRetry: Yes, as a new requestIn the provider's docs
The phone number is not a registered, active MoMo account.
How to fix it
- Check the number format (country code, no leading 0). Use "Validate account holder status" before charging.
What to tell the customer
We could not find a MoMo account for this number. Check the number and try again.
Sources: MTN MoMo Developer Community: failure reasons · MTN MoMo developer portal: error codes
Not paidSeen in: Status / callbackRetry: No, fix the cause firstIn the provider's docs
Your merchant (payee) account is not active — for debits this usually means the business account is blocked.
How to fix it
- Contact your MTN account manager. Retrying will keep failing until your account is fixed.
What to tell the customer
We cannot take MoMo payments right now. Please try another payment method.
Sources: MTN MoMo Developer Community: failure reasons · MTN MoMo developer portal: error codes
Not paidSeen in: Status / callbackRetry: No, fix the cause firstIn the provider's docs
The receiving wallet is not allowed to receive funds (for example, it is not active).
How to fix it
- Check the receiving account status with MTN.
What to tell the customer
This payment could not be completed. Please try another payment method.
Sources: MTN MoMo Developer Community: failure reasons · MTN MoMo developer portal: error codes
Not paidSeen in: Status / callbackRetry: Yes, as a new requestIn the provider's docs
The transaction was not completed. Often the approval window passed or the network failed mid-way.
How to fix it
- Retry with a new X-Reference-Id. If it repeats, check the status endpoint and contact MTN.
What to tell the customer
The payment did not go through. Please try again.
Sources: MTN MoMo Developer Community: failure reasons · MTN MoMo developer portal: error codes
Not paidSeen in: Status / callbackRetry: Yes, as a new requestConfirmed by several sources
The transaction was cancelled before completion.
How to fix it
- Mark the order unpaid and allow a new attempt.
What to tell the customer
The payment was cancelled. You can try again.
Sources: MTN MoMo developer portal: sandbox use cases
Not paidSeen in: Status / callbackRetry: Yes, as a new requestConfirmed by several sources
The payment was not approved by the payer.
How to fix it
- Mark the order unpaid and allow a new attempt.
What to tell the customer
The payment was not approved. You can try again.
Sources: MTN MoMo developer portal: sandbox use cases
Not paidSeen in: Status / callbackRetry: Later, it is temporaryConfirmed by several sources
A generic error inside MTN's system.
How to fix it
- Check the status endpoint before retrying — the payment may still complete. Retry later with a new X-Reference-Id.
What to tell the customer
MoMo had a temporary problem. Please try again in a few minutes.
Sources: MTN MoMo developer portal: sandbox use cases
Not paidSeen in: Status / callbackRetry: Later, it is temporaryConfirmed by several sources
The MoMo service is temporarily unavailable.
How to fix it
- Back off and retry later. Consider showing another payment method meanwhile.
What to tell the customer
MoMo is temporarily unavailable. Please try again shortly.
Sources: MTN MoMo developer portal: sandbox use cases
Not paidSeen in: Status / callbackRetry: No, fix the cause firstConfirmed by several sources
Your API user is not authorised for this operation.
How to fix it
- Check your product subscription (Collections) and API user permissions with MTN.
What to tell the customer
This payment could not be completed. Please try another payment method.
Sources: MTN MoMo developer portal: sandbox use cases
Not paidSeen in: Status / callbackRetry: No, fix the cause firstConfirmed by several sources
Your credentials are not valid for the X-Target-Environment you sent (e.g. sandbox keys with mtnuganda).
How to fix it
- Make the target environment match your credentials. This is a configuration bug, not a customer problem.
What to tell the customer
This payment could not be completed. Please try again later.
Sources: MTN MoMo developer portal: sandbox use cases
Not paidSeen in: Status / callbackRetry: No, fix the cause firstConfirmed by several sources
The X-Callback-Url host does not match the providerCallbackHost registered for your API user.
How to fix it
- Use a callback URL on the host you registered, or update the registration.
What to tell the customer
This payment could not be completed. Please try again later.
Sources: MTN MoMo developer portal: sandbox use cases
Not paidSeen in: Status / callbackRetry: No, fix the cause firstConfirmed by several sources
The currency is not supported for this target environment (the sandbox only accepts EUR).
How to fix it
- Send EUR in the sandbox and the local currency in production (e.g. UGX for mtnuganda).
What to tell the customer
This payment could not be completed. Please try again later.
Sources: MTN MoMo developer portal: sandbox use cases
Not paidSeen in: Status / callbackRetry: Yes, as a new requestIn the provider's docs
The X-Reference-Id was already used. Every request needs a new UUID v4.
How to fix it
- Generate a fresh UUID v4 for every Request to Pay. Never reuse one, even for a retry.
What to tell the customer
This payment could not be completed. Please try again.
Sources: MTN MoMo Developer Community: failure reasons · MTN MoMo developer portal: error codes
Not paidSeen in: Status / callbackRetry: Yes, as a new requestConfirmed by several sources
MTN could not find the resource you referred to.
How to fix it
- Check you are using the right X-Reference-Id and target environment.
What to tell the customer
This payment could not be completed. Please try again.
Sources: MTN MoMo developer portal: sandbox use cases
Not paidSeen in: Status / callbackRetry: Yes, as a new requestIn the provider's docs
The transaction could not be found.
How to fix it
- Check the reference ID and target environment you used for the status lookup.
What to tell the customer
We could not find this payment. Please try again.
Sources: MTN MoMo Developer Community: failure reasons · MTN MoMo developer portal: error codes
Not paidSeen in: Status / callbackRetry: No, fix the cause firstIn the provider's docs
The request failed validation: wrong data types, unsupported decimals, empty fields, or notes over 128 characters.
How to fix it
- Fix the request: amount as a string, supported currency, non-empty payerMessage/payeeNote of 128 characters or fewer.
What to tell the customer
This payment could not be completed. Please try again later.
Sources: MTN MoMo Developer Community: failure reasons · MTN MoMo developer portal: error codes
Request errors
Returned straight away when the API rejects your request.
Request errorSeen in: API responseRetry: No, fix the cause firstConfirmed by several sources
MTN rejected the request because a header or the body is malformed.
How to fix it
- X-Reference-Id must be a fresh UUID v4.
- Use EUR in the sandbox; the local currency in production.
- Send amount as a string ("500"), not a number.
- Send the phone number digits-only in international format, with no "+" and no leading 0.
- X-Callback-Url, if set, must be a valid URL.
Sources: MTN MoMo Developer Community: sandbox 400 errors
Request errorSeen in: API responseRetry: Yes, as a new requestConfirmed by several sources
The access token is missing, expired, or doesn't match the subscription key or product.
How to fix it
- Fetch a new token. Tokens expire, so cache them and refresh before expires_in runs out.
- Use the subscription key for the same product as the endpoint. Collections and Disbursements have separate keys and token endpoints.
- If you regenerated the API key, the old one stops working immediately.
- Send the token as "Authorization: Bearer <token>". The token endpoint itself uses Basic auth.
Sources: MTN MoMo Developer Community: sandbox 400 errors
HTTP 409 Conflict (duplicate reference)
Request errorSeen in: API responseRetry: Yes, as a new requestIn the provider's docs
You reused an X-Reference-Id. Every API user and every transaction needs its own UUID.
How to fix it
- Generate a new UUID v4 for every Request to Pay, including retries of a failed payment.
Sources: MTN MoMo Developer Community: failure reasons
Request errorSeen in: API responseRetry: Yes, as a new requestReported by one source
An empty POST (create API key, get token) was sent without a Content-Length header.
How to fix it
- Send "Content-Length: 0" on empty POSTs. With cURL use --data ''; most HTTP libraries do it automatically when the body is empty.
Sources: MTN MoMo Developer Community: sandbox 400 errors
HTTP 500 Internal Server Error
Request errorSeen in: API responseRetry: Check the status before retryingConfirmed by several sources
Something failed on MTN's side, or your target environment doesn't match your credentials (the body then often names NOT_ALLOWED_TARGET_ENVIRONMENT).
How to fix it
- Read the response body. If it names a reason code, handle that code.
- Check that X-Target-Environment matches your credentials (sandbox keys only work with "sandbox").
- For a Request to Pay, check the status endpoint before retrying. The request may have gone through.
Sources: MTN MoMo Developer Community: sandbox 400 errors · MTN MoMo developer portal: sandbox use cases
Handle every code in your code
Map each outcome code to one of four actions. Unknown codes fall back to "check the status", so a new or misspelled code never fulfils or cancels an order by accident.
// What to do with each MTN MoMo outcome code.
// Unknown codes fall back to "check_status": never fulfil or fail an order on a code you don't recognise.
const ACTIONS = {
"SUCCESSFUL": "fulfil", // Payment completed
"PENDING": "wait", // Waiting for the customer
"FAILED": "mark_failed", // Payment did not complete
"APPROVAL_REJECTED": "mark_failed", // Approval rejected
"EXPIRED": "mark_failed", // Expired
"NOT_ENOUGH_FUNDS": "mark_failed", // Not enough funds
"PAYER_LIMIT_REACHED": "mark_failed", // Payer limit reached
"PAYEE_LIMIT_REACHED": "mark_failed", // Payee limit reached
"PAYER_NOT_FOUND": "mark_failed", // Payer not found
"PAYEE_NOT_FOUND": "mark_failed", // Payee not found
"PAYEE_NOT_ALLOWED_TO_RECEIVE": "mark_failed", // Payee not allowed to receive
"COULD_NOT_PERFORM_TRANSACTION": "mark_failed", // Could not perform transaction
"TRANSACTION_CANCELED": "mark_failed", // Transaction canceled
"PAYMENT_NOT_APPROVED": "mark_failed", // Payment not approved
"INTERNAL_PROCESSING_ERROR": "mark_failed", // Internal processing error
"SERVICE_UNAVAILABLE": "mark_failed", // Service unavailable
"NOT_ALLOWED": "mark_failed", // Not allowed
"NOT_ALLOWED_TARGET_ENVIRONMENT": "mark_failed", // Not allowed target environment
"INVALID_CALLBACK_URL_HOST": "mark_failed", // Invalid callback url host
"INVALID_CURRENCY": "mark_failed", // Invalid currency
"RESOURCE_ALREADY_EXIST": "mark_failed", // Resource already exist
"RESOURCE_NOT_FOUND": "mark_failed", // Resource not found
"TRANSACTION_NOT_FOUND": "mark_failed", // Transaction not found
"VALIDATION_ERROR": "mark_failed", // Validation error
};
export function momoNextStep(code) {
const key = String(code ?? "").trim().toUpperCase().replace(/[\s-]+/g, "_");
return ACTIONS[key] ?? "check_status";
}
// Example:
// switch (momoNextStep(payment.reason?.code ?? payment.reason ?? payment.status)) {
// case "fulfil": // verify amount, then mark the order paid (idempotently)
// case "mark_failed": // mark unpaid, show a retry button
// case "wait": // do nothing yet; a callback or your poller will follow
// case "check_status": // ask the status endpoint before deciding
// }
Frequently asked questions
What does MTN MoMo code PAYER_NOT_FOUND mean?
PAYER_NOT_FOUND (Payer not found): The phone number is not a registered, active MoMo account. Check the number format (country code, no leading 0). Use "Validate account holder status" before charging.
What does MTN MoMo code NOT_ENOUGH_FUNDS mean?
NOT_ENOUGH_FUNDS (Not enough funds): The payer does not have enough money in their MoMo wallet, including fees. Show the total amount including any fees before you send the request, so customers can top up first.
What does MTN MoMo code APPROVAL_REJECTED mean?
APPROVAL_REJECTED (Approval rejected): The customer declined the payment prompt on their phone. Mark the order unpaid. Offer a "Try again" button; send a new Request to Pay with a new X-Reference-Id.
What does MTN MoMo error HTTP 401 mean?
HTTP 401 (Unauthorized): The access token is missing, expired, or doesn't match the subscription key or product. Fetch a new token. Tokens expire, so cache them and refresh before expires_in runs out.
What does MTN MoMo error HTTP 400 mean?
HTTP 400 (Bad Request): MTN rejected the request because a header or the body is malformed. X-Reference-Id must be a fresh UUID v4.
Integration guides
Full MTN MoMo integrations that handle these codes: Node.js, Laravel, Django, Disbursements (payouts) in Node.js.
Checked October 2026. Error codes change. If you see one that's missing or wrong, please let me know.