Skip to content

API Overview

Base URL: https://api.instapaybill.com Prefix: /api/v1

Every request and response is application/json (UTF-8). Request bodies are capped at 10 MB.


Endpoint map

Purchases

Method Path Service Auth
POST /airtime/buy Airtime API key
POST /data/buy Data bundle API key
POST /electricity/validate Meter validation API key
POST /electricity/buy Prepaid electricity API key
POST /cables/validate Smart card validation API key
POST /cables/buy Cable TV API key
POST /education/buy Result-checker PINs API key

Catalogue

Method Path Returns Auth
GET /data/agent-data Full agent catalogue (data plans + cable plans) API key
GET /data/networks Networks with active data plans API key
GET /data/networks/{network}/plans Plans for one network API key
GET /data/ Data plans API key
GET /cables/types Cable types API key
GET /cables/ Cable plans Public
GET /electricity/ Electricity discos API key
GET /education/ Education exam plans API key
GET /network/ Supported networks API key
GET /startime/ Startimes plans Public
GET /category/ Product categories Public
GET /network/validate-number/{phoneNumber} Carrier lookup for a number Public

Transactions and money

Method Path Auth
GET /transactions/ API key
GET /transactions/resolve API key
GET /transactions/success-rates API key
GET /wallet/manage-wallet-balance API key
GET /wallet/generate-wallet-reference API key
GET /user/ API key
GET /notification/ API key

Sandbox

All under /api/v1/sandbox — see Sandbox.

Method Path
POST /sandbox/airtime
POST /sandbox/data
POST /sandbox/electricity/validate
POST /sandbox/electricity
POST /sandbox/cables/validate
POST /sandbox/cables
POST /sandbox/education
POST /sandbox/startimes

Common request fields

Fields that apply to most purchase endpoints:

Field Type Notes
apiRefId string Your reference for the order. Stored only for API-channel requests. Look it up with GET /api/v1/transactions/resolve?apiRefID=….
pin string Wallet PIN. Ignored for API-key requests — only enforced on app/web channels.
promoCode / coupon string Discount codes. Not applied to API-channel requests.
type string Service-specific variant — vtu / share&sell / awuf4u for airtime, prepaid / postpaid for electricity.

apiRefId is the field most integrations get wrong. If you set it, you can always find the transaction later without scraping the transaction list.


Common response envelope

Every purchase endpoint returns the same shape:

{
  "msg": "MTN Airtime Purchase of ₦500 for 08012345678 was successful",
  "data": {
    "code": 200,
    "reference": "IP|TN|A|123|20260918120000_ASDFG",
    "description": "MTN Airtime Purchase",
    "message": "Top-up of ₦500 to 08012345678 delivered successfully.",
    "type": "airtime"
  },
  "code": 200
}
Field Type Notes
msg string Human-readable summary of the outcome.
data.code number 200 / 300 / 400. Mirrors the HTTP status.
data.reference string Your reference for the transaction. Save it.
data.description string What was bought, e.g. "MTN Airtime Purchase".
data.message string The outcome text. Safe to show a customer.
data.type string Service discriminator: airtime, data, electricity, cables, education.
code number Top-level business code. Same value as data.code.

Field availability by service

Not every service returns every field. Check before you depend on one.

Field Airtime Data Electricity Cables Education
data.code ✅ ✅ ✅ ✅ ✅
data.reference ✅ ✅ ✅ ✅ ✅
data.description ✅ ✅ ✅ ✅ ✅
data.message ✅ ✅ ✅ ✅ ✅
data.msg ✅ ✅ ✅ ❌ ✅
data.type ✅ ✅ ✅ ✅ ✅
data.token ❌ ❌ ✅ ❌ ❌
data.unit ❌ ❌ ✅ ❌ ❌
data.data_pin ❌ ❌ ❌ ❌ ✅

data.reference is your reference, not the provider's

The provider's own reference is overwritten with the platform's internal item_id before the response is sent. If you need the provider reference for reconciliation, read it from the transaction record via resolve.

The data shape differs by channel

When you authenticate with an API key, data is the compact envelope above. When you authenticate with a session JWT, data is the full transaction document — every internal field, including wallet balances before and after and the profit margin.

Always code against the API-key shape. If you need a field that only appears in the session shape, it is not part of the supported API contract.


Reference values

Networks

MTN, AIRTEL, GLO, T2MOBILE

Case-insensitive on input; the platform uppercases before use. 9MOBILE is accepted as a legacy alias for T2MOBILE in some catalogue responses but T2MOBILE is the canonical value.

{ "error": [{ "msg": "Invalid network", "path": "network", "suggesstions": ["MTN", "AIRTEL", "GLO", "T2MOBILE"] }] }

(The misspelled suggesstions key is the real field name.)

Electricity meter type

PREPAID, POSTPAID — case-insensitive.

Cable type

DSTV, GOTV, STARTIMES, SHOWMAX — uppercased before use.

Data plan identifiers

A data purchase needs the planId and the network:

{ "planId": "MTN-1.5GB-30D", "network": "MTN", "phone": "08012345678" }

planId alone is not enough — the plan lookup is { planId, network: network.toUpperCase() }. Omitting network produces "Plan Id not found", which reads like a bad plan id but is a missing field.

Retrieve valid identifiers from GET /api/v1/data/agent-data.


Product identifiers

The item_id returned as data.reference follows a fixed pattern:

IP|TN|<SERVICE>|<3-digit>|<YYYYMMDDHHmmssSSSS>_<5-char-suffix>
Segment Meaning
IP InstaPayBill
TN Transaction
A Airtime (also D data, E electricity, C cables, ED education)
123 Sequential counter
20260918120000 Timestamp, 14 digits, 100 µs resolution
ASDFG Random suffix

You do not need to construct or parse these. Treat them as opaque strings.


Health and status endpoints

Method Path Auth Returns
GET /mcp/health None { status, service, version, totalTools }
GET /mcp/tools None Array of { name, description }
GET /api/v1/settings/ None Public settings (commission rates, limits)
GET /api/v1/usecase/ None Feature flags and channel status
GET /api/v1/voice-assistant/health None Voice service health

GET /api/v1/usecase/ is the fastest way to see which features are currently enabled for a channel — including the kill switches that can make a purchase fail with 300 "Service is currently unavailable".


Making requests from a browser

CORS is restricted to an allowlist of known origins. The current allowlist includes https://instapaybill.com, https://www.instapaybill.com, https://admin.instapaybill.com, https://crm.instapaybill.com and https://developer.instapaybill.com.

Requests with no Origin header are always allowed. That covers server-to- server calls, CLI tools, and curl — you do not need to do anything special.

Browser calls from an origin outside the allowlist are blocked, and the CORS headers are omitted from the response. For browser-based integrations, proxy through your own backend rather than calling the API directly from the client — otherwise your live key would be exposed.