Skip to content

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.

SUCCESSFUL Payment completed

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

APPROVAL_REJECTED Approval rejected

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

EXPIRED Expired

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_ENOUGH_FUNDS Not enough funds

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

PAYER_LIMIT_REACHED Payer limit reached

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

PAYEE_LIMIT_REACHED Payee limit reached

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

PAYER_NOT_FOUND Payer not found

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

PAYEE_NOT_FOUND Payee not found

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

PAYEE_NOT_ALLOWED_TO_RECEIVE Payee not allowed to receive

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

COULD_NOT_PERFORM_TRANSACTION Could not perform transaction

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

TRANSACTION_CANCELED Transaction canceled

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

PAYMENT_NOT_APPROVED Payment not approved

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

INTERNAL_PROCESSING_ERROR Internal processing error

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

SERVICE_UNAVAILABLE Service unavailable

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_ALLOWED Not allowed

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_ALLOWED_TARGET_ENVIRONMENT Not allowed target environment

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

INVALID_CALLBACK_URL_HOST Invalid callback url host

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

INVALID_CURRENCY Invalid currency

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

RESOURCE_ALREADY_EXIST Resource already exist

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

RESOURCE_NOT_FOUND Resource not found

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

TRANSACTION_NOT_FOUND Transaction not found

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

VALIDATION_ERROR Validation error

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.

HTTP 400 Bad 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

HTTP 401 Unauthorized

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

HTTP 411 Length Required

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.

Need this built for you?

I integrate MTN MoMo, M-Pesa and Airtel Money into Laravel / PHP, Python / Django, Node.js / Next.js apps: payments, callbacks, payouts and go-live, with tests.