Skip to content

Four networks under one API, and a number for every plan

The Routegate team5 min read

MTN, Glo, Airtel and T2 Mobile sell through the same request. What changes per network is what a line can send, and a plan number names every plan the same way everywhere.

Selling on four networks has always meant four sets of quirks. Each carrier's lines can do different things, each reseller names the same plan differently, and the integration you wrote for one network grows a branch for every other. Routegate takes all four through one request. This guide is what differs underneath, and what you send.

The four network codes

Every request names its network with one of four codes:

NetworkCodePlan codes start
MTNmtnMTN-
GlogloGLO-
AirtelairtelAIRTEL-
T2 Mobilet2T2-

T2 Mobile is the network that was 9mobile. Its code is t2, its plan codes start T2-, and past transactions read the new name too, so a report that runs across the change reads as one network rather than two. If your own system still says 9mobile, map it to t2 before you send.

The request is the same on every network. A data sale is the network, the plan, the number and your reference, with an idempotency key:

POST /api/v1/data
 curl -X POST https://api.useroutegate.com/api/v1/data \
  -H "Authorization: Bearer $ROUTEGATE_API_KEY" \
  -H "Idempotency-Key: ord-10293" \
  -H "Content-Type: application/json" \
  -d '{
    "network": "airtel",
    "product_code": "1042",
    "destination": "08021234567",
    "client_reference": "ord-10293"
  }'

The destination can be 080..., 234... or +234...; it is stored in one form either way. By default the call waits for the final state and answers with the transaction, successful or failed. Add ?wait=0 if you would rather have an answer at once and take the result from the webhook.

What a line can send, per network

When a sale goes out from your own lines, what is possible depends on the carrier. Routegate knows each network's abilities and refuses a sale a network cannot do before any carrier is called, so a wrong combination fails fast with a reason rather than slowly with a timeout.

NetworkData shareGiftingBundle purchaseAirtime share
MTNYesYesYesYes
GloNoYesYesNo
AirtelNoYesYesYes
T2 MobileYesNoYesNot yet

Two notes on that table. Glo lines have no airtime product at all, so Glo airtime goes through your vendor links rather than your lines. And airtime sharing from T2 Mobile lines is built but switched off for now; until it is on, T2 Mobile airtime can go through your vendor links too.

None of this is something your integration has to branch on. You send the plan; the router works out which of your lines can send it and how, and if none can, your supply order decides whether a vendor takes it.

Connecting a line is the same on every network as well: the carrier sends a one-time code to the line, you enter it in the dashboard, and Glo and T2 Mobile also ask for the line's six-digit app passcode. After that the line is watched like any other: balances read around every operation, and taken out of routing when it runs low rather than left to fail sales.

Plan numbers

A plan code like MTN-SME-1GB is readable, but plenty of the systems that sell data in this market were built around short numeric service ids: a bot menu, a USSD flow, a reseller's own site. So every plan also has a plan number.

A plan number is three to eight digits and never starts with zero. It is unique, it does not change, and it is accepted anywhere a plan code is: as product_code on a vend, on a price quote, in the price list. Send 1042 or send the code; the sale is the same sale. It works identically in test mode, so the numbers you build your menu around in test are the ones you go live with.

Codes and numbers share one name space. That is why a plan code can never be made of digits only: there is never a question of whether 1042 is a code or a number.

The price list gives you both, grouped the way customers read plans, by data type and then by validity:

GET /api/v1/pricing/plans
 curl "https://api.useroutegate.com/api/v1/pricing/plans?network=glo&service=data" \
  -H "Authorization: Bearer $ROUTEGATE_API_KEY"
One plan in the list
 {
  "id": "01a0d8e5-0000-7000-8000-000000000042",
  "product_code": "GLO-2GB",
  "numeric_alias": "1042",
  "name": "Glo Gifting 2GB",
  "kind": "fixed_denomination",
  "validity_days": 30,
  "amount": 1000.00,
  "charges": 15.00,
  "charges_source": "data_type",
  "fee_type": "percentage",
  "fee_basis_points": 150
}

The plan, its number and its price there are illustrative; the live list is the one to build from.

Flat or a share of face value

What a business pays Routegate for a sale is the plan's charges, and nothing else. On a line sale, the line's own airtime or data pays the carrier; the charges are our fee for routing it. Every business pays the same charges for the same plan.

A plan's charges are either a flat amount per sale or a percentage of the plan's face value. In the price list a percentage shows as fee_type: "percentage" with the rate in basis points, so 150 is 1.5 percent, and charges is that share of the listed amount, rounded to the kobo. For a plan sold at any amount, airtime for example, ask for a quote at the amount you mean to sell:

POST /v1/pricing/quote
 curl -X POST https://api.useroutegate.com/v1/pricing/quote \
  -H "Authorization: Bearer $DASHBOARD_SESSION" \
  -H "Content-Type: application/json" \
  -d '{ "product_code": "1001", "amount": 1000.00, "mode": "live" }'

Money goes in and out of the API as naira, a number with at most two decimals. 1000, 1000.0 and 1000.00 are the same amount; 1000.005 is refused rather than rounded behind your back.

One integration

That is the whole difference between the networks, as far as your code is concerned: a code in the network field and a plan in product_code. Everything a network does differently, what its lines can send, how they connect, which sales go to a vendor, is Routegate's to handle, and the route trace on every sale shows how it was handled.

Airtime, reimagined.
Routing, today.