Makeipay Lab

sandbox · EUR sandbox.momodeveloper.mtn.com

Live integration console for MTN and Orange. Every button composes a real request, signs it and puts it on the wire, then shows the raw exchange — request, headers, response, verbatim. Built against each operator's own published specification.

Integration readiness

What is built, what is proven against live operator infrastructure, and the exact credential still outstanding. Every endpoint below is implemented and callable today — the requests are built, signed and sent; only production keys are missing.

MTN MoMo proven

Collections & disbursements · momodeveloper.mtn.com

  • POST /collection/v1_0/requesttopay
  • GET /collection/v1_0/requesttopay/{ref}
  • POST /disbursement/v1_0/transfer
  • GET /disbursement/v1_0/transfer/{ref}
  • GET /collection/v1_0/accountholder/msisdn/{n}/active

Settled SUCCESSFUL in sandbox: collect, then a split payout to two numbers, as independent transfers.

We need: production subscription keys and X-Target-Environment: mtncameroon in XAF.

MTN Airtime & Data endpoint verified

Balance Management V1 · api.mtn.com

  • POST /v1/accounts/{msisdn}/topUp
  • GET /v3/products/productOffering
  • POST /v2/customers/{id}/subscriptions

The endpoint answers 401 with MTN's own error envelope — live and reachable, rejecting us only for want of a key. Request bodies are built to spec, currency FCFA, Amount.type switching CURRENCY↔DATA.

We need: a Consumer Key for these products, and a reseller account on ERS to put in senderAccountId.

Orange Money built to spec

OrangeMoneyCoreAPIS · omdeveloper.orange.cm

  • POST /mp/init · /mp/pay · GET /mp/push/{payToken}
  • POST /cashin/init · /cashin/pay
  • GET /{service}/paymentstatus/{payToken}
  • POST /infos/subscriber/{usertype}/{msisdn}

Built from Orange's own swagger and SPECIFICATION_TECHNIQUE. The gateway answers 401 “Missing Credentials” — reachable, correctly formed, unkeyed.

We need: dossier approval, a gateway token (WSO2-Authorization), an API account for X-AUTH-TOKEN, a channel account + PIN, and the airtime merchant code.

Nothing here is mocked. Every button on this page composes a real request and puts it on the wire; where a credential is missing the lab shows the exact bytes it would send rather than inventing a response. The integration work is done. The gap is access.

Environment

Credentials, provisioned API users and wallet balances.

The proxy provisions its own API user and key on first use, then caches the access token until it expires. Reset forces a fresh set.

Wallet lookup

Confirm an MSISDN is a live MoMo wallet before moving money to it.

GET /collection/v1_0/accountholder/msisdn/{msisdn}/active — returns 200 {"result": true} for a valid wallet, 404 otherwise.

1MTN → MTN, with a commission split

Collect from a payer's MoMo wallet, then pay out to the recipient and a commission number in the same flow.

There is no native split primitive. The split is two independent POST /disbursement/v1_0/transfer calls with separate reference ids — so each leg can succeed or fail on its own, and the ledger has to reconcile the pair rather than assume atomicity. That is the real finding this card exists to prove.

The sandbox only settles EUR. Put XAF in the currency box and MTN answers 500 INVALID_CURRENCY — "Currency not supported." It is a property of the sandbox environment, not of where you are calling from. XAF arrives with production access, together with X-Target-Environment: mtncameroon.

2MTN ↔ Orange, cross-network

Collect on one network, pay out from our own pre-loaded float on the other.

buildable  Orange customer → MTN customer

Orange /mp/* collects — /mp/push rings the customer's handset to confirm — then MTN Transfer pays out, the payout already proven in card 1.

buildable  MTN customer → Orange customer

MTN RequesttoPay collects — proven — then Orange /cashin/pay credits the Orange customer from our channel account. No push step: we are pushing money out, so no customer approval is needed, which is also why that call carries our PIN.

Orange runs in preview until credentials exist. Registration at omdeveloper.orange.cm is open, but API access needs an approved dossier, so the lab renders the exact request it would send rather than faking a response. Every MTN leg runs for real.

Two things to design around. Orange needs two credentials: WSO2-Authorization: Bearer for the gateway and X-AUTH-TOKEN: base64(user:pass) for the account. And /cashin/pay carries our channel PIN in the request body — a different security posture from MTN's bearer token, so those credentials need handling to match.

3Airtime & data

Sell airtime and data bundles on MTN and on Orange.

MTN — one endpoint, and it fits us exactly. POST api.mtn.com/v1/accounts/{msisdn}/topUp, from Balance Management V1. Its own description: "allows a reseller to refill/credit a subscriber airtime account from the reseller's account" — a pre-loaded float we sell down, the same shape as the MoMo disbursement wallet. Currency enum is FCFA, so it is built for this market.

Data rides the same call. Amount.type is an enum of CURRENCY | DATA | MINUTES | SMS — the bucket changes, the request does not. Listing purchasable bundles is a different product (Product Offering v3, GET /v3/products/productOffering), and subscribing a customer to one is a third (Subscriptions v2). So airtime is one call; data is three products stitched together.

Orange has no airtime API — not on developer.orange.com, and not in OrangeMoneyCoreAPIS, whose operations are all money movement. On Orange, airtime is a purchase made with Orange Money, so the likely route is a merchant payment to Orange's airtime merchant code via /mp/* — the same call card 2 already builds. Unconfirmed: it needs Orange to tell us the merchant code.

Both operator routes need reseller/distributor status, which is commercial, not technical. The shortcut worth knowing: aggregators (Reloadly and similar) resell MTN, Orange, Nexttel and Camtel airtime for Cameroon with self-serve sandboxes — more expensive per unit, but testable this week instead of next quarter.

Trace

Every request and response, exactly as it went over the wire — credentials redacted by the proxy. Without an access key this shows recorded proof of earlier live calls instead.

Loading…