REST API v1

Build on DataMobile

Sell data, airtime, cable TV and electricity from your own website, app, POS or bot. Simple JSON over HTTPS, paid from your wallet at your plan's prices.

Base URLhttps://datamobile.com.ng/api/v1.php

Quick start

  1. Upgrade to API Client. API access comes with that plan.
  2. Create a key in Dashboard > API Access. Lock it to your server IP.
  3. Fund your wallet. Every order is paid from your balance.
  4. Test it: call ?action=balance. You should get "status": "success".
curl -X GET "https://datamobile.com.ng/api/v1.php?action=balance" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"

Authentication

Send your key on every request as a Bearer token. You can also use the X-API-Key header.

Authorization: Bearer imk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Keep the key on your server. Never put it in a mobile app, browser JavaScript or a public repo. Anyone with your key can spend your wallet. If it leaks, revoke it and create a new one.

Responses & errors

Every response is JSON with a status field. Reads return success or error. Purchases return success, pending or failed; errors have a machine-readable code.

{
    "status": "error",
    "code": "insufficient_balance",
    "message": "Insufficient wallet balance. Please fund your wallet."
}
HTTPcodeMeaning
400bad_json / no_actionBody is not valid JSON or the action is missing.
401no_key / invalid_keyKey missing, wrong or revoked.
402insufficient_balanceFund your wallet and retry.
403ip_not_allowed / no_api_accessRequest IP not on the key whitelist, or your plan has no API access.
404unknown_action / not_foundWrong action name or the transaction does not exist.
405method_not_allowedUse GET for reads and POST for purchases.
422validation_error / request_id_required / network_mismatchA field is missing or wrong. See message and field.
429rate_limitedMore than 60 requests per minute. Wait and retry.
503service_unavailable / maintenanceService switched off or maintenance. Retry later.

request_id & retries

Every purchase needs your own unique request_id (your order ID). If you send the same request_id again, we do not charge you twice. You get the original transaction back with "duplicate": true.

  • Save the order in your database before calling us.
  • On a timeout, retry with the same request_id. It is always safe.
  • Store our reference. Support will ask for it.

Statuses & webhooks

success

Delivered. Complete the order. HTTP 200.

pending

Still with the network. HTTP 202. We confirm it automatically; check transaction or wait for the webhook.

failed

Not delivered and refunded to your wallet. Do not charge your customer.

Webhooks

Add a webhook URL to your key. When an order finishes we POST it to you (events transaction.success and transaction.failed), retrying up to 6 times over about 4 hours until you return HTTP 2xx.

{
    "event": "transaction.success",
    "sent_at": "2026-10-16T09:31:02+01:00",
    "data": {
        "reference": "IM20261016093012A1B2C3D4",
        "request_id": "ORDER_1001",
        "service": "data",
        "status": "success",
        "refunded": false,
        "product": "MTN 1GB SME",
        "recipient": "08031234567",
        "amount": 280,
        "face_value": 280,
        "message": "Delivered",
        "created_at": "2026-10-16T09:30:12+01:00",
        "updated_at": "2026-10-16T09:30:16+01:00"
    }
}

Check the X-Signature header: HMAC-SHA256 of the raw body with your webhook signing secret (shown on your API page).

$body = file_get_contents("php://input");
$sig  = hash_hmac("sha256", $body, "whsec_YOUR_SECRET");
if (!hash_equals($sig, $_SERVER["HTTP_X_SIGNATURE"] ?? "")) {
    http_response_code(401); exit;
}
$event = json_decode($body, true);
// update the order with $event["data"]["request_id"], then:
http_response_code(200);

Rate limits

Up to 60 requests per minute per key. Cache plan lists instead of fetching them before every sale. Over the limit you get HTTP 429 with a Retry-After header.

GET?action=ping

Test your key

Checks that your key, IP and plan are valid. Use it when setting up.

curl -X GET "https://datamobile.com.ng/api/v1.php?action=ping" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"
GET?action=balance

Wallet balance

Your main wallet balance. Every API purchase is paid from it.

curl -X GET "https://datamobile.com.ng/api/v1.php?action=balance" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"
GET?action=networks

Networks

Network codes, airtime limits and your airtime discount.

curl -X GET "https://datamobile.com.ng/api/v1.php?action=networks" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"
GET?action=data-plans

Data plans

Every active plan with its ID and YOUR price. Optional filters: network (mtn, airtel, glo, 9mobile) and type (SME, GIFTING, CORPORATE...). Cache it and refresh every 30 minutes.

FieldTypeRequiredDescription
networkstringNomtn, airtel, glo or 9mobile
typestringNoSME, GIFTING, CORPORATE, AWOOF...
curl -X GET "https://datamobile.com.ng/api/v1.php?action=data-plans" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"

Example IDs right now (prices shown are public prices, yours depend on your plan):

plan_idNetworkPlanPrice
1MTNMTN 500MB₦281.00
2MTNMTN 1GB₦481.00
3MTNMTN 1GB Pro₦605.00
4MTNMTN 2GB₦929.00
46MTNMTN 2GB premium₦983.00
6MTNMTN 3GB₦1,631.00
Full API price list with every plan_idLog in to see all IDs at your own price, with cable and disco codes. CSV download included.
GET?action=cable-plans

Cable bouquets

DStv, GOtv and StarTimes bouquets with IDs and your price. Optional filter provider.

FieldTypeRequiredDescription
providerstringNodstv, gotv or startimes
curl -X GET "https://datamobile.com.ng/api/v1.php?action=cable-plans" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"
GET?action=discos

Electricity companies

DISCO codes, minimum / maximum amount and your fee.

curl -X GET "https://datamobile.com.ng/api/v1.php?action=discos" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"
POST?action=data

Buy data

Sends a data bundle. The plan decides the network.

FieldTypeRequiredDescription
plan_idintegerYesID from data-plans
phonestringYes11-digit number, e.g. 08031234567
request_idstringYesYour unique order ID (6-80 chars)
networkstringNoIf sent, must match the plan (safety check)
curl -X POST "https://datamobile.com.ng/api/v1.php?action=data" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"plan_id":12,"phone":"08031234567","request_id":"ORDER_1001"}'
POST?action=airtime

Buy airtime

Tops up any number. Your discount is applied automatically.

FieldTypeRequiredDescription
networkstringYesmtn, airtel, glo or 9mobile
phonestringYes11-digit number
amountintegerYesWhole naira, within the network limits
request_idstringYesYour unique order ID
curl -X POST "https://datamobile.com.ng/api/v1.php?action=airtime" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"network":"mtn","phone":"08031234567","amount":500,"request_id":"ORDER_1002"}'
POST?action=cable

Pay cable TV

Renews a DStv, GOtv or StarTimes decoder. Always confirm the IUC number with your customer.

FieldTypeRequiredDescription
plan_idintegerYesID from cable-plans
iuc_numberstringYesSmartcard / IUC number
request_idstringYesYour unique order ID
curl -X POST "https://datamobile.com.ng/api/v1.php?action=cable" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"plan_id":31,"iuc_number":"7012345678","request_id":"ORDER_1003"}'
POST?action=electricity

Pay electricity

Prepaid token or postpaid bill. For prepaid, the token is in data.token.

FieldTypeRequiredDescription
discostringYesCode from discos, e.g. ikeja
meter_numberstringYesCustomer meter number
meter_typestringNoprepaid (default) or postpaid
amountintegerYesWhole naira
request_idstringYesYour unique order ID
curl -X POST "https://datamobile.com.ng/api/v1.php?action=electricity" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"disco":"ikeja","meter_number":"45012345678","meter_type":"prepaid","amount":2000,"request_id":"ORDER_1004"}'
GET?action=transaction

Transaction status

Look up one order by our reference or your request_id. Use it for pending orders.

FieldTypeRequiredDescription
referencestringOne ofOur reference
request_idstringOne ofYour request_id
curl -X GET "https://datamobile.com.ng/api/v1.php?action=transaction" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"
GET?action=transactions

Transaction history

Your latest orders, newest first.

FieldTypeRequiredDescription
statusstringNosuccess, pending or failed
servicestringNodata, airtime, cable, electricity
from / todateNoYYYY-MM-DD
limitintegerNo1-100 (default 50)
pageintegerNoPage number
curl -X GET "https://datamobile.com.ng/api/v1.php?action=transactions" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"

FAQ

Who can use the API?
API access comes with the API / top membership plan. Upgrade from your dashboard, then create a key on the API Access page.
What prices do I pay?
Your plan prices, the same you see on the dashboard. The data-plans and cable-plans endpoints always return your current price.
What happens when an order fails?
Failed orders are refunded to your wallet automatically and return status "failed". Never charge your customer for a failed order.
Is it safe to retry a request?
Yes, as long as you reuse the same request_id. We never charge the same request_id twice; you get the original transaction back.
Why is my order pending?
The network has not confirmed it yet. We keep checking automatically. Use the transaction endpoint or a webhook to get the final result.
Can I use the key in my mobile app?
No. Keep it on your server. Your app should call your server, and your server calls our API.