Sell data from your own app
The Msub reseller API lets your website, app or bot buy data bundles for your customers. Purchases are paid from your Msub wallet at your API price.
https://api.msub.ng/api/v1/merchant
JSON requests and responses. Every response has success, message and data.
120 requests per minute per key.
Authentication
Send your API key in the X-API-Key header on every request. Get a key from
API Access in your Msub dashboard; your account must be approved as an API user.
curl https://api.msub.ng/api/v1/merchant/balance \ -H "X-API-Key: YOUR_API_KEY" \ -H "Accept: application/json"
Network IDs
Use these as network when buying.
| network | Network |
|---|---|
| 1 | MTN |
| 2 | Airtel |
| 3 | Glo |
| 4 | 9mobile |
Data plan IDs
Send the Plan ID as plan when buying. Your price for each plan is
returned by List your plans. This list is also available as JSON from
the public plan endpoint.
| Plan ID | Network | Type | Size | Validity |
|---|---|---|---|---|
| 541 | MTN (1) | GIFTING | 500MB | 1 day |
| 542 | MTN (1) | GIFTING | 1GB | 1 day |
| 543 | MTN (1) | GIFTING | 1.5GB | 2 days |
| 551 | MTN (1) | GIFTING | 1.8GB | 30 days |
| 544 | MTN (1) | GIFTING | 2GB | 2 days |
| 547 | MTN (1) | GIFTING | 2GB | 30 days |
| 545 | MTN (1) | GIFTING | 2.5GB | 2 days |
| 548 | MTN (1) | GIFTING | 2.7GB | 30 days |
| 546 | MTN (1) | GIFTING | 3.2GB | 2 days |
| 550 | MTN (1) | GIFTING | 3.5GB | 7 days |
| 549 | MTN (1) | GIFTING | 3.5GB | 30 days |
| 554 | MTN (1) | GIFTING | 5.5GB | 30 days |
| 553 | MTN (1) | GIFTING | 7GB | 2 days |
| 552 | MTN (1) | GIFTING | 7GB | 30 days |
| 555 | MTN (1) | GIFTING | 10GB | 30 days |
| 556 | MTN (1) | GIFTING | 11GB | 7 days |
| 557 | MTN (1) | GIFTING | 12.5GB | 30 days |
| 558 | MTN (1) | GIFTING | 14.5GB | 30 days |
| 559 | MTN (1) | GIFTING | 16.5GB | 30 days |
| 560 | MTN (1) | GIFTING | 20GB | 30 days |
| 561 | MTN (1) | GIFTING | 25GB | 30 days |
| 562 | MTN (1) | GIFTING | 25GB | 30 days |
| 563 | MTN (1) | GIFTING | 34GB | 30 days |
| 564 | MTN (1) | GIFTING | 36GB | 30 days |
| 565 | MTN (1) | GIFTING | 40GB | 60 days |
| 566 | MTN (1) | GIFTING | 65GB | 30 days |
| 567 | MTN (1) | GIFTING | 75GB | 30 days |
| 568 | MTN (1) | GIFTING | 90GB | 60 days |
| 569 | MTN (1) | GIFTING | 165GB | 30 days |
| 570 | MTN (1) | GIFTING | 250GB | 30 days |
| 571 | MTN (1) | GIFTING | 800GB | 365 days |
| 579 | MTN (1) | SME | 1GB | 7 days |
| 584 | MTN (1) | SME | 1GB | 30 days |
| 580 | MTN (1) | SME | 2GB | 30 days |
| 581 | MTN (1) | SME | 3GB | 30 days |
| 614 | MTN (1) | SME | 5GB | 30 days |
| 582 | MTN (1) | SME | 5GB | 30 days |
| 583 | MTN (1) | SME | 10GB | 30 days |
| 442 | Airtel (2) | GIFTING | 75MB | 1 day |
| 443 | Airtel (2) | GIFTING | 110MB | 1 day |
| 444 | Airtel (2) | GIFTING | 250MB | 1 day |
| 435 | Airtel (2) | GIFTING | 500MB | 7 days |
| 446 | Airtel (2) | GIFTING | 600MB | 2 days |
| 433 | Airtel (2) | GIFTING | 1GB | 3 days |
| 432 | Airtel (2) | GIFTING | 1GB | 7 days |
| 441 | Airtel (2) | GIFTING | 1.5GB | 1 day |
| 438 | Airtel (2) | GIFTING | 1.5GB | 7 days |
| 440 | Airtel (2) | GIFTING | 1.5GB | 1 day |
| 439 | Airtel (2) | GIFTING | 1.5 | 7 days |
| 445 | Airtel (2) | GIFTING | 2GB | 7 days |
| 434 | Airtel (2) | GIFTING | 2GB | 30 days |
| 437 | Airtel (2) | GIFTING | 3GB | 2 days |
| 447 | Airtel (2) | GIFTING | 3GB | 30 days |
| 436 | Airtel (2) | GIFTING | 3GB | 30 days |
| 448 | Airtel (2) | GIFTING | 4GB | 30 days |
| 449 | Airtel (2) | GIFTING | 7GB | 7 days |
| 491 | Airtel (2) | GIFTING | 8GB | 30 days |
| 450 | Airtel (2) | GIFTING | 8GB | 30 days |
| 431 | Airtel (2) | GIFTING | 10GB | 30 days |
| 451 | Airtel (2) | GIFTING | 10GB | 30 days |
| 452 | Airtel (2) | GIFTING | 13GB | 30 days |
| 453 | Airtel (2) | GIFTING | 25GB | 30 days |
| 454 | Airtel (2) | GIFTING | 35GB | 30 days |
| 518 | Airtel (2) | GIFTING | 60GB (EBONY PLAN) | 365 days |
| 455 | Airtel (2) | GIFTING | 60GB | 30 days |
| 519 | Airtel (2) | GIFTING | 100GB | 30 days |
| 456 | Airtel (2) | GIFTING | 100GB | 30 days |
| 457 | Airtel (2) | GIFTING | 300GB | 90 days |
| 458 | Airtel (2) | GIFTING | 350GB | 120 days |
| 459 | Airtel (2) | GIFTING | 685GB | 360 days |
| 492 | Glo (3) | GIFTING | 45MB | 1 day |
| 493 | Glo (3) | GIFTING | 100MB | 1 day |
| 521 | Glo (3) | GIFTING | 200MB | 30 days |
| 600 | Glo (3) | GIFTING | 200MB | 30 days |
| 494 | Glo (3) | GIFTING | 200MB | 2 days |
| 522 | Glo (3) | GIFTING | 500MB | 30 days |
| 523 | Glo (3) | GIFTING | 1GB | 30 days |
| 495 | Glo (3) | GIFTING | 1.5GB | 1 day |
| 498 | Glo (3) | GIFTING | 1.5GB | 7 days |
| 524 | Glo (3) | GIFTING | 2GB | 30 days |
| 497 | Glo (3) | GIFTING | 2.5GB | 2 days |
| 499 | Glo (3) | GIFTING | 2.6GB | 30 days |
| 496 | Glo (3) | GIFTING | 3GB | 2 days |
| 525 | Glo (3) | GIFTING | 3GB | 30 days |
| 500 | Glo (3) | GIFTING | 5GB | 30 days |
| 526 | Glo (3) | GIFTING | 5GB | 30 days |
| 501 | Glo (3) | GIFTING | 6.15GB | 30 days |
| 502 | Glo (3) | GIFTING | 7.25GB | 30 days |
| 503 | Glo (3) | GIFTING | 10GB | 30 days |
| 527 | Glo (3) | GIFTING | 10GB | 30 days |
| 504 | Glo (3) | GIFTING | 12.5GB | 30 days |
| 505 | Glo (3) | GIFTING | 16GB | 30 days |
| 506 | Glo (3) | GIFTING | 20GB | 30 days |
| 507 | Glo (3) | GIFTING | 28GB | 30 days |
| 421 | Glo (3) | SME | 500MB | 14 days |
| 423 | Glo (3) | SME | 1GB | 3 days |
| 424 | Glo (3) | SME | 1GB | 7 days |
| 422 | Glo (3) | SME | 1GB | 14 days |
| 425 | Glo (3) | SME | 3GB | 3 days |
| 520 | Glo (3) | SME | 3GB | 7 days |
| 426 | Glo (3) | SME | 3GB | 14 days |
| 427 | Glo (3) | SME | 5GB | 3 days |
| 428 | Glo (3) | SME | 5GB | 7 days |
| 429 | Glo (3) | SME | 5GB | 14 days |
| 430 | Glo (3) | SME | 10GB | 14 days |
| 601 | 9mobile (4) | GIFTING | 500MB | 30 days |
| 599 | 9mobile (4) | GIFTING | 500MB | 30 days |
| 602 | 9mobile (4) | GIFTING | 1GB | 30 days |
| 603 | 9mobile (4) | GIFTING | 2GB | 30 days |
| 604 | 9mobile (4) | GIFTING | 3GB | 30 days |
| 605 | 9mobile (4) | GIFTING | 4GB | 30 days |
| 606 | 9mobile (4) | GIFTING | 5GB | 30 days |
| 607 | 9mobile (4) | GIFTING | 10GB | 30 days |
| 597 | 9mobile (4) | SME | 1.1GB | 30 days |
| 598 | 9mobile (4) | SME | 2GB | 30 days |
Wallet balance
Your current wallet balance.
curl https://api.msub.ng/api/v1/merchant/balance -H "X-API-Key: YOUR_API_KEY"
{
"success": true,
"data": {
"wallet": { "id": 12, "balance": 25000.00, "currency": "NGN" }
}
}
List your plans
Every plan available to you, grouped by network, with your price.
dataplan_id is the Plan ID to send when buying.
curl https://api.msub.ng/api/v1/merchant/data/plans -H "X-API-Key: YOUR_API_KEY"
{
"success": true,
"data": {
"MTN_PLAN": [
{
"dataplan_id": "42",
"network": 1,
"plan_network": "MTN",
"plan_type": "SME",
"plan": "1GB",
"month_validate": "30 days",
"plan_amount": "280.00"
}
],
"AIRTEL_PLAN": [], "GLO_PLAN": [], "9MOBILE_PLAN": []
}
}
Buy data
Charges your wallet your price for the plan and sends the bundle to the number.
| Field | Type | Description |
|---|---|---|
plan | string | Plan ID from the plan list. Required. |
network | integer | Network ID (1 MTN, 2 Airtel, 3 Glo, 4 9mobile). Required. |
mobile_number | string | Recipient number, e.g. 08031234567. Required. |
curl -X POST https://api.msub.ng/api/v1/merchant/data/purchase \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{"plan": "42", "network": 1, "mobile_number": "08031234567"}'
$ch = curl_init('https://api.msub.ng/api/v1/merchant/data/purchase');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'X-API-Key: YOUR_API_KEY',
'Content-Type: application/json',
'Accept: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'plan' => '42',
'network' => 1,
'mobile_number' => '08031234567',
]),
]);
$result = json_decode(curl_exec($ch), true);
const res = await fetch("https://api.msub.ng/api/v1/merchant/data/purchase", {
method: "POST",
headers: {
"X-API-Key": process.env.MSUB_API_KEY,
"Content-Type": "application/json",
Accept: "application/json",
},
body: JSON.stringify({ plan: "42", network: 1, mobile_number: "08031234567" }),
});
const result = await res.json();
import requests
res = requests.post(
"https://api.msub.ng/api/v1/merchant/data/purchase",
headers={"X-API-Key": "YOUR_API_KEY", "Accept": "application/json"},
json={"plan": "42", "network": 1, "mobile_number": "08031234567"},
)
result = res.json()
Success 200
{
"success": true,
"message": "Purchase successful.",
"data": {
"reference": "MSUBUTIL-7KQ2M9XW4R8T1B5N3P",
"amount": 280.00,
"plan": "MTN 1GB 30 days",
"status": "success"
}
}
Still confirming 202
The network has not confirmed yet. Your wallet stays debited while we confirm; check
transaction status with the reference before retrying, so you don't buy twice.
{
"success": false,
"message": "This purchase is still being confirmed. It will be resolved shortly — your wallet has not been refunded yet.",
"data": { "reference": "MSUBUTIL-7KQ2M9XW4R8T1B5N3P", "status": "pending" }
}
Failed 409
The purchase did not go through and your wallet has been refunded. Safe to retry.
Transaction status
Look up a purchase by the reference you got back (or its numeric id).
status is pending, completed or failed.
curl https://api.msub.ng/api/v1/merchant/transactions/MSUBUTIL-7KQ2M9XW4R8T1B5N3P -H "X-API-Key: YOUR_API_KEY"
{
"success": true,
"data": {
"id": 9123,
"reference": "MSUBUTIL-7KQ2M9XW4R8T1B5N3P",
"amount": 280.00,
"type": "debit",
"status": "completed",
"category": "utility_data",
"phone_number": "08031234567",
"created_at": "2026-10-13T09:41:00+01:00"
}
}
Public plan IDs
The same plan list as above as JSON. No API key needed, and no prices. Handy for building your plan dropdown; refresh it daily as plans can change.
curl https://api.msub.ng/api/v1/public/data-plans
{
"success": true,
"data": [
{ "plan_id": "42", "network_id": 1, "network": "MTN", "plan_type": "SME",
"size": "1GB", "validity": "30 days", "name": "MTN 1GB 30 days" }
]
}
Responses & errors
| Status | Meaning |
|---|---|
| 200 | Success. |
| 202 | Purchase is still being confirmed. Do not retry; check its status. |
| 400 | Insufficient wallet balance. Fund your wallet and retry. |
| 401 | Missing, invalid or expired API key. |
| 404 | Transaction not found. |
| 409 | Purchase failed and your wallet was refunded. |
| 422 | Validation failed, or the plan is not available. Details are in errors. |
| 429 | Rate limit exceeded. Slow down and retry. |
{
"success": false,
"message": "Validation failed",
"data": null,
"errors": { "mobile_number": ["The mobile number field is required."] }
}
Need help? Contact Msub support from your dashboard.