Legacy compatibility
Already integrated with an MSORG or Adex / N3tdata style API? Point your existing integration at FinalDataSub with the same paths and payloads — only the host and key change. New integrations should use the Merchant API.
Endpoints
All paths are on the /api base (not /api/v1/merchant). A trailing slash is optional.
| Method | Path | Purpose |
|---|---|---|
| GET | /api/user | Account and wallet balance |
| POST | /api/data | Buy data |
| POST | /api/topup | Buy airtime |
| GET | /api/data/{id} · /api/topup/{id} | Transaction status by MSORG id |
Authentication
Use your ds_live_ key. All three headers work; API access approval, IP whitelist and the 120 requests / minute limit (shared with the merchant API) apply.
| Header | Example |
|---|---|
| Authorization | Token ds_live_YOUR_KEY |
| Authorization | Bearer ds_live_YOUR_KEY |
| X-API-Key | ds_live_YOUR_KEY |
MSORG vs Adex fields
The format is detected from the body: Adex if it contains request-id or data_plan, or phone without mobile_number; otherwise MSORG.
| Purpose | MSORG | Adex |
|---|---|---|
| Plan id | plan | data_plan |
| Phone number | mobile_number | phone |
| Network | network | network |
| Your reference | ident (or request_id) | request-id |
| Status in response | Status: successful · processing · failed | status: success · process · fail |
| Balances in response | balance_before / balance_after | oldbal / newbal |
Network ids
The id tables differ between formats. You can also send the network name (MTN, GLO, AIRTEL, 9MOBILE).
| Id | MSORG | Adex |
|---|---|---|
| 1 | MTN | MTN |
| 2 | GLO | AIRTEL |
| 3 | 9MOBILE | GLO |
| 4 | AIRTEL | 9MOBILE |
Plans, references and errors
- Plan ids are the
idvalues from GET /billers (also returned asmsorg_plan_id/adex_plan_id). - Send
ident/request_id(MSORG) orrequest-id(Adex) to make retries safe. Re-sending one silently returns the original transaction. Without one, every call is a new purchase. - Errors use
{"status": "fail", "Status": "failed", "message": "…", "error": ["…"]}. Insufficient balance is HTTP 400.
Error body
{
"status": "fail",
"Status": "failed",
"message": "A valid phone number is required.",
"error": [
"A valid phone number is required."
]
}