MobileWalletPartner Gateway Docs

Sandbox testing

Deterministic test outcomes keyed on magic MSISDNs, and on-demand callback replay.

A Sandbox-environment credential can trigger deterministic outcomes on MOMO_DEPOSIT, MOMO_WITHDRAWAL, CRYPTO_BUY, CRYPTO_SELL, and KYC_MOMO via magic MSISDNs — the same convention every real payment sandbox uses (Stripe's test card numbers, Twilio's magic phone numbers, MTN's own documented test MSISDNs). The MSISDN is the identity value a real provider actually keys outcomes on, so it's the value a test double keys on too — never an incidental business parameter like amount, which you need to vary freely for your own testing (limit enforcement, rounding, …).

MSISDNOutcome
+237670000001Accepted; a status poll resolves it to success on the very first check
+237670000002Rejected immediately with MTN's real PAYER_NOT_FOUND (money in) / PAYEE_NOT_FOUND (money out) reason
+237670000003Rejected immediately with MTN's real NOT_ENOUGH_FUNDS reason
+237670000004Rejected immediately with MTN's real SERVICE_UNAVAILABLE reason
+237670000005Accepted; never resolves — stays Pending forever (for testing your own timeout/retry handling)
+237670000006Accepted; stays Pending for ~5 seconds, then resolves to success on the next poll (for testing realistic async timing, not just instant-or-never)
+237670000007KYC_MOMO only — resolves to an active account
+237670000008KYC_MOMO only — resolves to an inactive/suspended account
anything elseRefused with 400 GW-400-BAD-REQUEST — Sandbox never reaches the real MTN network

Sandbox never touches real money

A Sandbox credential only ever talks to the simulator. Any number that is not in the table above is refused with a 400, for every service including KYC_MOMO (so test keys can never look up a real customer's name).

Sandbox also has its own balance. Money from Sandbox deposits lands in your Sandbox balance only, and Sandbox withdrawals and crypto sells draw only from it. Your Live balance is never affected, and Sandbox money can never be paid out for real. GET /api/v1/ledger/balance and GET /api/v1/ledger/history return the books of the credential you call them with. Daily limits are counted per environment too, so Sandbox traffic never uses up a Live limit.

Rejection reasons use MTN Mobile Money's own real API vocabulary, not gateway-invented strings — code written against these Sandbox responses needs no rewriting for production error handling.

This registry is discoverable at runtime, so you never have to keep this table in sync by hand:

GET /api/v1/sandbox/test-scenarios

returns the exact same list, read from the identical source the simulator itself acts on.

Replaying a callback

Resolved a Sandbox transaction already and want to re-test your webhook handler without creating a whole new transaction? Fire the callback again on demand — the same capability Stripe's CLI (stripe trigger) and Plaid Sandbox (fire_webhook) expose:

POST /api/v1/sandbox/callbacks/{partnerOrderId}/trigger

Requires a Sandbox credential (403 on Live) and a transaction that has already left Pending (400 otherwise — there's nothing to replay for a transaction with no resolved outcome yet). Enqueues a fresh delivery attempt the same way the real terminal-status path does, following the usual retry/backoff rules if your endpoint doesn't acknowledge it.

A Live-environment request never simulates, regardless of which MSISDN it carries — only a Sandbox-authenticated credential's requests are ever intercepted.

On this page