Build on NeratSubs
The NeratSubs API lets you sell airtime, data, electricity, cable TV, and social-media packages directly from your own platform, using the same wallet, pricing, and provider connections that power the NeratSubs app. Every endpoint below is documented against the live, production API — not a simplified or hypothetical version of it.
https://api.neratsub.com.ng/api
This API is account-based: you integrate as a NeratSubs user, using your own wallet balance to fund purchases you make on behalf of your customers. There is no separate "merchant" account type — any NeratSubs account can generate an API key and start integrating immediately.
Sandbox
Pick an endpoint, then send a real request straight from your browser to
api.neratsub.com.ng. This isn't a mockup — it's a live call
against the production API, using your own credentials. Purchase and voucher endpoints
spend real wallet balance.
Your personal API key, from Settings → API Access in the app.
Your key is used only for the request you send, never logged, and never sent anywhere but NeratSubs' own API — kept in this tab's session storage at most, cleared when you close it.
Authentication
Every request is authenticated with an API key, sent in the X-API-Key header.
Getting a key
API keys are generated from inside the NeratSubs app, not through this API — open the app, go to Settings → API Access, and tap Enable. The raw key is shown exactly once. If you lose it, generate a new one (this immediately invalidates the old one — there's no overlap period), or disable API access entirely from the same screen.
X-API-Key: your_api_key_here
NeratSubs stores only a one-way hash of your key — support cannot look up or recover a lost key for you, and neither can you retrieve it again from the app after the first time it's shown.
There is currently no way to scope a key to "purchases only." A key authenticates as your full NeratSubs account — the same as being logged into the app — and can move money from your wallet, change your account settings, and read your transaction history. Treat it like a password: never commit it to source control, never expose it to client-side/browser code, and rotate it immediately if it's ever leaked.
Requests & Responses
Every request body is JSON. Send Content-Type: application/json on any request with a body.
Response shape
Every response is plain JSON — the data directly, no wrapper envelope:
{ "user": { "...": "..." } }
// or { "transaction": "...", "balance": 12345 }, { "balance": 12345 }, etc.
// -- the exact shape is documented per endpoint below.On failure, a flat error message with no typed error code:
{ "error": "Incorrect PIN" }Check the HTTP status code to branch on the kind of failure — there is no separate code field to switch on.
Errors
HTTP status codes you'll actually see from this API:
| Status | Meaning |
|---|---|
| 400 | Request body failed validation, or a business rule rejected it (e.g. amount below minimum, insufficient balance). |
| 401 | Missing or invalid X-API-Key, or an incorrect transaction PIN. |
| 404 | The resource (transaction, voucher, route) doesn't exist, or doesn't belong to your account. |
| 409 | The request conflicts with existing state — a duplicate value, a voucher already redeemed, a virtual account already generated. |
| 429 | Rate limited — see Rate Limits. |
| 502 | The upstream network/disco/cable/SMM provider declined or errored. Your wallet is automatically refunded before this is returned. |
| 500 | Unexpected server error. Safe to retry. |
If a purchase's upstream provider declines or errors, you get a non-2xx response back and your wallet debit is reversed before the response is sent — you never need to poll or guess whether a refund is coming.
Rate Limits
Two limits apply, tracked separately. Everything not listed below is unthrottled.
The auth limit covers every /auth/* route, including
change-pin and change-password. The
purchases & vouchers limit covers every method under
/purchases and /vouchers — including the read-only
listing endpoints, not just the ones that spend money. Services, wallet, transactions,
account, and API-access endpoints have no endpoint-specific limit.
Unlike some APIs, a rate-limit rejection here uses the same { error } shape
as every other error — no special parsing needed. Standard rate-limit headers are included on every response:
RateLimit-Limit: 60 RateLimit-Policy: 60;w=3600 RateLimit-Remaining: 0 RateLimit-Reset: 1800
The full list of service types, providers, and fixed-price packages — fetch this to
know what providerId/packageId values are valid for a purchase.
The whole catalog is a few dozen rows, returned in one shot — no pagination or filtering params.
curl https://api.neratsub.com.ng/api/services \ -H "X-API-Key: your_api_key_here"
const res = await fetch("https://api.neratsub.com.ng/api/services", {
headers: { "X-API-Key": process.env.NERATSUBS_API_KEY }
});
const { serviceTypes, providers, packages } = await res.json();Response
{
"serviceTypes": ["airtime", "data", "electricity", "cable", "social"],
"providers": [
{ "id": "mtn", "serviceType": "airtime", "name": "MTN" },
{ "id": "mtn-data", "serviceType": "data", "name": "MTN" },
{ "id": "dstv", "serviceType": "cable", "name": "DStv" }
],
"packages": [
{ "id": "mtn-data-1gb-30d", "providerId": "mtn-data", "label": "1GB — 30 Days", "amount": 450, "category": "monthly" },
{ "id": "mtn-data-2gb-30d", "providerId": "mtn-data", "label": "2GB — 30 Days", "amount": 800, "category": "monthly" }
]
}
packages only applies to data, cable, and
social service types — airtime and electricity
are free-amount (you choose the amount at purchase time, see Buy a service).
Returns your account — name, username, email, balance, virtual account, referral code, and more. There is no separate "check balance" endpoint — use this, or Get wallet.
curl https://api.neratsub.com.ng/api/auth/me \ -H "X-API-Key: your_api_key_here"
const res = await fetch("https://api.neratsub.com.ng/api/auth/me", {
headers: { "X-API-Key": process.env.NERATSUBS_API_KEY }
});
const { user } = await res.json();
console.log(user.balance);Response
{
"user": {
"id": "68f1a2b3c4d5e6f7a8b9c0d1",
"name": "Jane Developer",
"username": "janedev",
"email": "you@example.com",
"balance": 15230,
"profileComplete": true,
"role": "user",
"referralCode": "JANE4F2A",
"virtualAccount": { "accountNumber": "8123456789", "bankName": "Providus Bank" },
"createdAt": "2026-01-14T09:22:11.000Z"
}
}Change your transaction PIN. Requires the current one.
| Field | Type | Notes | |
|---|---|---|---|
currentPin | string | required | Your current 4-digit PIN. |
newPin | string | required | 4 digits. |
curl -X POST https://api.neratsub.com.ng/api/auth/change-pin \
-H "X-API-Key: your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"currentPin":"1234","newPin":"5678"}'Change your login password. Requires the current one.
| Field | Type | Notes | |
|---|---|---|---|
currentPassword | string | required | |
newPassword | string | required | At least 6 characters. |
curl -X POST https://api.neratsub.com.ng/api/auth/change-password \
-H "X-API-Key: your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"currentPassword":"old_password","newPassword":"new_password_123"}'Check the status of your own upgrade request, if you have made one.
curl https://api.neratsub.com.ng/api/account/upgrade-request \ -H "X-API-Key: your_api_key_here"
Your referral code, how many people you have referred, and how much you have earned from it.
curl https://api.neratsub.com.ng/api/account/referral-stats \ -H "X-API-Key: your_api_key_here"
Buy airtime, data, electricity, cable, or a social-media package. For a package-based
service (data/cable/social), the price is
always the catalog price — amount is ignored. For
airtime/electricity, amount is required
and must meet the service minimum (₦1,000 for electricity, no minimum for airtime).
| Field | Type | Notes | |
|---|---|---|---|
serviceType | string | required | airtime | data | electricity | cable | social |
providerId | string | required | From List services. |
reference | string | required | Phone number (airtime/data), meter number (electricity), smartcard number (cable), or profile link (social). |
packageId | string | optional | Required for data/cable/social. |
amount | number | optional | Required for airtime/electricity. |
couponCode | string | optional | Applies a discount if valid. |
pin | string | required | Your 4-digit transaction PIN. |
curl -X POST https://api.neratsub.com.ng/api/purchases \
-H "X-API-Key: your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"serviceType": "data",
"providerId": "mtn-data",
"packageId": "mtn-data-1gb-30d",
"reference": "08031234567",
"pin": "1234"
}'const res = await fetch("https://api.neratsub.com.ng/api/purchases", {
method: "POST",
headers: {
"X-API-Key": process.env.NERATSUBS_API_KEY,
"Content-Type": "application/json"
},
body: JSON.stringify({
serviceType: "data",
providerId: "mtn-data",
packageId: "mtn-data-1gb-30d",
reference: "08031234567",
pin: "1234"
})
});
const { ok, transaction, balance } = await res.json();Response
{
"ok": true,
"transaction": {
"id": "68f9a1b2c3d4e5f6a7b8c9d1",
"kind": "purchase",
"serviceType": "data",
"providerName": "MTN",
"reference": "08031234567",
"amount": 450,
"status": "successful",
"date": "2026-10-05T11:02:00.000Z"
},
"balance": 14780
}List your transactions, newest first.
| Query param | Type | Notes | |
|---|---|---|---|
kind | string | optional | purchase | funding | voucher |
serviceType | string | optional | airtime | data | electricity | cable |
curl "https://api.neratsub.com.ng/api/transactions?kind=purchase" \ -H "X-API-Key: your_api_key_here"
Get one transaction by id.
curl https://api.neratsub.com.ng/api/transactions/68f9a1b2c3d4e5f6a7b8c9d1 \ -H "X-API-Key: your_api_key_here"
Get your balance and dedicated funding account (if you have generated one).
curl https://api.neratsub.com.ng/api/wallet \ -H "X-API-Key: your_api_key_here"
Response
{
"balance": 14780,
"virtualAccount": { "accountNumber": "8123456789", "bankName": "Providus Bank" }
}Generate a dedicated bank account number for funding your wallet by transfer — requires BVN or NIN verification. One per account; calling this again once generated is rejected with 409.
| Field | Type | Notes | |
|---|---|---|---|
idType | string | required | BVN or NIN |
idNumber | string | required | 11 digits, must match the account holder's name. |
curl -X POST https://api.neratsub.com.ng/api/wallet/virtual-account \
-H "X-API-Key: your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"idType":"BVN","idNumber":"12345678901"}'Response
{ "virtualAccount": { "accountNumber": "8123456789", "bankName": "Providus Bank" } }Confirm your PIN with no side effect — does not move money.
curl -X POST https://api.neratsub.com.ng/api/wallet/verify-pin \
-H "X-API-Key: your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"pin":"1234"}'Vouchers
Prepaid codes redeemable for wallet credit, airtime, data, electricity, or cable — create them to give away or resell, or redeem/use ones you have. Every voucher endpoint below is rate limited at 60/hour per account, same as purchases.
List vouchers you created.
curl https://api.neratsub.com.ng/api/vouchers \ -H "X-API-Key: your_api_key_here"
Create a voucher. Debits amountPerRedemption × maxRedemptions from your wallet immediately.
| Field | Type | Notes | |
|---|---|---|---|
type | string | required | wallet | airtime | data | electricity | cable |
providerId / packageId | string | optional | Required for non-wallet types, same rules as Buy a service. |
amount | number | optional | Required for wallet/airtime/electricity types. |
maxRedemptions | number | required | 1 to 1000. |
expiresAt | string | required | ISO date. |
message | string | optional | Up to 200 characters. |
code | string | optional | Custom voucher code; auto-generated if omitted. |
pin | string | required | Your 4-digit transaction PIN. |
curl -X POST https://api.neratsub.com.ng/api/vouchers \
-H "X-API-Key: your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"type": "wallet",
"amount": 500,
"maxRedemptions": 10,
"expiresAt": "2026-12-31T23:59:59.000Z",
"message": "Enjoy!",
"pin": "1234"
}'Response
{
"voucher": { "code": "ABC123", "type": "wallet", "amountPerRedemption": 500, "maxRedemptions": 10 },
"transaction": { "id": "...", "kind": "voucher", "amount": 5000, "status": "successful" },
"balance": 9780
}Preview a voucher by code before redeeming it — never reveals who created it.
curl https://api.neratsub.com.ng/api/vouchers/lookup/ABC123 \ -H "X-API-Key: your_api_key_here"
Redeem a voucher. Omitting reference claims it now and defers
delivery to Deliver a claimed voucher later.
wallet-type is always credited instantly.
| Field | Type | Notes | |
|---|---|---|---|
code | string | required | |
reference | string | optional | Phone/meter/smartcard — omit to defer delivery. |
pin | string | required | Your 4-digit transaction PIN. |
curl -X POST https://api.neratsub.com.ng/api/vouchers/redeem \
-H "X-API-Key: your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"code":"ABC123","reference":"08031234567","pin":"1234"}'Deliver a previously deferred redemption. No PIN — the creator already paid at redemption time.
curl -X POST https://api.neratsub.com.ng/api/vouchers/ABC123/use \
-H "X-API-Key: your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"reference":"08031234567"}'List vouchers you have redeemed as the claimant.
curl https://api.neratsub.com.ng/api/vouchers/redeemed \ -H "X-API-Key: your_api_key_here"
API Access
Manage this personal API key from the API itself — the same actions available in Settings → API Access in the app.
Check whether a key is enabled, and its prefix.
curl https://api.neratsub.com.ng/api/api-access \ -H "X-API-Key: your_api_key_here"
Generate a key (or rotate the existing one). The raw key is only ever shown in this response — there's also POST /api-access/regenerate, identical except it 400s if no key exists yet.
Response
{ "apiKey": "ns_live_3f9a1b2c4d5e6f7a8b9c0d1e2f3a4b5c", "status": "enabled" }Revoke your key immediately.
curl -X POST https://api.neratsub.com.ng/api/api-access/disable \ -H "X-API-Key: your_api_key_here"
Ready to integrate?
Open the NeratSubs app → Settings → API Access to generate your key.