GSUBZ API documentation
Sell airtime, data, cable TV, electricity tokens, exam pins and social media services from your own website or app, using your GSUBZ wallet.
https://api.gsubz.comBuilding with an AI assistant? Give it the Markdown or OpenAPI version of these docs, and it can write the integration for you.
OpenAPI Open in Claude Open in ChatGPTQuickstart
From zero to your first successful call in a few minutes.
- Create your account and fund your walletEvery API purchase is paid from your GSUBZ wallet, so add funds before you start.
- Copy your API keyOpen your dashboard key page and copy the key. It starts with
ap_. - Check your wallet balanceThis confirms your key works and costs nothing. Replace
YOUR_API_KEYwith your key.
curl --location 'https://api.gsubz.com/api/balance/' \ --header 'Authorization: Bearer YOUR_API_KEY' \ --form 'api="YOUR_API_KEY"'
<?php
$ch = curl_init('https://api.gsubz.com/api/balance/');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY'],
CURLOPT_POSTFIELDS => [
'api' => 'YOUR_API_KEY',
],
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
print_r($data);
const form = new FormData();
form.append("api", "YOUR_API_KEY");
const response = await fetch("https://api.gsubz.com/api/balance/", {
method: "POST",
headers: { Authorization: "Bearer YOUR_API_KEY" },
body: form,
});
const data = await response.json();
console.log(data);
import requests
url = "https://api.gsubz.com/api/balance/"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
payload = {
"api": "YOUR_API_KEY",
}
response = requests.post(url, headers=headers, data=payload, timeout=60)
print(response.json())
{
"balance": "747.5"
}
- Make your first purchase A typical data purchase takes three calls:
- Check your API pricesEvery plan from Get Plans shows two prices:
price, the normal price, andapi_price, what you pay through the API.
Authentication
Send your API key as a Bearer token in the Authorization header of every request, except Get Plans, List All Services, the eSIM country and package lists and the two game lists, which are public.
Authorization: Bearer YOUR_API_KEY
Most POST endpoints also take the same key in the api body field. Send both, exactly as the examples show. The Store endpoints take the Bearer header only.
Making requests
These conventions apply to every endpoint.
| Topic | Detail |
|---|---|
| Base URL | https://api.gsubz.com. Always use HTTPS. |
| Endpoint paths | Paths end with a trailing slash, for example /api/pay/. Use the URLs exactly as shown. |
| Request body | Form data: multipart/form-data or application/x-www-form-urlencoded. Every value is sent as text. The GET endpoints (Get Plans, List All Services, List Airports, the eSIM lists, the two game lists and every Store endpoint except Image Search) take their fields in the query string instead. Place an Order and Book a Flight also accept a JSON body (application/json), which is the easiest way to send their lists (items, passengers). |
| Response body | JSON, UTF-8 encoded. |
| Authentication | Header Authorization: Bearer YOUR_API_KEY. See Authentication above. |
| Phone numbers | 11-digit Nigerian format, for example 08031234567. |
| Money | Nigerian naira (₦). Send plain numbers: no ₦ symbol, commas or spaces (2400, not ₦2,400). |
| Dates and time | ISO 8601 with the West Africa Time offset, for example 2026-01-01T09:30:00+01:00. |
| Timeouts | A purchase can take a few seconds while the network or biller responds. Use a client timeout of at least 60 seconds. |
Responses
Every purchase returns the same flat JSON object. Check status first: successful means delivered and failed means it did not go through.
| Field | Type | Description |
|---|---|---|
code | integer | Result code. 200 means the request was processed. See Errors. |
status | string | Outcome of the purchase. successful means it was delivered. failed means it did not go through. |
transactionID | integer | GSUBZ's unique reference for this transaction. |
amount | number | Value of the purchase in naira (the plan price, or the amount you requested). |
phone | string | The phone number the purchase was made for, where the service uses one. |
serviceID | string | The service you bought. |
amountPaid | number | Amount deducted from your wallet, in naira, at your API price. It can be lower than amount. |
initialBalance | number | Wallet balance before the purchase. |
finalBalance | number | Wallet balance after the purchase. |
date | string | When the transaction was created (ISO 8601, West Africa Time). |
api_response | string | The message returned by the network or provider, for example the confirmation text for a recharge or data purchase. |
Errors
status field, not just the response code.| Code | status | description | Meaning | What to do |
|---|---|---|---|---|
200 |
successful |
— | The request was processed. A transaction can still fail with HTTP 200, so always read the status field. |
Deliver value only when status is successful. A purchase that did not go through returns failed. |
204 |
failed |
REQUIRED_CONTENT_NOT_SENT |
A required field is missing from your request. | Compare your request with the Parameters table for that endpoint. |
400 |
failed |
REQUIRED_CONTENT_REQUESTID_IS_EMPTY |
You sent neither requestID nor transactionID to Fetch Transaction Status. |
Send one of them. |
206 |
failed |
INVALID_CONTENT |
One of the fields has an invalid value. | Check the phone number, amount and service ID formats. |
401 |
failed |
INVALID_PLAN |
The plan or variation_code does not match the serviceID. |
Call Get Plans again and use a value from that list. |
401 |
failed |
INVALID_API_OR_NOT_FOUND |
The API key is missing or is not valid. | Send it as Authorization: Bearer YOUR_API_KEY, and copy it again from your dashboard if it still fails. |
402 |
failed |
INSUFFICIENT_BALANCE |
Your wallet balance is too low for this purchase. | Fund your wallet, then try again. |
404 |
failed |
CONTENT_NOT_FOUND |
The resource you asked for could not be found. | Check the URL and the reference you sent. |
405 |
failed |
REQUEST_METHOD_NOT_IN_POST |
You used GET where POST is required, or the other way round. | Use the method shown for the endpoint. |
406 |
failed |
SERVICE_DISABLED |
This service is temporarily disabled. | Try again later or use another service. |
406 |
successful or failed |
INVALID_ARGUMENTS_DUPLICATE_REQUEST_ID |
You already used this requestID. Nothing was charged again, and the response carries the original result. A requestID already used by another account is refused the same way, with no transaction details. |
Read the original result from the response, or send a new requestID for a new order. |
406 |
failed |
NOT_CANCELLABLE |
The eSIM cannot be cancelled, for example because it was already installed or already refunded. | Nothing was changed. Only an unused eSIM can be cancelled. |
404 |
failed |
PLAYER_NOT_FOUND |
The player ID you sent does not exist for that game. | Check the ID with the player. Nothing was charged. |
406 |
failed |
OUT_OF_STOCK |
That game product is out of stock right now. For a Store order: you asked for more than is in stock, and the response has available. |
Nothing was charged. Pick another amount or lower the quantity, or try again later. |
406 |
failed |
PRICE_CHANGED |
The price changed while your order was being placed. For a Store order: a product costs more than the price you sent, and the response lists currentPriceNgn for each item. |
Nothing was charged. Fetch the products again (List Game Products or Get Product Details) and retry. |
206 |
failed |
REGION_MISMATCH |
The player account is in a region that cannot receive this product. | Use the product line for the player's region. Nothing was charged. |
406 |
failed |
ORDER_FAILED |
The order could not be completed, and your wallet was refunded automatically. | The response carries the refunded order. Try another product or try again later. |
406 |
failed |
REQUEST_IN_PROGRESS |
An earlier request with this requestID has not finished yet. |
Look it up with Fetch Game Orders in a minute, or send a new requestID for a new order. |
206 |
failed |
BELOW_MINIMUM_ORDER |
A product needs more pieces (across its variants) than you ordered. The response has moq. |
Raise the quantity to at least moq. |
406 |
failed |
SEARCH_EXPIRED |
The flight search you are booking from is older than one hour (or is not yours). | Search again and pick a flight from the new results. Nothing was charged. |
406 |
failed |
QUOTE_EXPIRED |
The locked flight price expired (about 25 minutes) or was already used. | Call Book a Flight with preview=true for a new price. Nothing was charged. |
406 |
failed |
FARE_UNAVAILABLE |
The airline no longer offers that fare. | Search again and pick another flight. Nothing was charged. |
406 |
failed |
BOOKING_FAILED |
The airline could not issue the booking, and your wallet was refunded automatically. | Nothing was charged. Search again, or try another flight. |
406 |
failed |
CANCEL_NOT_ALLOWED |
The order or item can no longer be cancelled: more than 2 hours have passed, or it is already being processed or cancelled. | Nothing was changed. Contact support if something went wrong with the order. |
406 |
failed |
NOTHING_DUE |
No shipping fee is due on that order or item right now. | Nothing was charged. Check shipping.status in Get Orders. |
406 |
failed |
ACCOUNT_BLOCKED |
This account is blocked. | Contact support. |
407 |
failed |
Chat Admin to get upgraded before using our API, Thank you! |
Your account has not been upgraded for API use yet. | Contact support to be upgraded. The HTTP status for this one is 403. |
429 |
failed |
TOO_MANY_REQUESTS |
You sent too many requests in a short time. The Store endpoints allow 60 calls a minute for each API key, and flight searches 20. | Wait a minute, then try again. |
500 |
failed |
SERVER_ERROR |
Something went wrong on our side. Nothing was charged. | Try again. If it keeps happening, contact support. |
502 |
failed |
GATEWAY_ERROR |
The upstream provider did not respond. Safe to retry. | If you sent a requestID, check Fetch Transaction Status first, then retry. Store calls that fail this way are never charged. |
A failed request returns "status": "failed", the code, a description from the table above, and an api_response that explains in plain words what went wrong.
{
"code": 402,
"status": "failed",
"description": "INSUFFICIENT_BALANCE",
"api_response": "Your wallet balance is too low for this purchase"
}Best practices
Follow these before you go live. They prevent the most common problems, including charging a customer twice.
- Keep your API key on your server
Never put it in a mobile app, in website JavaScript or in a public repository. Call GSUBZ from your backend only. If a key is ever exposed, reset it from your dashboard.
- Send a unique requestID with every purchase
Use your own order or invoice number. It lets you look the transaction up later with Fetch Transaction Status. You can also look it up with the
transactionIDfrom the response, so save that too. - Read status, not just the HTTP code
A response can arrive with HTTP 200 and still describe a failed transaction. Treat a purchase as successful only when
statusissuccessful. A failed purchase returnsfailed. - Never resend a purchase blindly after a timeout
If a request times out or you get no response, the purchase may still have gone through. Look it up by
requestIDfirst, so you do not charge your customer twice. A purchase that takes longer than 10 seconds, or whose answer never reaches you, also sends its final result to your webhook astransaction.updated. - Fetch plans instead of hard-coding them
Plan values and prices can change. Call Get Plans and use the
valueit returns as yourplan(orvariation_code). - Verify meter and smartcard numbers before paying
Call Verify Meter / IUC Number so your customer can confirm their name before you charge them. It catches typing mistakes before money moves.
- Watch your wallet balance
Check Fetch Wallet Balance and top up before it runs low, so customers do not hit
INSUFFICIENT_BALANCE. - Treat processing game orders as unfinished
A game purchase can return
orderStatusprocessing. You have been charged, and the order ends ascompletedorrefunded. Wait for thegames.order.updatedwebhook, or check it with Fetch Game Orders, before you tell your customer it is done. - Cache Store results on your side
Every paid Store call is charged, even when you repeat the same request. Save search results and product details in your own database or cache, and refresh them only when you need to.
- Preview Store orders, and send a reference
Call Place an Order with
preview=trueto show your customer the exact total first. Then place it with your own uniquereference, so a retry after a timeout can never create a second order. - Preview a flight, then book it
Show your customer the price from Book a Flight with
preview=true, not the one from search, then book with thequoteIDand a uniquerequestID. A booking can beprocessingfor a while: wait for theflight.order.updatedwebhook before you tell your customer the ticket is issued. - Check every webhook's signature
Verify
X-Gsubz-Signaturewith your signing secret before you trust a webhook, answer2xxquickly, and ignore aneventIdyou have already handled. - Convert numbers before doing arithmetic
Amounts and balances are numbers in naira. Convert them yourself before doing arithmetic, in case a value ever arrives as text.
Webhooks
We send a POST with a JSON event to your webhook URL whenever something changes on an order you placed through the API: the final result of a slow purchase, a refund, a new status, a shipping fee after weighing, a tracking number, a flight ticket, a game order finishing, a cancellation and its refund.
Set your webhook URL and copy your signing secret on your key page. The URL must be
https://. One URL receives every event for your account.Webhooks are sent for orders you place through the API. Each one carries the whole order as it is now, so you never need a second call to know where things stand.
Answer with any
2xxstatus within 10 seconds. Save the event and do the slow work afterwards.If your server does not answer
2xx, we try again after about 1 minute, 5 minutes, 30 minutes, 2 hours, 6 hours and 24 hours (7 attempts in all). You can see every delivery, and resend failed ones, on your key page.The same event can arrive more than once, and events can arrive out of order. Use
eventIdto ignore repeats, and trust the newestorderortransactionyou have received (or call Get Orders or Fetch Transaction Status).
Headers
| Header | Meaning |
|---|---|
Content-Type | Always application/json. |
X-Gsubz-Event | The event name, for example store.order.updated. |
X-Gsubz-Delivery | The unique ID of this event (the same as eventId in the body). Retries of the same event keep the same ID, so use it to ignore duplicates. |
X-Gsubz-Timestamp | Unix time (seconds) when this attempt was sent. |
X-Gsubz-Signature | sha256= followed by the HMAC-SHA256 of timestamp + "." + raw body, made with your signing secret. |
Events
| Event | data.change.type | When |
|---|---|---|
transaction.updated | COMPLETED | The final result of a data, airtime, cable TV, electricity, exam pin or social media purchase (/api/pay/), sent when the call took longer than 10 seconds or the connection closed before our answer reached you. So a short timeout on your side never leaves you guessing. reason is SLOW_RESPONSE or CLIENT_DISCONNECTED, and processingSeconds is how long it took. Sent at most once per transaction. |
transaction.updated | REFUNDED | A purchase that had already answered was refunded to your wallet later, for example by our support team, or because the provider cancelled a social media order: from, to (failed), refundNgn and reason (ADMIN or PROVIDER_CANCELLED). The transaction's status is now failed and amountRefunded shows the refund. Sent at most once per transaction. |
store.order.updated | ORDER_PLACED | An order you placed through the API was created and paid. |
store.order.updated | STATUS | An item moved to a new status (from, to). A cancellation also carries refund (totalNgn, itemNgn, serviceFeeNgn, shippingNgn, deliveryNgn) and reason. |
store.order.updated | SHIPPING_FEE | An item was weighed and its shipping fee was set or changed (previousUnitNgn, unitNgn). The item's shipping in order has the new weightKg, volumeCbm and dueNgn. Pay with Pay Shipping when dueNgn is more than 0. |
store.order.updated | SHIPPING_METHOD | An item had to switch between air and sea (from, to), with its new fee and any refund (refundNgn). |
store.order.updated | SHIPPING_PAID | Shipping you paid was received (items, amountNgn). |
store.order.updated | TRACKING | The delivery tracking number for the pickup station was added (trackingNumber). |
flight.order.updated | CONFIRMED | A flight you booked was confirmed. order carries the pnr and tickets when they are already issued. |
flight.order.updated | TICKETED | The PNR and e-ticket numbers arrived after the booking was confirmed. |
flight.order.updated | REFUNDED | A flight booking failed or was cancelled by the airline, and your wallet was refunded: reason (FAILED or CANCELLED) and refundNgn. |
games.order.updated | STATUS | A game order that was still processing when Buy Game Top-up answered has finished (from, to). to is completed (any gift-card codes are in order) or refunded (your wallet was refunded). Not sent when the purchase response already gave the final result. |
webhook.test | - | Sent when you press "Send test event" on your key page. |
Every event has event, eventId, createdAt and data. Transaction events carry data.change (what happened) and data.transaction: the purchase as it is now, with the fields of the purchase response plus requestID, description and amountRefunded. Store order events carry data.change (what happened) and data.order: the whole order as it is now, in the same format as Get Orders. Flight events carry data.change and data.order in the format of Fetch Flight Orders. Game events carry data.change and data.order in the format of one order from Fetch Game Orders.
Example body
Data, airtime and bills (a refund)
{
"event": "transaction.updated",
"eventId": "evt_7d41c2b9e0a35f6d8c12ab90",
"createdAt": "2026-10-19T10:20:05+01:00",
"data": {
"change": { "type": "REFUNDED", "from": "successful", "to": "failed", "refundNgn": 2284.56, "reason": "ADMIN" },
"transaction": {
"transactionID": 3878886201,
"requestID": "8dhbc8w7huwh8hw9hew9",
"serviceID": "mtn_sme",
"status": "failed",
"description": "TRANSACTION_REVERSED",
"amount": 2400,
"amountPaid": 0,
"amountRefunded": 2284.56,
"phone": "08031234567",
"initialBalance": 5000,
"finalBalance": 2715.44,
"date": "2026-10-19T09:47:15+01:00",
"api_response": "Dear Customer, You have successfully shared 10GB Data to 2348031234567. Thankyou"
}
}
}Store order
{
"event": "store.order.updated",
"eventId": "evt_8f2c1d0a9b7e6f5a4c3b2a19",
"createdAt": "2026-10-16T13:02:44+01:00",
"data": {
"change": { "type": "SHIPPING_FEE", "itemId": 88121, "previousUnitNgn": 0, "unitNgn": 13068 },
"order": {
"orderId": 5231,
"reference": "ORDER-10045",
"amounts": { "itemsNgn": 14100, "serviceFeeNgn": 1900, "shippingPaidNgn": 16676, "shippingDueNgn": 13068, "deliveryNgn": 2400 },
"items": [
{
"itemId": 88121,
"status": "PAID",
"shipping": { "method": "air", "weightKg": 0.9, "volumeCbm": 0.001, "status": "due", "unitNgn": 13068, "totalNgn": 13068, "paidNgn": 0, "dueNgn": 13068 }
}
]
}
}
}Flight booking
{
"event": "flight.order.updated",
"eventId": "evt_3c9a77d1b0e24f6a8d15c2e7",
"createdAt": "2026-10-17T11:04:10+01:00",
"data": {
"change": { "type": "CONFIRMED" },
"order": {
"transactionID": "TRV261017110002AB12CD34",
"requestID": "flight-1001",
"orderStatus": "completed",
"origin": "LOS",
"destination": "ABV",
"departureDate": "2026-12-01",
"amountPaid": 95000,
"pnr": "ABC123",
"tickets": [
{ "name": "Ada Obi", "type": "ADT", "ticketNumber": "1234567890123" }
]
}
}
}Game order
{
"event": "games.order.updated",
"eventId": "evt_5b1e93c0d7a24f88b6e01c4d",
"createdAt": "2026-10-17T13:54:33+01:00",
"data": {
"change": { "type": "STATUS", "from": "processing", "to": "completed" },
"order": {
"orderID": 15,
"transactionID": "GM261007113015A1B2C3D4",
"requestID": "game-1001",
"game": "Free Fire · Direct Topup Mena",
"product": "100 Diamonds",
"amount": 1520,
"amountPaid": 1520,
"amountRefunded": 0,
"orderStatus": "completed",
"playerName": "ProGamer99",
"codes": [],
"date": "2026-10-07T11:30:15+01:00"
}
}
}Check the signature
Always check X-Gsubz-Signature before you trust a webhook, using the raw body exactly as received.
PHP
<?php
$secret = 'whsec_...'; // from your key page
$body = file_get_contents('php://input'); // the RAW body, before json_decode
$ts = $_SERVER['HTTP_X_GSUBZ_TIMESTAMP'] ?? '';
$sig = $_SERVER['HTTP_X_GSUBZ_SIGNATURE'] ?? '';
$expected = 'sha256=' . hash_hmac('sha256', $ts . '.' . $body, $secret);
if (!hash_equals($expected, $sig) || abs(time() - (int)$ts) > 300) {
http_response_code(401);
exit;
}
$event = json_decode($body, true);
// Save it, skip it if you already have $event['eventId'], then do the work later.
http_response_code(200);
echo 'ok';Node.js
// Express: use the raw body for the signature
app.post('/gsubz/webhook', express.raw({ type: 'application/json' }), (req, res) => {
const ts = req.get('X-Gsubz-Timestamp');
const expected = 'sha256=' + crypto.createHmac('sha256', process.env.GSUBZ_WEBHOOK_SECRET)
.update(ts + '.' + req.body).digest('hex');
const got = req.get('X-Gsubz-Signature') || '';
if (got.length !== expected.length || !crypto.timingSafeEqual(Buffer.from(got), Buffer.from(expected))) {
return res.sendStatus(401);
}
const event = JSON.parse(req.body);
// Save it, skip it if you already have event.eventId, then do the work later.
res.send('ok');
});Service IDs
Use the serviceID exactly as shown, including capitals and underscores. This list is generated live from our system, so it is always current. Click a row to copy its ID. Want this in a single API call instead? See List All Services.
Airtime 4 services
| Service | serviceID |
|---|---|
| Airtel Airtime | airtel |
| Glo Airtime | glo |
| MTN Airtime | mtn |
| T2 (formerly 9mobile) Airtime | etisalat |
Data Subscription 6 services
| Service | serviceID |
|---|---|
| Airtel Gifting Data | airtel_gifting |
| Airtel SME Data | airtel_sme |
| Glo Corporate Gifting Data | glo_data |
| Glo SME Data | glo_sme |
| MTN Gifting Data | mtn_gifting |
| MTN SME Data | mtn_sme |
Education (Result Pins) 3 services
| Service | serviceID |
|---|---|
| NABTEB Result Pin | nabteb |
| NECO Result Pin | neco |
| WAEC Result Pin | waec |
Electricity Billl 12 services
| Service | serviceID |
|---|---|
| Aba (ABEDC/APL) | aba-electric |
| Abuja (AEDC) | abuja-electric |
| Benin (BEDC) | benin-electric |
| Eko (EKEDC) | eko-electric |
| Enugu (EEDC) | enugu-electric |
| Ibadan (IBEDC) | ibadan-electric |
| Ikeja (IKEDC) | ikeja-electric |
| Jos (JEDC) | jos-electric |
| Kaduna KAEDCO) | kaduna-electric |
| Kano (KEDCO) | kano-electric |
| Port Harcourt (PHED) | portharcourt-electric |
| Yola (YEDC) | yola-electric |
Pro Services/Apps 1 service
| Service | serviceID |
|---|---|
| Canva Pro | canva |
Socials Media Market 1 service
| Service | serviceID |
|---|---|
| Socials Media Market | socials |
TV Subscriptions 3 services
| Service | serviceID |
|---|---|
| DSTV | dstv |
| GOTV | gotv |
| Startimes | startimes |
Uncategorised 1 service
| Service | serviceID |
|---|---|
| MTN-SME-Datashare | mtn_datashare |
API reference
| Method | Endpoint | What it does |
|---|---|---|
| POST | /api/balance/ Fetch Wallet Balance |
Get your current wallet balance in naira. |
| GET | /api/category/ List All Services |
List every active service, grouped by category. |
| GET | /api/plans/ Get Plans |
List the plans, and their prices, for any data, cable TV or social media service. |
| POST | /api/verify-customer/ Verify Meter / IUC Number |
Check an electricity meter or cable smartcard number and get the customer name before paying. |
| POST | /api/pay/ Buy Data |
Send a data bundle to a phone number. |
| POST | /api/pay/ Buy Airtime |
Send airtime to a phone number on MTN, Airtel, 9mobile or Glo. |
| POST | /api/pay/ Buy TV / Decoder / Cable Sub |
Renew a DStv, GOtv or StarTimes subscription. |
| POST | /api/pay/ Buy Electric Token |
Buy a prepaid electricity token or pay a postpaid electricity bill. |
| POST | /api/pay/ Buy Exam Pin |
Buy a WAEC, NECO or NABTEB result checker or registration pin. |
| POST | /api/pay/ Buy Social Media Service |
Place a social media order such as followers or likes. |
| POST | /api/generate/ Recharge Pins / Epins Printing |
Generate recharge card pins for MTN, Airtel, Glo or 9mobile. |
| GET | /api/generate/history/ Fetch Recharge Pin Orders |
List your last 200 recharge pin orders, or fetch one order with its pins. |
| GET | /api/esim/countries/ List eSIM Countries |
List the countries and regions you can buy an eSIM for. |
| GET | /api/esim/packages/ List eSIM Packages |
List the eSIM packages for a country, cheapest first, priced in naira. |
| POST | /api/esim/buy/ Buy eSIM |
Buy an eSIM package and get its QR code and activation code. |
| POST | /api/esim/orders/ Fetch eSIM Orders |
Look up your eSIM orders, or check one that was still being prepared. |
| POST | /api/esim/cancel/ Cancel eSIM |
Cancel an eSIM that has not been installed and get your money back. |
| GET | /api/games/list/ List Games |
List the games and gift-card brands on sale, with the lowest price of each. |
| GET | /api/games/products/ List Game Products |
List the product lines, required fields and prices for one game. |
| POST | /api/games/validate/ Validate Player ID |
Check a player ID, and get the player's name, before you charge for a top-up. |
| POST | /api/games/buy/ Buy Game Top-up |
Top up a game account, or buy a gift card, and get the result or the codes. |
| POST | /api/games/orders/ Fetch Game Orders |
Look up your game orders, or check one that was still processing. |
| POST | /api/sms/ Send Bulk SMS |
Send one text message to many Nigerian phone numbers. |
| GET | /api/flight/search/ List Airports |
Find the airport codes to search with. Free. |
| POST | /api/flight/search/ Search Flights |
Search one-way or return flights and get priced options. Free. |
| POST | /api/flight/book/ Book a Flight |
Lock the final price, or book the flight and pay from your wallet. preview=true only returns the price. |
| POST | /api/flight/orders/ Fetch Flight Orders |
Look up a flight booking, or check one that was still processing. Free. |
| GET | /api/store/search/ Search Products |
Browse trending products, the Gsubz Official Store, or search the whole product catalogue by keyword. |
| POST | /api/store/image-search/ Search Products by Image |
Find products that look like a photo you send. |
| GET | /api/store/product/ Get Product Details |
Get everything the store shows for one product: media, price tiers, variants, specs and shipping data. |
| GET | /api/store/supplier/ Get Supplier Products |
List the products of one supplier, 20 at a time. |
| GET | /api/store/categories/ List Categories and Brands |
Get the store's category tree and the Official Store brands. Free. |
| GET | /api/store/order/ List Pickup Stations |
Get the pickup stations an order can be delivered to, with their delivery fees. Free. |
| POST | /api/store/order/ Place an Order |
Buy products for your customer, paid from your wallet. preview=true only returns the price. |
| GET | /api/store/order/ Get Orders |
Get one order by order_id or reference, or a page of your orders. Free. |
| POST | /api/store/order/ Cancel an Order |
Cancel a whole order, or one item, within 2 hours of ordering. Refunded to your wallet. |
| POST | /api/store/order/ Pay Shipping |
Pay shipping that became due after an item was weighed. |
| POST | /api/verify/ Fetch Transaction Status |
Look up the status and response of a purchase using its requestID or transactionID. |
All purchases (data, airtime, cable, electricity, exam pins and social media) use the same POST /api/pay/ endpoint. The serviceID you send decides what is bought. eSIMs have their own endpoints under /api/esim/, bulk SMS uses POST /api/sms/, game top-ups and gift cards have their own endpoints under /api/games/, and the product store has its own endpoints under /api/store/, where /api/store/order/ places and manages orders.
Wallet
Returns your current wallet balance in naira (₦). Check it before a purchase so you can top up before a transaction fails with INSUFFICIENT_BALANCE.
| Body field | Description |
|---|---|
api
string
Required |
Your API key. Send the same key you use in the Authorization header. Example:
YOUR_API_KEY |
Try it live
Sent only to GSUBZ, through this page's server. We never store it. It stays in this browser tab until you close it.
About the response. balance is returned as a string. Convert it to a number before doing arithmetic.
curl --location 'https://api.gsubz.com/api/balance/' \ --header 'Authorization: Bearer YOUR_API_KEY' \ --form 'api="YOUR_API_KEY"'
<?php
$ch = curl_init('https://api.gsubz.com/api/balance/');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY'],
CURLOPT_POSTFIELDS => [
'api' => 'YOUR_API_KEY',
],
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
print_r($data);
const form = new FormData();
form.append("api", "YOUR_API_KEY");
const response = await fetch("https://api.gsubz.com/api/balance/", {
method: "POST",
headers: { Authorization: "Bearer YOUR_API_KEY" },
body: form,
});
const data = await response.json();
console.log(data);
import requests
url = "https://api.gsubz.com/api/balance/"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
payload = {
"api": "YOUR_API_KEY",
}
response = requests.post(url, headers=headers, data=payload, timeout=60)
print(response.json())
{
"balance": "747.5"
}
Services
Returns every active serviceID GSUBZ offers, grouped under its category — data, cable TV, electricity, social media and so on. Call this once to build a full picture of what's available, then use Get Plans for a specific service's pricing. No parameters: it always returns everything in one response, so filter or sort on your side.
Try it live
This endpoint is public, so no API key is needed.
About the response. A category with no active services still appears, with an empty services array. image is null when the category has no icon set. This list is cached for up to 60 seconds, so a change can take up to a minute to show here.
curl --location 'https://api.gsubz.com/api/category/'
<?php
$ch = curl_init('https://api.gsubz.com/api/category/');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
print_r($data);
const response = await fetch("https://api.gsubz.com/api/category/");
const data = await response.json();
console.log(data);
import requests
url = "https://api.gsubz.com/api/category/"
payload = {
}
response = requests.get(url, params=payload, timeout=60)
print(response.json())
[
{
"name": "electricity",
"displayName": "Electricity",
"image": "//gsubz.com/uploads/2021/9/1/electric-icon.png",
"services": [
{
"serviceID": "eko-electric",
"displayName": "Eko (EKEDC)"
},
{
"serviceID": "kaduna-electric",
"displayName": "Kaduna Electric"
}
]
},
{
"name": "cable",
"displayName": "Cable TV",
"image": "//gsubz.com/uploads/2021/9/1/cable-icon.png",
"services": [
{
"serviceID": "gotv",
"displayName": "GOtv"
}
]
}
]
Plans
One shared endpoint for every category's plan list: data, cable TV, social media and more. Pass the service you want and get back that service's plans. Call it before a purchase to get the correct plan value. Every plan shows its normal price and its api_price, the price you pay through the API.
- The plan identifier is returned in a field called
PlanName, and its value tells you which body field to submit when buying. Data and social media services useplan. Cable TV services usevariation_code.
| Query parameter | Description |
|---|---|
service
string
Required |
The service ID, for example mtn_sme. Also accepts cable (gotv, dstv, startimes) and social media (socials) service IDs. See Service IDs. Example:
mtn_sme |
This sends a real GET /api/plans/ request, so you see an actual response before you write any code.
About the response. Use value as your plan (or variation_code) when you buy. price is the normal price and api_price is the price you pay through the API, both in naira. discount is your API discount on this service.
curl --location 'https://api.gsubz.com/api/plans/?service=mtn_sme'
<?php
$ch = curl_init('https://api.gsubz.com/api/plans/?service=mtn_sme');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
print_r($data);
const response = await fetch("https://api.gsubz.com/api/plans/?service=mtn_sme");
const data = await response.json();
console.log(data);
import requests
url = "https://api.gsubz.com/api/plans/"
payload = {
"service": "mtn_sme",
}
response = requests.get(url, params=payload, timeout=60)
print(response.json())
{
"service": "MTN-SME-Data(*461*4#)",
"PlanName": "plan",
"fixedPrice": true,
"discount": "4.81%",
"plans": [
{
"displayName": "10GB - 30days",
"value": "260",
"price": "2400",
"api_price": "2284.56"
}
]
}
Verify Customer
Checks a meter number or a cable smartcard/IUC number before payment and returns the customer's name (and, for electricity meters, their address and account type). Always verify before you charge: it catches typing mistakes before money moves.
- For electricity services,
typeis required:prepaidorpostpaid. For cable services (dstv,gotv,startimes), leavetypeout.
| Body field | Description |
|---|---|
api
string
Required |
Your API key. Send the same key you use in the Authorization header. Example:
YOUR_API_KEY |
serviceID
string
Required |
Any electricity or cable service ID: see the list below, or dstv, gotv, startimes for cable. Underscores and hyphens both work, so kaduna_electric and kaduna-electric are the same. Example:
kaduna_electric |
billersCode
string
Required |
The meter number (electricity) or smartcard/IUC number (cable). Example:
00000000000 |
type
string
Electricity only |
prepaid or postpaid. Required for electricity, omit for cable. Example:
prepaid |
Try it live
Sent only to GSUBZ, through this page's server. We never store it. It stays in this browser tab until you close it.
About the response. Some fields, such as accountType, can be null when the provider does not send them. Cable verification returns customerName, status, dueDate, customerNumber and customerType instead of the address and meter fields. Both shapes are under content, so you can always read customerName the same way.
curl --location 'https://api.gsubz.com/api/verify-customer/' \ --header 'Authorization: Bearer YOUR_API_KEY' \ --form 'api="YOUR_API_KEY"' \ --form 'serviceID="kaduna_electric"' \ --form 'billersCode="00000000000"' \ --form 'type="prepaid"'
<?php
$ch = curl_init('https://api.gsubz.com/api/verify-customer/');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY'],
CURLOPT_POSTFIELDS => [
'api' => 'YOUR_API_KEY',
'serviceID' => 'kaduna_electric',
'billersCode' => '00000000000',
'type' => 'prepaid',
],
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
print_r($data);
const form = new FormData();
form.append("api", "YOUR_API_KEY");
form.append("serviceID", "kaduna_electric");
form.append("billersCode", "00000000000");
form.append("type", "prepaid");
const response = await fetch("https://api.gsubz.com/api/verify-customer/", {
method: "POST",
headers: { Authorization: "Bearer YOUR_API_KEY" },
body: form,
});
const data = await response.json();
console.log(data);
import requests
url = "https://api.gsubz.com/api/verify-customer/"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
payload = {
"api": "YOUR_API_KEY",
"serviceID": "kaduna_electric",
"billersCode": "00000000000",
"type": "prepaid",
}
response = requests.post(url, headers=headers, data=payload, timeout=60)
print(response.json())
{
"code": 200,
"status": "successful",
"description": "CUSTOMER_FOUND",
"content": {
"customerName": "JOHN ADEBAYO",
"address": "12 SAMPLE STREET, IKEJA",
"meterNumber": "45000000000",
"meterType": "PREPAID",
"accountType": null,
"canVend": "yes"
}
}
{
"code": 404,
"status": "failed",
"description": "CONTENT_NOT_FOUND",
"api_response": "Could not verify this meter number"
}
Data & Airtime
Send a data bundle to any Nigerian phone number. Call Get Plans with the network's serviceID first to get the exact plan value, then submit it here. The data service IDs are listed under Service IDs.
| Body field | Description |
|---|---|
serviceID
string
Required |
The data service ID, for example mtn_sme. Example:
mtn_sme |
plan
string
Required |
The plan value from Get Plans for this service. Example:
260 |
api
string
Required |
Your API key. Send the same key you use in the Authorization header. Example:
YOUR_API_KEY |
amount
string
Required |
Send as an empty string. The price is set by the plan. Example: empty string
|
phone
string
Required |
The phone number to receive the data. Example:
08031234567 |
requestID
string
Optional |
Your own unique reference for this order (for example your order ID). Use it later with Fetch Transaction Status. Example:
8dhbc8w7huwh8hw9hew9 |
Try it live
Sent only to GSUBZ, through this page's server. We never store it. It stays in this browser tab until you close it.
About the response. Values are examples. Read status (successful or failed) to know the outcome, and see Responses for every field.
curl --location 'https://api.gsubz.com/api/pay/' \ --header 'Authorization: Bearer YOUR_API_KEY' \ --form 'serviceID="mtn_sme"' \ --form 'plan="260"' \ --form 'api="YOUR_API_KEY"' \ --form 'amount=""' \ --form 'phone="08031234567"' \ --form 'requestID="8dhbc8w7huwh8hw9hew9"'
<?php
$ch = curl_init('https://api.gsubz.com/api/pay/');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY'],
CURLOPT_POSTFIELDS => [
'serviceID' => 'mtn_sme',
'plan' => '260',
'api' => 'YOUR_API_KEY',
'amount' => '',
'phone' => '08031234567',
'requestID' => '8dhbc8w7huwh8hw9hew9',
],
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
print_r($data);
const form = new FormData();
form.append("serviceID", "mtn_sme");
form.append("plan", "260");
form.append("api", "YOUR_API_KEY");
form.append("amount", "");
form.append("phone", "08031234567");
form.append("requestID", "8dhbc8w7huwh8hw9hew9");
const response = await fetch("https://api.gsubz.com/api/pay/", {
method: "POST",
headers: { Authorization: "Bearer YOUR_API_KEY" },
body: form,
});
const data = await response.json();
console.log(data);
import requests
url = "https://api.gsubz.com/api/pay/"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
payload = {
"serviceID": "mtn_sme",
"plan": "260",
"api": "YOUR_API_KEY",
"amount": "",
"phone": "08031234567",
"requestID": "8dhbc8w7huwh8hw9hew9",
}
response = requests.post(url, headers=headers, data=payload, timeout=60)
print(response.json())
{
"code": 200,
"status": "successful",
"transactionID": 3878886201,
"amount": 2400,
"phone": "08031234567",
"serviceID": "mtn_sme",
"amountPaid": 2284.56,
"initialBalance": 5000,
"finalBalance": 2715.44,
"date": "2026-09-28T09:47:15+01:00",
"api_response": "Dear Customer, You have successfully shared 10GB Data to 2348031234567. Thankyou"
}
Send airtime to any Nigerian number. The serviceID must be one of mtn, airtel, etisalat (9mobile) or glo: lowercase, spelt exactly as shown.
| Body field | Description |
|---|---|
serviceID
string
Required |
mtn, airtel, etisalat (9mobile) or glo. Example:
mtn |
api
string
Required |
Your API key. Send the same key you use in the Authorization header. Example:
YOUR_API_KEY |
amount
string
Required |
Amount of airtime in naira. The minimum is ₦100. Example:
100 |
phone
string
Required |
The phone number to receive the airtime. Example:
08031234567 |
requestID
string
Optional |
Your own unique reference for this order (for example your order ID). Use it later with Fetch Transaction Status. Example:
8dhbc8w7huwh8hw9hew9 |
Try it live
Sent only to GSUBZ, through this page's server. We never store it. It stays in this browser tab until you close it.
About the response. Values are examples. Read status (successful or failed) to know the outcome, and see Responses for every field.
curl --location 'https://api.gsubz.com/api/pay/' \ --header 'Authorization: Bearer YOUR_API_KEY' \ --form 'serviceID="mtn"' \ --form 'api="YOUR_API_KEY"' \ --form 'amount="100"' \ --form 'phone="08031234567"' \ --form 'requestID="8dhbc8w7huwh8hw9hew9"'
<?php
$ch = curl_init('https://api.gsubz.com/api/pay/');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY'],
CURLOPT_POSTFIELDS => [
'serviceID' => 'mtn',
'api' => 'YOUR_API_KEY',
'amount' => '100',
'phone' => '08031234567',
'requestID' => '8dhbc8w7huwh8hw9hew9',
],
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
print_r($data);
const form = new FormData();
form.append("serviceID", "mtn");
form.append("api", "YOUR_API_KEY");
form.append("amount", "100");
form.append("phone", "08031234567");
form.append("requestID", "8dhbc8w7huwh8hw9hew9");
const response = await fetch("https://api.gsubz.com/api/pay/", {
method: "POST",
headers: { Authorization: "Bearer YOUR_API_KEY" },
body: form,
});
const data = await response.json();
console.log(data);
import requests
url = "https://api.gsubz.com/api/pay/"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
payload = {
"serviceID": "mtn",
"api": "YOUR_API_KEY",
"amount": "100",
"phone": "08031234567",
"requestID": "8dhbc8w7huwh8hw9hew9",
}
response = requests.post(url, headers=headers, data=payload, timeout=60)
print(response.json())
{
"code": 200,
"status": "successful",
"transactionID": 3768661863,
"amount": 800,
"phone": "08031234567",
"serviceID": "mtn",
"amountPaid": 768,
"initialBalance": 5000,
"finalBalance": 4232,
"date": "2026-09-28T09:47:15+01:00",
"api_response": "You have topped up N800.00 to 2348031234567. ref: 2026092809402519057879292"
}
Cable TV
Renew a DStv, GOtv or StarTimes subscription. The serviceID must be gotv, dstv or startimes. Verify the smartcard/IUC number with Verify Meter / IUC Number first.
- For cable, Get Plans returns the package identifier as
variation_code. Send that value in thevariation_codefield.
| Body field | Description |
|---|---|
serviceID
string
Required |
dstv, gotv or startimes. Example:
gotv |
api
string
Required |
Your API key. Send the same key you use in the Authorization header. Example:
YOUR_API_KEY |
variation_code
string
Required |
The package from Get Plans (service=gotv, dstv or startimes). Example:
gotv-smallie |
phone
string
Required |
Customer phone number. Can be any valid number. Example:
08031234567 |
amount
string
Required |
Send as an empty string. The price is set by the plan. Example: empty string
|
customerID
string
Required |
The IUC or smartcard number of the decoder. Example:
0000000000 |
requestID
string
Optional |
Your own unique reference for this order (for example your order ID). Use it later with Fetch Transaction Status. Example:
8dhbc8w7huwh8hw9hew9 |
Try it live
Sent only to GSUBZ, through this page's server. We never store it. It stays in this browser tab until you close it.
About the response. Values are examples. Read status (successful or failed) to know the outcome, and see Responses for every field.
curl --location 'https://api.gsubz.com/api/pay/' \ --header 'Authorization: Bearer YOUR_API_KEY' \ --form 'serviceID="gotv"' \ --form 'api="YOUR_API_KEY"' \ --form 'variation_code="gotv-smallie"' \ --form 'phone="08031234567"' \ --form 'amount=""' \ --form 'customerID="0000000000"' \ --form 'requestID="8dhbc8w7huwh8hw9hew9"'
<?php
$ch = curl_init('https://api.gsubz.com/api/pay/');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY'],
CURLOPT_POSTFIELDS => [
'serviceID' => 'gotv',
'api' => 'YOUR_API_KEY',
'variation_code' => 'gotv-smallie',
'phone' => '08031234567',
'amount' => '',
'customerID' => '0000000000',
'requestID' => '8dhbc8w7huwh8hw9hew9',
],
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
print_r($data);
const form = new FormData();
form.append("serviceID", "gotv");
form.append("api", "YOUR_API_KEY");
form.append("variation_code", "gotv-smallie");
form.append("phone", "08031234567");
form.append("amount", "");
form.append("customerID", "0000000000");
form.append("requestID", "8dhbc8w7huwh8hw9hew9");
const response = await fetch("https://api.gsubz.com/api/pay/", {
method: "POST",
headers: { Authorization: "Bearer YOUR_API_KEY" },
body: form,
});
const data = await response.json();
console.log(data);
import requests
url = "https://api.gsubz.com/api/pay/"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
payload = {
"serviceID": "gotv",
"api": "YOUR_API_KEY",
"variation_code": "gotv-smallie",
"phone": "08031234567",
"amount": "",
"customerID": "0000000000",
"requestID": "8dhbc8w7huwh8hw9hew9",
}
response = requests.post(url, headers=headers, data=payload, timeout=60)
print(response.json())
{
"code": 200,
"status": "successful",
"transactionID": 3685573902,
"amount": 900,
"phone": "08031234567",
"serviceID": "gotv",
"amountPaid": 882,
"initialBalance": 5000,
"finalBalance": 4118,
"date": "2026-09-28T09:47:15+01:00",
"api_response": "Your GOtv subscription was successful."
}
Electricity
Generate an electricity token (prepaid) or pay a postpaid bill for any supported distribution company. Verify the meter number first with Verify Meter / IUC Number so your customer sees their own name before you charge them.
| Body field | Description |
|---|---|
serviceID
string
Required |
The distribution company service ID. See the list below. Example:
kaduna_electric |
api
string
Required |
Your API key. Send the same key you use in the Authorization header. Example:
YOUR_API_KEY |
phone
string
Required |
Customer phone number. Can be any valid number. Example:
08031234567 |
customerID
string
Required |
The meter number. Example:
00000000000 |
amount
string
Required |
Amount of electricity to buy, in naira. Example:
1100 |
variation_code
string
Required |
prepaid or postpaid. Example:
prepaid |
requestID
string
Optional |
Your own unique reference for this order (for example your order ID). Use it later with Fetch Transaction Status. Example:
8dhbc8w7huwh8hw9hew9 |
Try it live
Sent only to GSUBZ, through this page's server. We never store it. It stays in this browser tab until you close it.
About the response. Values are examples. Read status (successful or failed) to know the outcome, and see Responses for every field.
curl --location 'https://api.gsubz.com/api/pay/' \ --header 'Authorization: Bearer YOUR_API_KEY' \ --form 'serviceID="kaduna_electric"' \ --form 'api="YOUR_API_KEY"' \ --form 'phone="08031234567"' \ --form 'customerID="00000000000"' \ --form 'amount="1100"' \ --form 'variation_code="prepaid"' \ --form 'requestID="8dhbc8w7huwh8hw9hew9"'
<?php
$ch = curl_init('https://api.gsubz.com/api/pay/');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY'],
CURLOPT_POSTFIELDS => [
'serviceID' => 'kaduna_electric',
'api' => 'YOUR_API_KEY',
'phone' => '08031234567',
'customerID' => '00000000000',
'amount' => '1100',
'variation_code' => 'prepaid',
'requestID' => '8dhbc8w7huwh8hw9hew9',
],
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
print_r($data);
const form = new FormData();
form.append("serviceID", "kaduna_electric");
form.append("api", "YOUR_API_KEY");
form.append("phone", "08031234567");
form.append("customerID", "00000000000");
form.append("amount", "1100");
form.append("variation_code", "prepaid");
form.append("requestID", "8dhbc8w7huwh8hw9hew9");
const response = await fetch("https://api.gsubz.com/api/pay/", {
method: "POST",
headers: { Authorization: "Bearer YOUR_API_KEY" },
body: form,
});
const data = await response.json();
console.log(data);
import requests
url = "https://api.gsubz.com/api/pay/"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
payload = {
"serviceID": "kaduna_electric",
"api": "YOUR_API_KEY",
"phone": "08031234567",
"customerID": "00000000000",
"amount": "1100",
"variation_code": "prepaid",
"requestID": "8dhbc8w7huwh8hw9hew9",
}
response = requests.post(url, headers=headers, data=payload, timeout=60)
print(response.json())
{
"code": 200,
"status": "successful",
"transactionID": 3574357094,
"amount": 1100,
"phone": "08031234567",
"serviceID": "kaduna_electric",
"amountPaid": 1100,
"initialBalance": 5000,
"finalBalance": 3900,
"date": "2026-09-28T09:47:15+01:00",
"api_response": "Token: 47488383838383838383833"
}
Exam Pins
Buy an exam pin. The serviceID must be waec, neco or nabteb: lowercase, spelt exactly as shown. Each exam service has one plan.
| Body field | Description |
|---|---|
serviceID
string
Required |
waec, neco or nabteb. Example:
waec |
plan
string
Required |
The plan for the exam service. There is one plan per service; for WAEC it is waecdirect. Example:
waecdirect |
api
string
Required |
Your API key. Send the same key you use in the Authorization header. Example:
YOUR_API_KEY |
amount
string
Required |
Send as an empty string. The price is set by the plan. Example: empty string
|
phone
string
Required |
Customer phone number. Example:
08031234567 |
requestID
string
Optional |
Your own unique reference for this order. Use it later with Fetch Transaction Status. Example:
87dfhw8dbw8e7hw9d9dh |
Try it live
Sent only to GSUBZ, through this page's server. We never store it. It stays in this browser tab until you close it.
About the response. Values are examples. Read status (successful or failed) to know the outcome, and see Responses for every field.
curl --location 'https://api.gsubz.com/api/pay/' \ --header 'Authorization: Bearer YOUR_API_KEY' \ --form 'serviceID="waec"' \ --form 'plan="waecdirect"' \ --form 'api="YOUR_API_KEY"' \ --form 'amount=""' \ --form 'phone="08031234567"' \ --form 'requestID="87dfhw8dbw8e7hw9d9dh"'
<?php
$ch = curl_init('https://api.gsubz.com/api/pay/');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY'],
CURLOPT_POSTFIELDS => [
'serviceID' => 'waec',
'plan' => 'waecdirect',
'api' => 'YOUR_API_KEY',
'amount' => '',
'phone' => '08031234567',
'requestID' => '87dfhw8dbw8e7hw9d9dh',
],
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
print_r($data);
const form = new FormData();
form.append("serviceID", "waec");
form.append("plan", "waecdirect");
form.append("api", "YOUR_API_KEY");
form.append("amount", "");
form.append("phone", "08031234567");
form.append("requestID", "87dfhw8dbw8e7hw9d9dh");
const response = await fetch("https://api.gsubz.com/api/pay/", {
method: "POST",
headers: { Authorization: "Bearer YOUR_API_KEY" },
body: form,
});
const data = await response.json();
console.log(data);
import requests
url = "https://api.gsubz.com/api/pay/"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
payload = {
"serviceID": "waec",
"plan": "waecdirect",
"api": "YOUR_API_KEY",
"amount": "",
"phone": "08031234567",
"requestID": "87dfhw8dbw8e7hw9d9dh",
}
response = requests.post(url, headers=headers, data=payload, timeout=60)
print(response.json())
{
"code": 200,
"status": "successful",
"transactionID": 3075647209,
"amount": 3500,
"phone": "08031234567",
"serviceID": "waec",
"amountPaid": 3500,
"initialBalance": 5000,
"finalBalance": 1500,
"date": "2026-09-28T09:47:15+01:00",
"api_response": "968686868685<=>WRN2056666666"
}
Social Media Market
Place a social media order. The serviceID is always socials. Call Get Plans with service=socials first to get the plan value for the service you want (for example Instagram followers or TikTok likes).
| Body field | Description |
|---|---|
serviceID
string
Required |
Always socials. Example:
socials |
plan
string
Required |
The plan value from Get Plans (service=socials). Example:
179 |
api
string
Required |
Your API key. Send the same key you use in the Authorization header. Example:
YOUR_API_KEY |
amount
string
Required |
Send as an empty string. The price is set by the plan. Example: empty string
|
link
string
Required |
The profile or post URL the order should be delivered to. Example:
https://instagram.com/gsubzonline |
quantity
integer
Required |
How many to deliver. Must be a positive whole number. Example:
1000 |
requestID
string
Optional |
Your own unique reference for this order (for example your order ID). Use it later with Fetch Transaction Status. Example:
8dhbc8w7huwh8hw9hew9 |
Try it live
Sent only to GSUBZ, through this page's server. We never store it. It stays in this browser tab until you close it.
About the response. Values are examples. Read status (successful or failed) to know the outcome, and see Responses for every field.
curl --location 'https://api.gsubz.com/api/pay/' \ --header 'Authorization: Bearer YOUR_API_KEY' \ --form 'serviceID="socials"' \ --form 'plan="179"' \ --form 'api="YOUR_API_KEY"' \ --form 'amount=""' \ --form 'link="https://instagram.com/gsubzonline"' \ --form 'quantity="1000"' \ --form 'requestID="8dhbc8w7huwh8hw9hew9"'
<?php
$ch = curl_init('https://api.gsubz.com/api/pay/');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY'],
CURLOPT_POSTFIELDS => [
'serviceID' => 'socials',
'plan' => '179',
'api' => 'YOUR_API_KEY',
'amount' => '',
'link' => 'https://instagram.com/gsubzonline',
'quantity' => '1000',
'requestID' => '8dhbc8w7huwh8hw9hew9',
],
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
print_r($data);
const form = new FormData();
form.append("serviceID", "socials");
form.append("plan", "179");
form.append("api", "YOUR_API_KEY");
form.append("amount", "");
form.append("link", "https://instagram.com/gsubzonline");
form.append("quantity", "1000");
form.append("requestID", "8dhbc8w7huwh8hw9hew9");
const response = await fetch("https://api.gsubz.com/api/pay/", {
method: "POST",
headers: { Authorization: "Bearer YOUR_API_KEY" },
body: form,
});
const data = await response.json();
console.log(data);
import requests
url = "https://api.gsubz.com/api/pay/"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
payload = {
"serviceID": "socials",
"plan": "179",
"api": "YOUR_API_KEY",
"amount": "",
"link": "https://instagram.com/gsubzonline",
"quantity": "1000",
"requestID": "8dhbc8w7huwh8hw9hew9",
}
response = requests.post(url, headers=headers, data=payload, timeout=60)
print(response.json())
{
"code": 200,
"status": "successful",
"transactionID": 3075647200,
"amount": 179,
"serviceID": "socials",
"amountPaid": 179,
"initialBalance": 5000,
"finalBalance": 4821,
"date": "2026-09-28T09:47:15+01:00",
"api_response": "Order received. Order ID: 39554883"
}
Recharge Pins
Generate recharge card pins for printing. The network must be mtn, airtel, glo or 9mobile: lowercase, spelt exactly as shown. This endpoint authenticates with the Authorization header only.
- If you get
UNABLE_TO_PROCESS_REQUEST, or no response at all, do not resend the order straight away. Check Fetch Recharge Pin Orders first: if the order is listed, it went through and your pins are there. Only send a new order when it is not listed.
| Body field | Description |
|---|---|
network
string
Required |
mtn, airtel, glo or 9mobile. Example:
airtel |
value
string
Required |
Face value of each pin in naira: 100, 200, 400 or 500. Example:
500 |
number
string
Required |
How many pins to generate. The minimum is 10 for values below 500. Example:
1 |
Try it live
Sent only to GSUBZ, through this page's server. We never store it. It stays in this browser tab until you close it.
About the response. delivered and pending show how many pins have been issued so far. Each item in pins has the pin and its serial number sn.
curl --location 'https://api.gsubz.com/api/generate/' \ --header 'Authorization: Bearer YOUR_API_KEY' \ --form 'network="airtel"' \ --form 'value="500"' \ --form 'number="1"'
<?php
$ch = curl_init('https://api.gsubz.com/api/generate/');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY'],
CURLOPT_POSTFIELDS => [
'network' => 'airtel',
'value' => '500',
'number' => '1',
],
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
print_r($data);
const form = new FormData();
form.append("network", "airtel");
form.append("value", "500");
form.append("number", "1");
const response = await fetch("https://api.gsubz.com/api/generate/", {
method: "POST",
headers: { Authorization: "Bearer YOUR_API_KEY" },
body: form,
});
const data = await response.json();
console.log(data);
import requests
url = "https://api.gsubz.com/api/generate/"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
payload = {
"network": "airtel",
"value": "500",
"number": "1",
}
response = requests.post(url, headers=headers, data=payload, timeout=60)
print(response.json())
{
"message": "We Received your order, 1 of 1 delivered\n Thank you for your patronage",
"status": "success",
"id": "c143e774874a59623aa928292d128f97",
"network": "Airtel",
"value": "500",
"number": "1",
"delivered": "1",
"pending": 0,
"pins": [
{
"pin": "5794977707301520",
"sn": "26026825914918714922"
}
]
}
Returns your recent Recharge Pins orders, newest first, so you can compare them with your own records. If an order timed out or its response never reached you, the pins are here: read them from this endpoint instead of resending the order. Send an order_id to get just one order. This endpoint is free and authenticates with the Authorization header only. It also accepts POST.
- Every order comes with its
pins(thepinand its serial numbersn), so you can save any you did not receive. A long list can be large: uselimitfor fewer orders, ororder_idfor one. Sendpins=0if you only want the order details. order_idis theidreturned when you placed the order.
| Query parameter | Description |
|---|---|
limit
integer
Optional |
How many orders to return, from 1 to 200. The default is 200. Example:
200 |
order_id
string
Optional |
Return only this order, with its pins. Use the id from the order response. Example:
c143e774874a59623aa928292d128f97 |
pins
string
Optional |
Pins are included by default. Send 0 to leave them out. Example:
0 |
Try it live
Sent only to GSUBZ, through this page's server. We never store it. It stays in this browser tab until you close it.
About the response. status is success when every pin you asked for was delivered, partial when only some were, and failed when none were. requested and delivered are pin counts. pins lists every pin issued for the order, and is empty for an order that failed.
curl --location 'https://api.gsubz.com/api/generate/history/' \ --header 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.gsubz.com/api/generate/history/');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY'],
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
print_r($data);
const response = await fetch("https://api.gsubz.com/api/generate/history/", {
headers: { Authorization: "Bearer YOUR_API_KEY" },
});
const data = await response.json();
console.log(data);
import requests
url = "https://api.gsubz.com/api/generate/history/"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
payload = {
}
response = requests.get(url, headers=headers, params=payload, timeout=60)
print(response.json())
{
"code": "200",
"status": "TRANSACTION_SUCCESSFUL",
"count": 1,
"orders": [
{
"order_id": "c143e774874a59623aa928292d128f97",
"description": "Airtel-500-1 28/09/2026",
"network": "airtel",
"value": "500",
"requested": 1,
"delivered": 1,
"amount_paid": "485",
"status": "success",
"timestamp": 1790585235,
"date": "2026-09-28 09:47:15",
"pins": [
{
"pin": "5794977707301520",
"sn": "26026825914918714922"
}
]
}
]
}
{
"code": "404",
"description": "ORDER_NOT_FOUND",
"status": "TRANSACTION_FAILED"
}
eSIM
An eSIM gives your customer mobile data in another country without a physical SIM card. Start here: list the countries, pick one, then call List eSIM Packages with its locationCodes. This list is public and needs no API key.
| Query parameter | Description |
|---|---|
q
string
Optional |
Search text to filter countries by name, for example fra for France. Leave it out to list every country. Example:
fra |
Try it live
This endpoint is public, so no API key is needed.
About the response. locationCodes can hold more than one code, separated by commas. Send the whole value as locationCode to List eSIM Packages. plans is how many packages exist for that country.
curl --location 'https://api.gsubz.com/api/esim/countries/?q=fra'
<?php
$ch = curl_init('https://api.gsubz.com/api/esim/countries/?q=fra');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
print_r($data);
const response = await fetch("https://api.gsubz.com/api/esim/countries/?q=fra");
const data = await response.json();
console.log(data);
import requests
url = "https://api.gsubz.com/api/esim/countries/"
payload = {
"q": "fra",
}
response = requests.get(url, params=payload, timeout=60)
print(response.json())
{
"code": 200,
"status": "successful",
"countries": [
{
"country": "France",
"locationCodes": "FR",
"plans": 12
},
{
"country": "Spain",
"locationCodes": "ES",
"plans": 9
}
]
}
Returns the data packages for one country, cheapest first. Use the packageCode of the one your customer wants when you call Buy eSIM. This list is public and needs no API key.
priceis in naira and can change slightly between this list and your purchase, because the live price is checked when you buy. ReadamountPaidin the purchase response for what was actually charged.
| Query parameter | Description |
|---|---|
locationCode
string
Required |
The locationCodes value from List eSIM Countries. You can send up to twenty codes, separated by commas. Example:
FR |
Try it live
This endpoint is public, so no API key is needed.
About the response. dataGB is the data allowance and duration is how long the package lasts, in durationUnit. A package with refundable set to false cannot be cancelled for a refund. topUp shows whether more data can be added later.
curl --location 'https://api.gsubz.com/api/esim/packages/?locationCode=FR'
<?php
$ch = curl_init('https://api.gsubz.com/api/esim/packages/?locationCode=FR');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
print_r($data);
const response = await fetch("https://api.gsubz.com/api/esim/packages/?locationCode=FR");
const data = await response.json();
console.log(data);
import requests
url = "https://api.gsubz.com/api/esim/packages/"
payload = {
"locationCode": "FR",
}
response = requests.get(url, params=payload, timeout=60)
print(response.json())
{
"code": 200,
"status": "successful",
"packages": [
{
"packageCode": "FR_1_7",
"name": "France 1GB 7Days",
"country": "France",
"dataGB": 1,
"duration": 7,
"durationUnit": "DAY",
"price": 2607,
"refundable": true,
"topUp": true
}
]
}
Buys one eSIM. Your wallet is charged and the eSIM details come back in the response: scan the qrCodeUrl image or type the activationCode into the phone to install it.
- Always send a
requestID. If you send the same one again, the API returns the original order (code406,INVALID_ARGUMENTS_DUPLICATE_REQUEST_ID) and never charges twice. - If
esimStatusisprovisioning, the eSIM is still being prepared. Call Fetch eSIM Orders in a minute to get the QR code and activation code. You have already been charged.
| Body field | Description |
|---|---|
api
string
Required |
Your API key. Send the same key you use in the Authorization header. Example:
YOUR_API_KEY |
packageCode
string
Required |
The packageCode from List eSIM Packages. Example:
FR_1_7 |
requestID
string
Optional |
Your own unique reference for this order, up to 100 characters. Use it later with Fetch eSIM Orders. Example:
esim-1001 |
Try it live
Sent only to GSUBZ, through this page's server. We never store it. It stays in this browser tab until you close it.
About the response. esimStatus is active when the eSIM is ready to install, or provisioning while it is still being prepared (then iccid, activationCode and qrCodeUrl are null). Keep orderID: you need it to cancel or look the order up.
curl --location 'https://api.gsubz.com/api/esim/buy/' \ --header 'Authorization: Bearer YOUR_API_KEY' \ --form 'api="YOUR_API_KEY"' \ --form 'packageCode="FR_1_7"' \ --form 'requestID="esim-1001"'
<?php
$ch = curl_init('https://api.gsubz.com/api/esim/buy/');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY'],
CURLOPT_POSTFIELDS => [
'api' => 'YOUR_API_KEY',
'packageCode' => 'FR_1_7',
'requestID' => 'esim-1001',
],
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
print_r($data);
const form = new FormData();
form.append("api", "YOUR_API_KEY");
form.append("packageCode", "FR_1_7");
form.append("requestID", "esim-1001");
const response = await fetch("https://api.gsubz.com/api/esim/buy/", {
method: "POST",
headers: { Authorization: "Bearer YOUR_API_KEY" },
body: form,
});
const data = await response.json();
console.log(data);
import requests
url = "https://api.gsubz.com/api/esim/buy/"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
payload = {
"api": "YOUR_API_KEY",
"packageCode": "FR_1_7",
"requestID": "esim-1001",
}
response = requests.post(url, headers=headers, data=payload, timeout=60)
print(response.json())
{
"code": 200,
"status": "successful",
"transactionID": "ESIMA0BA0EC673A45212",
"orderID": 1,
"amount": 3476,
"serviceID": "esim",
"amountPaid": 3476,
"initialBalance": 100000,
"finalBalance": 96524,
"date": "2026-09-28T12:36:59+01:00",
"api_response": "Your eSIM is ready. Scan the QR code or enter the activation code to install it.",
"requestID": "esim-1001",
"packageCode": "FR_1_7",
"packageName": "France 1GB 7Days",
"country": "France",
"esimStatus": "active",
"iccid": "8944500102030405060",
"activationCode": "LPA:1$rsp.example.com$ABCD-1234-EFGH",
"qrCodeUrl": "https://example.com/qr/ORD-123"
}
{
"code": 402,
"status": "failed",
"description": "INSUFFICIENT_BALANCE",
"api_response": "Insufficient balance. This eSIM costs ₦3,476.00 but your wallet has ₦100.00."
}
Returns your eSIM orders. Send a requestID or an orderID to get one order, or send neither to list your last 50. An order that was still being prepared is checked again each time you call, so this is also how you collect the QR code after a provisioning purchase.
| Body field | Description |
|---|---|
api
string
Required |
Your API key. Send the same key you use in the Authorization header. Example:
YOUR_API_KEY |
requestID
string
Optional |
The requestID you sent when you bought the eSIM. Example:
esim-1001 |
orderID
integer
Optional |
The orderID from the purchase response. Example:
1 |
Try it live
Sent only to GSUBZ, through this page's server. We never store it. It stays in this browser tab until you close it.
About the response. esimStatus is one of active, provisioning, refunded or failed. amountRefunded shows what was returned to your wallet, if anything.
curl --location 'https://api.gsubz.com/api/esim/orders/' \ --header 'Authorization: Bearer YOUR_API_KEY' \ --form 'api="YOUR_API_KEY"' \ --form 'requestID="esim-1001"' \ --form 'orderID="1"'
<?php
$ch = curl_init('https://api.gsubz.com/api/esim/orders/');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY'],
CURLOPT_POSTFIELDS => [
'api' => 'YOUR_API_KEY',
'requestID' => 'esim-1001',
'orderID' => '1',
],
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
print_r($data);
const form = new FormData();
form.append("api", "YOUR_API_KEY");
form.append("requestID", "esim-1001");
form.append("orderID", "1");
const response = await fetch("https://api.gsubz.com/api/esim/orders/", {
method: "POST",
headers: { Authorization: "Bearer YOUR_API_KEY" },
body: form,
});
const data = await response.json();
console.log(data);
import requests
url = "https://api.gsubz.com/api/esim/orders/"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
payload = {
"api": "YOUR_API_KEY",
"requestID": "esim-1001",
"orderID": "1",
}
response = requests.post(url, headers=headers, data=payload, timeout=60)
print(response.json())
{
"code": 200,
"status": "successful",
"orders": [
{
"orderID": 1,
"transactionID": "ESIMA0BA0EC673A45212",
"packageCode": "FR_1_7",
"packageName": "France 1GB 7Days",
"country": "France",
"amountPaid": 3476,
"amountRefunded": 0,
"esimStatus": "active",
"iccid": "8944500102030405060",
"activationCode": "LPA:1$rsp.example.com$ABCD-1234-EFGH",
"qrCodeUrl": "https://example.com/qr/ORD-123",
"date": "2026-09-28T12:36:59+01:00"
}
]
}
{
"code": 404,
"status": "failed",
"description": "CONTENT_NOT_FOUND",
"api_response": "No eSIM order found for that reference."
}
Cancels an eSIM that has not been installed and returns what you paid to your wallet. It can only work once for each order.
NOT_CANCELLABLE and nothing is refunded.| Body field | Description |
|---|---|
api
string
Required |
Your API key. Send the same key you use in the Authorization header. Example:
YOUR_API_KEY |
orderID
integer
Required |
The orderID from the purchase response or from Fetch eSIM Orders. Example:
1 |
Try it live
Sent only to GSUBZ, through this page's server. We never store it. It stays in this browser tab until you close it.
curl --location 'https://api.gsubz.com/api/esim/cancel/' \ --header 'Authorization: Bearer YOUR_API_KEY' \ --form 'api="YOUR_API_KEY"' \ --form 'orderID="1"'
<?php
$ch = curl_init('https://api.gsubz.com/api/esim/cancel/');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY'],
CURLOPT_POSTFIELDS => [
'api' => 'YOUR_API_KEY',
'orderID' => '1',
],
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
print_r($data);
const form = new FormData();
form.append("api", "YOUR_API_KEY");
form.append("orderID", "1");
const response = await fetch("https://api.gsubz.com/api/esim/cancel/", {
method: "POST",
headers: { Authorization: "Bearer YOUR_API_KEY" },
body: form,
});
const data = await response.json();
console.log(data);
import requests
url = "https://api.gsubz.com/api/esim/cancel/"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
payload = {
"api": "YOUR_API_KEY",
"orderID": "1",
}
response = requests.post(url, headers=headers, data=payload, timeout=60)
print(response.json())
{
"code": 200,
"status": "successful",
"orderID": 1,
"amountRefunded": 3476,
"initialBalance": 96524,
"finalBalance": 100000,
"date": "2026-09-28T12:37:22+01:00",
"api_response": "Refunded ₦3,476.00."
}
{
"code": 406,
"status": "failed",
"description": "NOT_CANCELLABLE",
"api_response": "This eSIM cannot be cancelled. It may already be in use."
}
Games
Top up a player's game account or sell a gift card. Start here: list the games and brands on sale, most popular first, then call List Game Products with the gameID you want. This list is public and needs no API key.
| Query parameter | Description |
|---|---|
q
string
Optional |
Search text to filter by name, for example free for Free Fire. Leave it out to list everything. Example:
free |
Try it live
This endpoint is public, so no API key is needed.
About the response. lines is how many product lines the game has (for example one per region) and products is how many amounts or packs you can buy. fromPrice is the lowest price in naira. note is an important message about the game, or null. image is null when the game has no logo. The example is shortened.
curl --location 'https://api.gsubz.com/api/games/list/?q=free'
<?php
$ch = curl_init('https://api.gsubz.com/api/games/list/?q=free');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
print_r($data);
const response = await fetch("https://api.gsubz.com/api/games/list/?q=free");
const data = await response.json();
console.log(data);
import requests
url = "https://api.gsubz.com/api/games/list/"
payload = {
"q": "free",
}
response = requests.get(url, params=payload, timeout=60)
print(response.json())
{
"code": 200,
"status": "successful",
"games": [
{
"gameID": 12,
"name": "Free Fire",
"image": "https://gsubz.com/uploads/gaming/free-fire.png",
"note": null,
"lines": 2,
"products": 24,
"fromPrice": 1440
},
{
"gameID": 20,
"name": "Roblox",
"image": "https://gsubz.com/uploads/gaming/roblox.png",
"note": "Codes arrive within seconds.",
"lines": 1,
"products": 8,
"fromPrice": 8000
}
]
}
Returns the product lines of one game, each with the fields the player must give and the amounts or packs you can buy, priced in naira. Use a productID from here with Validate Player ID and Buy Game Top-up. This list is public and needs no API key.
- A game can have several product lines, usually one for each region. A player's account only works with the line for its own region, so check
regionand use Validate Player ID before charging. Each line has its ownrequirements: send every field it lists, using itsfieldname, when you validate or buy.
| Query parameter | Description |
|---|---|
gameID
integer
Required |
The gameID from List Games. Example:
12 |
Try it live
This endpoint is public, so no API key is needed.
About the response. price is in naira and is exactly what a purchase charges (it is checked live when you buy). kind is amount for a top-up of an amount, or pack for a bundle, pass or gift card. inStock is true, false (cannot be bought right now) or null (not known, the purchase is still attempted). options lists the allowed values when a field is a choice, such as a server. Gift cards have an empty requirements list. The example is shortened.
curl --location 'https://api.gsubz.com/api/games/products/?gameID=12'
<?php
$ch = curl_init('https://api.gsubz.com/api/games/products/?gameID=12');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
print_r($data);
const response = await fetch("https://api.gsubz.com/api/games/products/?gameID=12");
const data = await response.json();
console.log(data);
import requests
url = "https://api.gsubz.com/api/games/products/"
payload = {
"gameID": "12",
}
response = requests.get(url, params=payload, timeout=60)
print(response.json())
{
"code": 200,
"status": "successful",
"game": {
"gameID": 12,
"name": "Free Fire",
"image": "https://gsubz.com/uploads/gaming/free-fire.png",
"note": null
},
"lines": [
{
"lineID": 467,
"name": "Direct Topup Mena",
"region": "Mena",
"requirements": [
{
"field": "player_id",
"label": "Player ID",
"type": "text",
"required": true,
"options": null
}
],
"products": [
{
"productID": "101",
"name": "100 Diamonds",
"price": 1520,
"kind": "amount",
"inStock": true
},
{
"productID": "102",
"name": "Weekly Membership",
"price": 5200,
"kind": "pack",
"inStock": null
}
]
}
]
}
{
"code": 404,
"status": "failed",
"description": "CONTENT_NOT_FOUND",
"api_response": "That game is not available."
}
Checks the player's details for a product and returns the player's name (and region, when the game states one), so your customer can confirm it is the right account before you buy. It is free. Always validate before you buy: it catches a wrong ID or the wrong region before any money moves.
- Send every field the product line lists under
requirements, using itsfieldname. Most games need onlyplayer_id. Games that need more, such as a zone or server, take those as extra fields named exactly as listed inrequirements, for examplezone_id. Gift cards need no player details and answerNO_ID_NEEDED. - You can make 20 checks every 10 minutes for each API key.
| Body field | Description |
|---|---|
productID
string
Required |
The productID from List Game Products. Example:
101 |
player_id
string
Optional |
The player's ID. Needed by most games. It is one of the fields a line lists under requirements. Example:
12345678 |
Try it live
Sent only to GSUBZ, through this page's server. We never store it. It stays in this browser tab until you close it.
Other fields the product line asks for, one name=value on each line.
About the response. playerName and region are null when the game does not give them. description is PLAYER_FOUND or, for products that need no player details, NO_ID_NEEDED.
curl --location 'https://api.gsubz.com/api/games/validate/' \ --header 'Authorization: Bearer YOUR_API_KEY' \ --form 'productID="101"' \ --form 'player_id="12345678"'
<?php
$ch = curl_init('https://api.gsubz.com/api/games/validate/');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY'],
CURLOPT_POSTFIELDS => [
'productID' => '101',
'player_id' => '12345678',
],
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
print_r($data);
const form = new FormData();
form.append("productID", "101");
form.append("player_id", "12345678");
const response = await fetch("https://api.gsubz.com/api/games/validate/", {
method: "POST",
headers: { Authorization: "Bearer YOUR_API_KEY" },
body: form,
});
const data = await response.json();
console.log(data);
import requests
url = "https://api.gsubz.com/api/games/validate/"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
payload = {
"productID": "101",
"player_id": "12345678",
}
response = requests.post(url, headers=headers, data=payload, timeout=60)
print(response.json())
{
"code": 200,
"status": "successful",
"description": "PLAYER_FOUND",
"playerName": "ProGamer99",
"region": "AF",
"api_response": "Player found."
}
{
"code": 404,
"status": "failed",
"description": "PLAYER_NOT_FOUND",
"api_response": "We could not find that player ID. Please check it and try again."
}
Buys one game top-up or gift card. Your wallet is charged first. A top-up goes straight to the player's account, and a gift card returns its code or codes in codes. Validate the player with Validate Player ID first.
orderStatus is processing, you have been charged and the order is not finished. It ends as completed or refunded. We send you a webhook (games.order.updated) when it finishes, and you can always check it with Fetch Game Orders. A refund goes back to your wallet automatically, and an order is never refunded while its outcome is unclear.- Always send a
requestID. If you send the same one again, the API returns the original order (code406,INVALID_ARGUMENTS_DUPLICATE_REQUEST_ID) and never buys twice. ArequestIDis free to use again only after a request that was refused before any money moved (for example a wrong player ID or too little balance). - Send every field the product line lists under
requirements, using itsfieldname. Most games need onlyplayer_id. Games that need more, such as a zone or server, take those as extra fields named exactly as listed inrequirements, for examplezone_id.
| Body field | Description |
|---|---|
productID
string
Required |
The productID from List Game Products. Example:
101 |
player_id
string
Optional |
The player's ID. Needed by most games. It is one of the fields a line lists under requirements. Example:
12345678 |
requestID
string
Optional |
Your own unique reference for this order, up to 100 characters. Use it later with Fetch Game Orders. Example:
game-1001 |
Try it live
Sent only to GSUBZ, through this page's server. We never store it. It stays in this browser tab until you close it.
Other fields the product line asks for, one name=value on each line.
About the response. orderStatus is completed, or processing while the order is still being delivered. Keep orderID: you need it to look the order up. For a gift card, codes holds one item for each code, with code, serial and expiry, and it can be empty until the order is completed. Treat codes like cash and never log them.
curl --location 'https://api.gsubz.com/api/games/buy/' \ --header 'Authorization: Bearer YOUR_API_KEY' \ --form 'productID="101"' \ --form 'player_id="12345678"' \ --form 'requestID="game-1001"'
<?php
$ch = curl_init('https://api.gsubz.com/api/games/buy/');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY'],
CURLOPT_POSTFIELDS => [
'productID' => '101',
'player_id' => '12345678',
'requestID' => 'game-1001',
],
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
print_r($data);
const form = new FormData();
form.append("productID", "101");
form.append("player_id", "12345678");
form.append("requestID", "game-1001");
const response = await fetch("https://api.gsubz.com/api/games/buy/", {
method: "POST",
headers: { Authorization: "Bearer YOUR_API_KEY" },
body: form,
});
const data = await response.json();
console.log(data);
import requests
url = "https://api.gsubz.com/api/games/buy/"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
payload = {
"productID": "101",
"player_id": "12345678",
"requestID": "game-1001",
}
response = requests.post(url, headers=headers, data=payload, timeout=60)
print(response.json())
{
"code": 200,
"status": "successful",
"transactionID": "GM261007113015A1B2C3D4",
"orderID": 15,
"amount": 1520,
"serviceID": "games",
"amountPaid": 1520,
"initialBalance": 100000,
"finalBalance": 98480,
"date": "2026-10-07T11:30:15+01:00",
"api_response": "Your order is complete.",
"requestID": "game-1001",
"game": "Free Fire · Direct Topup Mena",
"product": "100 Diamonds",
"orderStatus": "completed",
"playerName": "ProGamer99",
"codes": []
}
{
"code": 404,
"status": "failed",
"description": "PLAYER_NOT_FOUND",
"api_response": "We could not find that player ID. Please check it and try again. You have not been charged."
}
Returns your game orders, including orders bought on the website. Send a requestID, an orderID or a transactionID to get one order, or send none of them to list your last 50. An order that is still processing is checked again when you look it up (at most every 25 seconds), so this is also how you collect the result, and any gift-card codes, after a processing purchase if you missed the webhook.
| Body field | Description |
|---|---|
requestID
string
Optional |
The requestID you sent when you bought. Example:
game-1001 |
orderID
integer
Optional |
The orderID from the purchase response. Example:
15 |
transactionID
string
Optional |
The transactionID from the purchase response. Example:
GM261007113015A1B2C3D4 |
Try it live
Sent only to GSUBZ, through this page's server. We never store it. It stays in this browser tab until you close it.
About the response. orderStatus is one of processing, completed or refunded. amountRefunded shows what was returned to your wallet, and amountPaid is what you paid after any refund. requestID is null for orders that were not placed through the API.
curl --location 'https://api.gsubz.com/api/games/orders/' \ --header 'Authorization: Bearer YOUR_API_KEY' \ --form 'requestID="game-1001"' \ --form 'orderID="15"' \ --form 'transactionID="GM261007113015A1B2C3D4"'
<?php
$ch = curl_init('https://api.gsubz.com/api/games/orders/');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY'],
CURLOPT_POSTFIELDS => [
'requestID' => 'game-1001',
'orderID' => '15',
'transactionID' => 'GM261007113015A1B2C3D4',
],
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
print_r($data);
const form = new FormData();
form.append("requestID", "game-1001");
form.append("orderID", "15");
form.append("transactionID", "GM261007113015A1B2C3D4");
const response = await fetch("https://api.gsubz.com/api/games/orders/", {
method: "POST",
headers: { Authorization: "Bearer YOUR_API_KEY" },
body: form,
});
const data = await response.json();
console.log(data);
import requests
url = "https://api.gsubz.com/api/games/orders/"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
payload = {
"requestID": "game-1001",
"orderID": "15",
"transactionID": "GM261007113015A1B2C3D4",
}
response = requests.post(url, headers=headers, data=payload, timeout=60)
print(response.json())
{
"code": 200,
"status": "successful",
"orders": [
{
"orderID": 15,
"transactionID": "GM261007113015A1B2C3D4",
"requestID": "game-1001",
"game": "Free Fire · Direct Topup Mena",
"product": "100 Diamonds",
"amount": 1520,
"amountPaid": 1520,
"amountRefunded": 0,
"orderStatus": "completed",
"playerName": "ProGamer99",
"codes": [],
"date": "2026-10-07T11:30:15+01:00"
}
]
}
{
"code": 404,
"status": "failed",
"description": "CONTENT_NOT_FOUND",
"api_response": "No game order found for that reference."
}
Bulk SMS
Sends one text message to up to 5,000 Nigerian numbers in a single request. Your wallet is charged first, the message is sent, and anything that could not be sent is refunded automatically.
5,000; years like 2026 are fine). Numbers on the DND list are not delivered by the networks and are not refunded.- The field names
from,toandmsgare the standard names most SMS gateways use, so code written for another SMS service needs very little change. The message type (normal or unicode) is detected for you, so you never sendtype. - You pay per page, per recipient. One page is 160 characters (153 each once the message is longer), or 70 (67) if it has emoji or other special characters. The naira sign is sent as
Nso it does not turn the message into a special-character one. The price is currently ₦5 per page per recipient, andamountin the response shows exactly what was charged. - Numbers are cleaned and de-duplicated. Invalid or repeated numbers are skipped and counted in
skipped. If some numbers cannot be sent, the request still returnssuccessfulwithfailedabove zero, and those numbers are refunded. If nothing can be sent you getGATEWAY_ERRORand you are not charged. - Common failures, all with
"status": "failed":INVALID_SENDER,MESSAGE_CONTENT_BLOCKED(with anissueslist),NO_VALID_RECIPIENTS,TOO_MANY_RECIPIENTSandMESSAGE_TOO_LONG(code206), andDUPLICATE_MESSAGE(code406, the same message to the same list within two minutes and norequestIDsent). Send arequestIDto send the same message again on purpose.
| Body field | Description |
|---|---|
api
string
Required |
Your API key. Send the same key you use in the Authorization header. Example:
YOUR_API_KEY |
from
string
Required |
The sender name shown on the phone: 3 to 11 letters, with no spaces, numbers or symbols. Names of banks, payment companies, telecoms and government bodies cannot be used. Example:
MyShop |
to
string
Required |
The phone numbers, separated by commas or new lines, up to 5,000. 080…, 234… and +234… are all accepted. Example:
08031234567,08021234568 |
msg
string
Required |
The message text, up to 905 characters. Example:
Hello, your order is ready for pickup. |
requestID
string
Optional |
Your own unique reference for this send, up to 100 characters. Send the same one again and you get the original result back, never a second send or charge. message_uuid is accepted as the same thing. Example:
sms-1001 |
Try it live
Sent only to GSUBZ, through this page's server. We never store it. It stays in this browser tab until you close it.
to.About the response. recipients is how many valid, different numbers were found. sent and failed add up to that, and skipped counts invalid or repeated numbers that were left out. pages is the number of pages per recipient. amount is the full cost and amountPaid is what you were charged after any refund for numbers that were not sent.
curl --location 'https://api.gsubz.com/api/sms/' \ --header 'Authorization: Bearer YOUR_API_KEY' \ --form 'api="YOUR_API_KEY"' \ --form 'from="MyShop"' \ --form 'to="08031234567,08021234568"' \ --form 'msg="Hello, your order is ready for pickup."' \ --form 'requestID="sms-1001"'
<?php
$ch = curl_init('https://api.gsubz.com/api/sms/');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY'],
CURLOPT_POSTFIELDS => [
'api' => 'YOUR_API_KEY',
'from' => 'MyShop',
'to' => '08031234567,08021234568',
'msg' => 'Hello, your order is ready for pickup.',
'requestID' => 'sms-1001',
],
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
print_r($data);
const form = new FormData();
form.append("api", "YOUR_API_KEY");
form.append("from", "MyShop");
form.append("to", "08031234567,08021234568");
form.append("msg", "Hello, your order is ready for pickup.");
form.append("requestID", "sms-1001");
const response = await fetch("https://api.gsubz.com/api/sms/", {
method: "POST",
headers: { Authorization: "Bearer YOUR_API_KEY" },
body: form,
});
const data = await response.json();
console.log(data);
import requests
url = "https://api.gsubz.com/api/sms/"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
payload = {
"api": "YOUR_API_KEY",
"from": "MyShop",
"to": "08031234567,08021234568",
"msg": "Hello, your order is ready for pickup.",
"requestID": "sms-1001",
}
response = requests.post(url, headers=headers, data=payload, timeout=60)
print(response.json())
{
"code": 200,
"status": "successful",
"transactionID": 3530235131,
"amount": 10,
"serviceID": "bulk_sms",
"amountPaid": 10,
"initialBalance": 1000,
"finalBalance": 990,
"date": "2026-09-28T12:30:52+01:00",
"api_response": "Your message was sent to 2 numbers.",
"reference": "BSMSA260928123052FC8106",
"requestID": "sms-1001",
"sender": "MyShop",
"recipients": 2,
"sent": 2,
"failed": 0,
"skipped": 0,
"pages": 1
}
{
"code": 206,
"status": "failed",
"description": "MESSAGE_CONTENT_BLOCKED",
"api_response": "This message would be blocked by the networks, so it was not sent. The networks block messages that mention international brands such as WhatsApp or Facebook.",
"issues": [
"The networks block messages that mention international brands such as WhatsApp or Facebook."
]
}
Flights
Returns airports with their 3-letter code, name, city and country. Send q to search by city, airport name, code or country (the best 15 matches). Send nothing to get the popular airports, or all=true to download the whole list and keep it in your own cache. Use the code as origin and destination in Search Flights.
| Query parameter | Description |
|---|---|
q
string
Optional |
Search text, for example lagos, abuja, LHR or London. Leave it out for the popular airports. Example:
lagos |
all
string
Optional |
true returns every airport instead of the best matches. Example:
true |
Try it live
Sent only to GSUBZ, through this page's server. We never store it. It stays in this browser tab until you close it.
About the response. Airports are listed with the best match first.
curl --location 'https://api.gsubz.com/api/flight/search/?q=lagos' \ --header 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.gsubz.com/api/flight/search/?q=lagos');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY'],
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
print_r($data);
const response = await fetch("https://api.gsubz.com/api/flight/search/?q=lagos", {
headers: { Authorization: "Bearer YOUR_API_KEY" },
});
const data = await response.json();
console.log(data);
import requests
url = "https://api.gsubz.com/api/flight/search/"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
payload = {
"q": "lagos",
}
response = requests.get(url, headers=headers, params=payload, timeout=60)
print(response.json())
{
"code": 200,
"status": "successful",
"count": 1,
"airports": [
{ "code": "LOS", "name": "Murtala Muhammed International Airport", "city": "Lagos", "country": "Nigeria" }
]
}
{
"code": 401,
"status": "failed",
"description": "INVALID_API_OR_NOT_FOUND",
"api_response": "This API key is not valid."
}
Searches flights for a date (and a return date for a return trip) and returns the available options, cheapest first, with every price in naira. Searching is free. Each option carries a token. Send that token, together with the searchID of this response, to Book a Flight.
- Prices already include our margin, so
amountis what the booking will cost, to the naira. The price is confirmed again when you call Book a Flight withpreview=true, so show your customer that price, not the search one. - Send
return_dateto search a return trip; leave it out for one-way. Times in the results are the local time at each airport, with no timezone. A search stays valid for one hour. You can run up to 20 searches a minute for each API key.
| Body field | Description |
|---|---|
api
string
Required |
Your API key. Send the same key you use in the Authorization header. Example:
YOUR_API_KEY |
origin
string
Required |
The airport code you fly from, from List Airports. Example:
LOS |
destination
string
Required |
The airport code you fly to. Example:
ABV |
departure_date
string
Required |
Departure date as YYYY-MM-DD. Today or later. Example:
2026-12-01 |
return_date
string
Optional |
Return date as YYYY-MM-DD, on or after the departure date. Leave it out for a one-way trip. Example:
2026-12-08 |
adults
integer
Optional |
Adults (12 and over). 1 to 9. The default is 1. Example:
1 |
children
integer
Optional |
Children (2 to 11). 0 to 9. Example:
0 |
infants
integer
Optional |
Infants (under 2). Each needs an adult. 0 to 9. Example:
0 |
cabin
string
Optional |
economy (default), premium_economy, business or first. Example:
economy |
Try it live
Sent only to GSUBZ, through this page's server. We never store it. It stays in this browser tab until you close it.
About the response. offers is sorted by amount, cheapest first, and holds up to 80 options (a return trip has two journeys). token is long, so store it as it is. Keep searchID: Book a Flight needs it.
curl --location 'https://api.gsubz.com/api/flight/search/' \ --header 'Authorization: Bearer YOUR_API_KEY' \ --form 'api="YOUR_API_KEY"' \ --form 'origin="LOS"' \ --form 'destination="ABV"' \ --form 'departure_date="2026-12-01"' \ --form 'adults="1"'
<?php
$ch = curl_init('https://api.gsubz.com/api/flight/search/');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY'],
CURLOPT_POSTFIELDS => [
'api' => 'YOUR_API_KEY',
'origin' => 'LOS',
'destination' => 'ABV',
'departure_date' => '2026-12-01',
'adults' => '1',
],
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
print_r($data);
const form = new FormData();
form.append("api", "YOUR_API_KEY");
form.append("origin", "LOS");
form.append("destination", "ABV");
form.append("departure_date", "2026-12-01");
form.append("adults", "1");
const response = await fetch("https://api.gsubz.com/api/flight/search/", {
method: "POST",
headers: { Authorization: "Bearer YOUR_API_KEY" },
body: form,
});
const data = await response.json();
console.log(data);
import requests
url = "https://api.gsubz.com/api/flight/search/"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
payload = {
"api": "YOUR_API_KEY",
"origin": "LOS",
"destination": "ABV",
"departure_date": "2026-12-01",
"adults": "1",
}
response = requests.post(url, headers=headers, data=payload, timeout=60)
print(response.json())
{
"code": 200,
"status": "successful",
"searchID": "FS3A9C41D07B22E8F5A61",
"expiresAt": "2026-10-17T11:59:51+01:00",
"currency": "NGN",
"count": 1,
"api_response": "Found 1 flight option.",
"offers": [
{
"token": "eyJhbGciOi…",
"airline": "Ibom Air",
"airlineCode": "QI",
"logo": "https://…/QI.png",
"amount": 95000,
"refundable": false,
"journeys": [
{
"from": "LOS",
"to": "ABV",
"departsAt": "2026-12-01T08:00:00",
"arrivesAt": "2026-12-01T09:10:00",
"duration": "1h10",
"stops": 0,
"flightNumber": "QI 301",
"baggage": "23KG baggage"
}
]
}
]
}
{
"code": 206,
"status": "failed",
"description": "INVALID_CONTENT",
"api_response": "origin and destination must be different."
}
Books one flight for your customer and pays for it from your wallet. The price is locked first: send preview=true to get the final price (and a quoteID) without paying, then book with that quoteID, or book straight away with the token and searchID from Search Flights. Send the body as JSON (recommended) or as form fields.
orderStatus is processing, you have been charged and the airline is still issuing the ticket. It ends as completed (with the pnr and tickets) or refunded. We send you a webhook (flight.order.updated) when it changes, and you can always check it with Fetch Flight Orders. A refund goes back to your wallet automatically, and a booking is never refunded while its outcome is unclear.- Two steps. 1)
preview=truewithtokenandsearchIDreturns the final price and aquoteIDthat stays valid for about 25 minutes (expiresIn). Nothing is charged. 2) Send the passengers and contact with thatquoteIDto book at exactly that price. A quote can be used once. AddmaxAmountto refuse a booking that would cost more: you getPRICE_CHANGEDand nothing is charged. - Always send a
requestID. Send the same one again and you get the original booking back (code406,INVALID_ARGUMENTS_DUPLICATE_REQUEST_ID) and never a second booking, so retrying after a timeout is safe. International trips needpassport_numberandpassport_expiryfor every passenger, and the passport must be valid after the last travel date. The ticket e-mail to your customer is yours to send: we do not e-mail them.
| Body field | Description |
|---|---|
searchID
string
With token |
The searchID from Search Flights. Needed together with token. Example:
FS3A9C41D07B22E8F5A61 |
token
string
Without quoteID |
The token of the option your customer picked in Search Flights. Example:
eyJhbGciOi… |
quoteID
string
Without token |
The quoteID from an earlier preview=true call. Books at that locked price. Example:
Q1b2c3d4 |
passengers
array
To book |
One item for each traveller, matching the adults, children and infants you searched. Each has type (adult, child or infant), title (Mr, Mrs, Ms, Miss or Master), first_name, last_name, gender (male or female), and optionally middle_name and country_code (2 letters, default NG). International trips also need passport_number and passport_expiry (YYYY-MM-DD). Names use letters only. Example:
[{"type":"adult","title":"Mr","first_name":"Ada","last_name":"Obi","gender":"male"}] |
contact
object
To book |
Who the airline contacts: email and phone (080…, 234… or +234…). Example:
{"email":"[email protected]","phone":"08031234567"} |
requestID
string
Optional |
Your own unique reference for this booking, up to 100 characters. Use it later with Fetch Flight Orders. Example:
flight-1001 |
maxAmount
number
Optional |
The most you will pay, in naira. If the price is higher you get PRICE_CHANGED and nothing is charged. Example:
100000 |
preview
boolean
Optional |
true locks and returns the final price (as quoteID and amount) without booking or charging anything. Example:
true |
Try it live
Sent only to GSUBZ, through this page's server. We never store it. It stays in this browser tab until you close it.
preview as true to see the price without paying.About the response. orderStatus is completed (ticket issued: pnr and tickets are filled in), processing (charged, ticket not issued yet) or refunded. Keep transactionID: you need it to look the booking up. With preview=true the response has "preview": true, the final amount, a quoteID, expiresIn (seconds), the journeys, fareRules and penaltyRules, and amountPaid is 0. amountPaid is what you pay after any refund.
curl --location 'https://api.gsubz.com/api/flight/book/' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"searchID": "FS3A9C41D07B22E8F5A61",
"token": "eyJhbGciOi…",
"passengers": [
{
"type": "adult",
"title": "Mr",
"first_name": "Ada",
"last_name": "Obi",
"gender": "male"
}
],
"contact": {
"email": "[email protected]",
"phone": "08031234567"
},
"requestID": "flight-1001",
"preview": true
}'
<?php
$payload = [
'searchID' => 'FS3A9C41D07B22E8F5A61',
'token' => 'eyJhbGciOi…',
'passengers' => [
[
'type' => 'adult',
'title' => 'Mr',
'first_name' => 'Ada',
'last_name' => 'Obi',
'gender' => 'male',
],
],
'contact' => [
'email' => '[email protected]',
'phone' => '08031234567',
],
'requestID' => 'flight-1001',
'preview' => true,
];
$ch = curl_init('https://api.gsubz.com/api/flight/book/');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY', 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode($payload),
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
print_r($data);
const payload = {
"searchID": "FS3A9C41D07B22E8F5A61",
"token": "eyJhbGciOi…",
"passengers": [
{
"type": "adult",
"title": "Mr",
"first_name": "Ada",
"last_name": "Obi",
"gender": "male"
}
],
"contact": {
"email": "[email protected]",
"phone": "08031234567"
},
"requestID": "flight-1001",
"preview": true
};
const response = await fetch("https://api.gsubz.com/api/flight/book/", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
});
const data = await response.json();
console.log(data);
import requests
url = "https://api.gsubz.com/api/flight/book/"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
payload = {
"searchID": "FS3A9C41D07B22E8F5A61",
"token": "eyJhbGciOi…",
"passengers": [
{
"type": "adult",
"title": "Mr",
"first_name": "Ada",
"last_name": "Obi",
"gender": "male",
},
],
"contact": {
"email": "[email protected]",
"phone": "08031234567",
},
"requestID": "flight-1001",
"preview": True,
}
response = requests.post(url, headers=headers, json=payload, timeout=60)
print(response.json())
{
"code": 200,
"status": "successful",
"transactionID": "TRV261017110002AB12CD34",
"amount": 95000,
"serviceID": "flight",
"amountPaid": 95000,
"initialBalance": 500000,
"finalBalance": 405000,
"date": "2026-10-17T11:00:02+01:00",
"api_response": "Your booking is being processed and you have been charged. The result is sent to your webhook as flight.order.updated, or check it with Fetch Flight Orders.",
"requestID": "flight-1001",
"orderStatus": "processing",
"tripType": "oneway",
"origin": "LOS",
"destination": "ABV",
"departureDate": "2026-12-01",
"returnDate": null,
"airline": "Ibom Air",
"journeys": [
{ "from": "LOS", "to": "ABV", "departsAt": "2026-12-01T08:00:00", "arrivesAt": "2026-12-01T09:10:00", "duration": "1h10", "stops": 0, "flightNumber": "QI 301", "baggage": "23KG baggage" }
],
"passengers": [
{ "type": "Adult", "title": "Mr", "firstName": "Ada", "middleName": null, "lastName": "Obi", "gender": "Male", "countryCode": "NG" }
],
"contact": { "email": "[email protected]", "phone": "+2348031234567" },
"amountRefunded": 0,
"pnr": null,
"tickets": []
}
{
"code": 406,
"status": "failed",
"description": "PRICE_CHANGED",
"api_response": "The price is now ₦98,500.00, above your maxAmount. Nothing was charged. Send the same request with the quoteID in this response to book at the new price.",
"quoteID": "Q1b2c3d4",
"currentAmount": 98500,
"expiresIn": 1700
}
Returns your flight bookings made through the API. Send a requestID or a transactionID to get one booking, or send neither to list your last 50. A booking that is still processing is checked again when you look it up (at most every 25 seconds), so this is also how you collect the PNR and e-ticket numbers if you missed the webhook. It also answers GET.
| Body field | Description |
|---|---|
api
string
Required |
Your API key. Send the same key you use in the Authorization header. Example:
YOUR_API_KEY |
requestID
string
Optional |
The requestID you sent when you booked. Example:
flight-1001 |
transactionID
string
Optional |
The transactionID from the booking response. Example:
TRV261017110002AB12CD34 |
Try it live
Sent only to GSUBZ, through this page's server. We never store it. It stays in this browser tab until you close it.
About the response. orderStatus is one of processing, completed or refunded. amountRefunded shows what was returned to your wallet, and amountPaid is what you paid after any refund. pnr and tickets are filled in once the ticket is issued. Without a reference the response also has count.
curl --location 'https://api.gsubz.com/api/flight/orders/' \ --header 'Authorization: Bearer YOUR_API_KEY' \ --form 'api="YOUR_API_KEY"' \ --form 'requestID="flight-1001"' \ --form 'transactionID="TRV261017110002AB12CD34"'
<?php
$ch = curl_init('https://api.gsubz.com/api/flight/orders/');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY'],
CURLOPT_POSTFIELDS => [
'api' => 'YOUR_API_KEY',
'requestID' => 'flight-1001',
'transactionID' => 'TRV261017110002AB12CD34',
],
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
print_r($data);
const form = new FormData();
form.append("api", "YOUR_API_KEY");
form.append("requestID", "flight-1001");
form.append("transactionID", "TRV261017110002AB12CD34");
const response = await fetch("https://api.gsubz.com/api/flight/orders/", {
method: "POST",
headers: { Authorization: "Bearer YOUR_API_KEY" },
body: form,
});
const data = await response.json();
console.log(data);
import requests
url = "https://api.gsubz.com/api/flight/orders/"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
payload = {
"api": "YOUR_API_KEY",
"requestID": "flight-1001",
"transactionID": "TRV261017110002AB12CD34",
}
response = requests.post(url, headers=headers, data=payload, timeout=60)
print(response.json())
{
"code": 200,
"status": "successful",
"orders": [
{
"transactionID": "TRV261017110002AB12CD34",
"requestID": "flight-1001",
"serviceID": "flight",
"orderStatus": "completed",
"tripType": "oneway",
"origin": "LOS",
"destination": "ABV",
"departureDate": "2026-12-01",
"returnDate": null,
"airline": "Ibom Air",
"journeys": [
{ "from": "LOS", "to": "ABV", "departsAt": "2026-12-01T08:00:00", "arrivesAt": "2026-12-01T09:10:00", "duration": "1h10", "stops": 0, "flightNumber": "QI 301", "baggage": "23KG baggage" }
],
"passengers": [
{ "type": "Adult", "title": "Mr", "firstName": "Ada", "middleName": null, "lastName": "Obi", "gender": "Male", "countryCode": "NG" }
],
"contact": { "email": "[email protected]", "phone": "+2348031234567" },
"amount": 95000,
"amountRefunded": 0,
"amountPaid": 95000,
"pnr": "ABC123",
"tickets": [
{ "name": "Ada Obi", "type": "ADT", "ticketNumber": "1234567890123" }
],
"date": "2026-10-17T11:00:02+01:00"
}
]
}
{
"code": 404,
"status": "failed",
"description": "CONTENT_NOT_FOUND",
"api_response": "No flight booking found for that reference."
}
Store
Returns a page of products, 20 at a time, with every price in naira, exactly as shown on the Gsubz store. The scope decides where you search: trending (the default) and official are free, market searches the whole catalogue by keyword and costs ₦2. Send no parameters at all to get the first page of trending products.
q you must also send scope, so that you never pay for a market search by accident. A market search returns up to 5 pages (100 products) for each keyword and filters only work with scope=market. Every call is charged, including a repeat of the same request, so keep the results in your own cache.- What is free and what is not. Free: trending products, the Official Store (with or without a brand), List Categories and Brands, and Official Store product details (IDs that start with
g). ₦2 per call:scope=marketsearch, details of any other product, and supplier products. ₦4: image search. You are charged only when a call returns results. If it returns nothing or fails, your wallet is refunded automatically, and the response shows what you paid inamountPaid. - The Store endpoints use the
AuthorizationBearer header only, and the same upgraded API account as the rest of the API. Each response carriescallID, our reference for that call (quote it to support), plusamountPaidand your wallet balances.
| Query parameter | Description |
|---|---|
scope
string
Optional |
trending (free, the default), official (free, the Gsubz Official Store) or market (₦2, searches the whole catalogue). If you send only brand, the scope is official. Example:
market |
q
string
Needed for market |
The keyword to search for, up to 100 characters. Required with scope=market. With scope=official it filters the Official Store. Not used with trending. To search by category, use the category name as the keyword. Example:
wireless earbuds |
brand
integer
Optional |
A brand id from List Categories and Brands. Returns every product of that brand. Only with scope=official. Example:
1 |
page
integer
Optional |
The page number, starting at 1. Up to 5 for market and 80 for trending. Example:
1 |
sort
string
Optional |
default, sales, price_up or price_down. Only with scope=market. Example:
sales |
start_price
number
Optional |
Lowest price in naira. Only with scope=market. Example:
5000 |
end_price
number
Optional |
Highest price in naira. Only with scope=market. Example:
20000 |
moq
integer
Optional |
Only products you can order in this quantity or less. Only with scope=market. Example:
2 |
new_arrival
string
Optional |
true to list new products only. Only with scope=market. Example:
true |
Try it live
Sent only to GSUBZ, through this page's server. We never store it. It stays in this browser tab until you close it.
About the response. id is the product ID: use it with Get Product Details. IDs that start with g are Official Store products (freeShipping is true for those, and they are free to fetch). title is the short title shown on the store and fullTitle is the full one. priceNgn is in naira, or null when no price is available. sold is how many were sold recently (always 0 for the Official Store). hasMore tells you whether another page exists. The example is shortened to two products.
curl --location 'https://api.gsubz.com/api/store/search/?scope=market&q=wireless+earbuds&page=1' \ --header 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.gsubz.com/api/store/search/?scope=market&q=wireless+earbuds&page=1');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY'],
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
print_r($data);
const response = await fetch("https://api.gsubz.com/api/store/search/?scope=market&q=wireless+earbuds&page=1", {
headers: { Authorization: "Bearer YOUR_API_KEY" },
});
const data = await response.json();
console.log(data);
import requests
url = "https://api.gsubz.com/api/store/search/"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
payload = {
"scope": "market",
"q": "wireless earbuds",
"page": "1",
}
response = requests.get(url, headers=headers, params=payload, timeout=60)
print(response.json())
{
"code": 200,
"status": "successful",
"callID": 18452,
"scope": "market",
"amountPaid": 2,
"initialBalance": 5000,
"finalBalance": 4998,
"date": "2026-10-07T11:20:15+01:00",
"api_response": "Search results.",
"page": 1,
"pageSize": 20,
"count": 2,
"hasMore": false,
"items": [
{
"id": "682718261723",
"title": "Wireless Bluetooth Earbuds Noise Cancelling",
"fullTitle": "Wireless Bluetooth Earbuds Noise Cancelling Headset, Long Battery Life",
"image": "https://gsubz.com/store/image_proxy.php?url=https%3A%2F%2Fimg.example.com%2Fa1.jpg",
"priceNgn": 4850,
"sold": 1240,
"freeShipping": false
},
{
"id": "701442970035",
"title": "TWS Earbuds Touch Control Charging Case",
"fullTitle": "TWS Earbuds Touch Control Charging Case",
"image": "https://gsubz.com/store/image_proxy.php?url=https%3A%2F%2Fimg.example.com%2Fb2.jpg",
"priceNgn": 3600,
"sold": 310,
"freeShipping": false
}
]
}
{
"code": 404,
"status": "failed",
"description": "CONTENT_NOT_FOUND",
"api_response": "No products found. You were not charged.",
"callID": 18453
}
Send a link to a photo and get back up to 20 similar products, in the same format as Search Products. It costs ₦4 and you are charged only when it returns results.
image_urlmust be a publichttpslink that anyone on the internet can open without logging in. Use a JPG, PNG or WebP photo of at least 100 × 100 pixels and up to 8 MB. We download the photo, so links to private networks are refused. Use a clear photo of one product for the best matches.
| Body field | Description |
|---|---|
image_url
string
Required |
A public https link to the photo. Example:
https://example.com/photos/earbuds.jpg |
Try it live
Sent only to GSUBZ, through this page's server. We never store it. It stays in this browser tab until you close it.
About the response. Image search returns one page of up to 20 products, so hasMore is always false. The example is shortened to one product.
curl --location 'https://api.gsubz.com/api/store/image-search/' \ --header 'Authorization: Bearer YOUR_API_KEY' \ --form 'image_url="https://example.com/photos/earbuds.jpg"'
<?php
$ch = curl_init('https://api.gsubz.com/api/store/image-search/');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY'],
CURLOPT_POSTFIELDS => [
'image_url' => 'https://example.com/photos/earbuds.jpg',
],
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
print_r($data);
const form = new FormData();
form.append("image_url", "https://example.com/photos/earbuds.jpg");
const response = await fetch("https://api.gsubz.com/api/store/image-search/", {
method: "POST",
headers: { Authorization: "Bearer YOUR_API_KEY" },
body: form,
});
const data = await response.json();
console.log(data);
import requests
url = "https://api.gsubz.com/api/store/image-search/"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
payload = {
"image_url": "https://example.com/photos/earbuds.jpg",
}
response = requests.post(url, headers=headers, data=payload, timeout=60)
print(response.json())
{
"code": 200,
"status": "successful",
"callID": 18455,
"scope": "market",
"amountPaid": 4,
"initialBalance": 4998,
"finalBalance": 4994,
"date": "2026-10-07T11:22:40+01:00",
"api_response": "Image search results.",
"page": 1,
"pageSize": 20,
"count": 1,
"hasMore": false,
"items": [
{
"id": "682718261723",
"title": "Wireless Bluetooth Earbuds Noise Cancelling",
"fullTitle": "Wireless Bluetooth Earbuds Noise Cancelling Headset, Long Battery Life",
"image": "https://gsubz.com/store/image_proxy.php?url=https%3A%2F%2Fimg.example.com%2Fa1.jpg",
"priceNgn": 4850,
"sold": 1240,
"freeShipping": false
}
]
}
{
"code": 206,
"status": "failed",
"description": "INVALID_CONTENT",
"api_response": "That link is not an image.",
"callID": 18456
}
Returns the full details of one product, with every price in naira. Use an id from Search Products. Official Store products (IDs that start with g) are free. Any other product costs ₦2, and you are charged only when the product is found.
| Query parameter | Description |
|---|---|
id
string
Required |
The product id from a search result, for example 682718261723, or g000000001 for an Official Store product. Example:
682718261723 |
Try it live
Sent only to GSUBZ, through this page's server. We never store it. It stays in this browser tab until you close it.
g) are free.About the response. priceTiers show the price for each minimum quantity. minPriceNgn and maxPriceNgn are the lowest and highest variant prices. skus are the variants (colour, size and so on): send the skuId as sku_id when you Place an Order. A variant's weight and size are null when unknown. media can hold image, video and youtube items (a youtube item has videoId, start and end in seconds). supplier.id is the ID to use with Get Supplier Products; it is null for Official Store products. Each variant's shippingNgn is the shipping fee we charge to Nigeria for 1 piece and for 5 pieces ordered together, by air and by sea (more pieces cost less per piece, because they ship together); every variant is priced when you request the product. shipping.estimated is true when those fees are filled in. shipping.seaOnly is true for goods that can only go by sea (power banks, sprays, perfumes). flatAirFeePerItemNgn is set for phones, tablets and laptops, which have a flat air fee per item. For the exact fee of any quantity mix, call Place an Order with preview=true. The rates and the variants' weights and volumes are also included. shipping is null when freeShipping is true. description is empty for most products. similar lists up to 20 similar products from our catalogue (id, title, image, priceNgn, totalSold); use the id with this endpoint for full details. It is an empty list for Official Store products and is included at no extra cost. The example is shortened.
curl --location 'https://api.gsubz.com/api/store/product/?id=682718261723' \ --header 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.gsubz.com/api/store/product/?id=682718261723');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY'],
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
print_r($data);
const response = await fetch("https://api.gsubz.com/api/store/product/?id=682718261723", {
headers: { Authorization: "Bearer YOUR_API_KEY" },
});
const data = await response.json();
console.log(data);
import requests
url = "https://api.gsubz.com/api/store/product/"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
payload = {
"id": "682718261723",
}
response = requests.get(url, headers=headers, params=payload, timeout=60)
print(response.json())
{
"code": 200,
"status": "successful",
"callID": 18460,
"scope": "market",
"amountPaid": 2,
"initialBalance": 4994,
"finalBalance": 4992,
"date": "2026-10-07T11:25:03+01:00",
"api_response": "Product details.",
"product": {
"id": "682718261723",
"title": "Wireless Bluetooth Earbuds Noise Cancelling Headset",
"media": [
{ "type": "video", "url": "https://video.example.com/earbuds.mp4" },
{ "type": "image", "url": "https://gsubz.com/store/image_proxy.php?url=https%3A%2F%2Fimg.example.com%2Fa1.jpg" }
],
"priceTiers": [
{ "minQty": 2, "priceNgn": 4850 },
{ "minQty": 100, "priceNgn": 4300 }
],
"minPriceNgn": 4300,
"maxPriceNgn": 5100,
"moq": 2,
"skus": [
{
"skuId": "5001",
"label": "Black / Standard",
"stock": 120,
"priceNgn": 4850,
"image": "https://gsubz.com/store/image_proxy.php?url=https%3A%2F%2Fimg.example.com%2Fk1.jpg",
"weightKg": 0.12,
"lengthCm": 12,
"widthCm": 8,
"heightCm": 4,
"shippingNgn": { "airFor1Pc": 4276, "airFor5Pcs": 14250, "seaFor1Pc": 990, "seaFor5Pcs": 3300 }
}
],
"specs": {
"Battery": "300mAh",
"Bluetooth": "5.3"
},
"description": "",
"location": "Guangdong Shenzhen",
"totalSold": 4321,
"freeShipping": false,
"supplier": {
"id": "sp_Q3ZnR2Fh0uJp9mKcT1xYvWbEoLd8sA"
},
"shipping": {
"airRatePerKgNgn": 21000,
"seaRatePerCbmNgn": 450000,
"weightsKg": [0.12],
"volumesCbm": [0.000384],
"estimated": true,
"seaOnly": false,
"flatAirFeePerItemNgn": null,
"note": "Fees for any mix of quantities: POST /api/store/order/ with preview=true. The shipping fee charged is final."
}
}
}
{
"code": 404,
"status": "failed",
"description": "CONTENT_NOT_FOUND",
"api_response": "Product not found. You were not charged.",
"callID": 18461
}
Returns a page of products from one supplier, in the same format as Search Products. Get the supplier ID from supplier.id in Get Product Details. It costs ₦2, charged only when the page has products.
| Query parameter | Description |
|---|---|
id
string
Required |
The supplier ID from supplier.id in Get Product Details. Always start with sp_. Example:
sp_Q3ZnR2Fh0uJp9mKcT1xYvWbEoLd8sA |
page
integer
Optional |
The page number, starting at 1. Example:
1 |
sort
string
Optional |
default, sales, price_up, price_down, time_up or time_down. Example:
sales |
Try it live
Sent only to GSUBZ, through this page's server. We never store it. It stays in this browser tab until you close it.
About the response. The example is shortened to one product.
curl --location 'https://api.gsubz.com/api/store/supplier/?id=sp_Q3ZnR2Fh0uJp9mKcT1xYvWbEoLd8sA&page=1' \ --header 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.gsubz.com/api/store/supplier/?id=sp_Q3ZnR2Fh0uJp9mKcT1xYvWbEoLd8sA&page=1');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY'],
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
print_r($data);
const response = await fetch("https://api.gsubz.com/api/store/supplier/?id=sp_Q3ZnR2Fh0uJp9mKcT1xYvWbEoLd8sA&page=1", {
headers: { Authorization: "Bearer YOUR_API_KEY" },
});
const data = await response.json();
console.log(data);
import requests
url = "https://api.gsubz.com/api/store/supplier/"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
payload = {
"id": "sp_Q3ZnR2Fh0uJp9mKcT1xYvWbEoLd8sA",
"page": "1",
}
response = requests.get(url, headers=headers, params=payload, timeout=60)
print(response.json())
{
"code": 200,
"status": "successful",
"callID": 18470,
"scope": "market",
"amountPaid": 2,
"initialBalance": 4992,
"finalBalance": 4990,
"date": "2026-10-07T11:27:30+01:00",
"api_response": "Supplier products.",
"page": 1,
"pageSize": 20,
"count": 1,
"hasMore": true,
"items": [
{
"id": "770000000015",
"title": "Cotton Casual Shirt",
"fullTitle": "Cotton Casual Shirt Short Sleeve",
"image": "https://gsubz.com/store/image_proxy.php?url=https%3A%2F%2Fimg.example.com%2Fsh1.jpg",
"priceNgn": 3100,
"sold": 65,
"freeShipping": false
}
]
}
{
"code": 206,
"status": "failed",
"description": "INVALID_CONTENT",
"api_response": "id must be a supplier id from a product (supplier.id).",
"callID": 18471
}
Returns the categories shown on the Gsubz store and the Official Store brands. It is free. No parameters: it always returns everything in one response.
- A category is only a group of related search words. To get a category's products, send its
nameasqto Search Products withscope=market. You are free to build your own categories from keywords instead. To get a brand's products, send itsidasbrandwithscope=official.
Try it live
Sent only to GSUBZ, through this page's server. We never store it. It stays in this browser tab until you close it.
About the response. categories is a tree up to three levels deep: a category with no sub-categories has an empty children array. brands lists only brands that have products, and products is how many. The example is shortened.
curl --location 'https://api.gsubz.com/api/store/categories/' \ --header 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.gsubz.com/api/store/categories/');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY'],
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
print_r($data);
const response = await fetch("https://api.gsubz.com/api/store/categories/", {
headers: { Authorization: "Bearer YOUR_API_KEY" },
});
const data = await response.json();
console.log(data);
import requests
url = "https://api.gsubz.com/api/store/categories/"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
payload = {
}
response = requests.get(url, headers=headers, params=payload, timeout=60)
print(response.json())
{
"code": 200,
"status": "successful",
"callID": 18480,
"amountPaid": 0,
"initialBalance": 4990,
"finalBalance": 4990,
"date": "2026-10-07T11:30:02+01:00",
"api_response": "Categories and brands.",
"categories": [
{
"name": "Women's Clothing",
"image": "https://gsubz.com/store/image_proxy.php?url=https%3A%2F%2Fimg.example.com%2Fc1.jpg",
"children": [
{
"name": "Women's T-Shirts",
"image": "https://gsubz.com/store/image_proxy.php?url=https%3A%2F%2Fimg.example.com%2Fc2.jpg",
"children": []
},
{
"name": "Women's Casual Pants",
"image": "https://gsubz.com/store/image_proxy.php?url=https%3A%2F%2Fimg.example.com%2Fc3.jpg",
"children": [
{
"name": "Casual Pants",
"image": "https://gsubz.com/store/image_proxy.php?url=https%3A%2F%2Fimg.example.com%2Fc4.jpg",
"children": []
}
]
}
]
}
],
"brands": [
{
"id": 1,
"name": "Apple",
"image": "https://gsubz.com/store/image_proxy.php?url=https%3A%2F%2Fimg.example.com%2Fapple.jpg",
"products": 24
}
]
}
Every Store order is delivered to a pickup station, where your customer collects it. This returns the stations by state, with the delivery fee for each parcel size. Send the state and the station name exactly as returned when you Place an Order. It is free.
| Query parameter | Description |
|---|---|
action
string
Required |
Always stations. Example:
stations |
state
string
Optional |
Only this state. Leave it out to get every state. Example:
Lagos |
Try it live
Sent only to GSUBZ, through this page's server. We never store it. It stays in this browser tab until you close it.
About the response. deliveryFee is what the order pays to reach that station, by parcel size. The size is decided by the parcel's total weight and total volume (the bigger one wins), using the limits in parcelSizes: for example 3 kg but 0.05 m³ is a medium parcel. days is the usual delivery time once the parcel leaves our Lagos warehouse. The example is shortened to one station.
curl --location 'https://api.gsubz.com/api/store/order/?action=stations&state=Lagos' \ --header 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.gsubz.com/api/store/order/?action=stations&state=Lagos');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY'],
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
print_r($data);
const response = await fetch("https://api.gsubz.com/api/store/order/?action=stations&state=Lagos", {
headers: { Authorization: "Bearer YOUR_API_KEY" },
});
const data = await response.json();
console.log(data);
import requests
url = "https://api.gsubz.com/api/store/order/"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
payload = {
"action": "stations",
"state": "Lagos",
}
response = requests.get(url, headers=headers, params=payload, timeout=60)
print(response.json())
{
"code": 200,
"status": "successful",
"callID": 18490,
"scope": "stations",
"amountPaid": 0,
"initialBalance": 50000,
"finalBalance": 50000,
"date": "2026-10-13T10:02:11+01:00",
"api_response": "Pickup stations.",
"parcelSizes": {
"small": { "maxKg": 4, "maxCbm": 0.0384 },
"medium": { "maxKg": 12, "maxCbm": 0.1536 },
"large": { "maxKg": null, "maxCbm": null }
},
"states": [
{
"state": "Lagos",
"stations": [
{
"name": "Ikota",
"address": "Ikota Shopping Complex, Lekki",
"landmark": "Near VGC",
"phone": "08000000001",
"hours": { "weekdays": "8am - 6pm", "weekends": "9am - 3pm" },
"map": "https://maps.example.com/ikota",
"deliveryFee": { "smallNgn": 2400, "mediumNgn": 4200, "largeNgn": 6800, "days": "2-4 days" }
}
]
}
]
}
Places an order for one or more products and pays for it from your wallet. Prices, the service fee, shipping and the delivery fee are worked out exactly as on the Gsubz store. Send preview=true first to get the full price without paying. API orders are always packed without Gsubz branding, so you can ship to your own customers. Send the body as JSON (recommended) or as form fields.
reference is your own unique ID for the order. Sending the same reference again never creates or charges a second order: you get the first order back with "duplicate": true. That makes it safe to retry after a timeout.- What you pay now: the products, a service fee (5% of each product's total, at least ₦1,900 and at most ₦70,000 a product; none on Official Store products), the shipping to Nigeria, and the delivery fee to the pickup station. Shipping is worked out for every product and quantity when you order, and the fee you pay is final: there is no extra shipping fee later. In the rare case that a fee cannot be worked out, that item's shipping shows as
pending: we send you a webhook with the fee, and you pay it with Pay Shipping. Items are processed only once their shipping is paid.shippingNoticesin the quote lists any warning for the chosen method, for example goods that can only go by sea.
| Body field | Description |
|---|---|
reference
string
Required |
Your own unique ID for this order: letters, numbers, . - _, up to 64 characters. Example:
ORDER-10045 |
items
array
Required |
The products. Each item has product_id (from Search Products), sku_id (a skuId from Get Product Details; Official Store products use their own skuId too), quantity, and optionally price: the naira unit price you expect. If the price has gone up, nothing is charged and you get PRICE_CHANGED with the new price. Up to 50 items. A product with a minimum order (moq) needs at least that many pieces across its variants. Example:
[{"product_id":"682718261723","sku_id":"5001","quantity":2,"price":4850}] |
shipping_method
string
International products |
air or sea, for the whole order. Not needed when every item is an Official Store product (their shipping is already in the price). Example:
air |
state
string
Required |
The pickup station's state, from List Pickup Stations. Example:
Lagos |
station
string
Required |
The pickup station's name, from List Pickup Stations. Example:
Ikota |
first_name
string
Required |
First name of the person who collects the order. Example:
Ada |
last_name
string
Required |
Last name of the person who collects the order. Example:
Obi |
phone
string
Required |
Their phone number. The pickup station contacts this number. Example:
08031234567 |
preview
boolean
Optional |
true returns the full price (as quote) without placing or paying for anything. Example:
true |
Try it live
Sent only to GSUBZ, through this page's server. We never store it. It stays in this browser tab until you close it.
preview as true to see the price without paying.About the response. amountPaid is what this order took from your wallet. Each item has its own status: PAID (order placed), PROCESSING, SHIPPED, IN_NIGERIA, OUT_FOR_DELIVERY, DELIVERED, RETURNED or CANCELLED. shipping.status is paid, due (pay it with Pay Shipping), pending (not weighed yet) or included (Official Store). weightKg and volumeCbm are filled in once the item is weighed. With preview=true the response has "preview": true and a quote object (shipping method, pickup station, parcelSize with the estimated weight and volume, amounts with totalNgn, shippingNotices, and the priced items) instead of order, and amountPaid is 0.
curl --location 'https://api.gsubz.com/api/store/order/' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"reference": "ORDER-10045",
"items": [
{
"product_id": "682718261723",
"sku_id": "5001",
"quantity": 2,
"price": 4850
}
],
"shipping_method": "air",
"state": "Lagos",
"station": "Ikota",
"first_name": "Ada",
"last_name": "Obi",
"phone": "08031234567",
"preview": true
}'
<?php
$payload = [
'reference' => 'ORDER-10045',
'items' => [
[
'product_id' => '682718261723',
'sku_id' => '5001',
'quantity' => 2,
'price' => 4850,
],
],
'shipping_method' => 'air',
'state' => 'Lagos',
'station' => 'Ikota',
'first_name' => 'Ada',
'last_name' => 'Obi',
'phone' => '08031234567',
'preview' => true,
];
$ch = curl_init('https://api.gsubz.com/api/store/order/');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY', 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode($payload),
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
print_r($data);
const payload = {
"reference": "ORDER-10045",
"items": [
{
"product_id": "682718261723",
"sku_id": "5001",
"quantity": 2,
"price": 4850
}
],
"shipping_method": "air",
"state": "Lagos",
"station": "Ikota",
"first_name": "Ada",
"last_name": "Obi",
"phone": "08031234567",
"preview": true
};
const response = await fetch("https://api.gsubz.com/api/store/order/", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
});
const data = await response.json();
console.log(data);
import requests
url = "https://api.gsubz.com/api/store/order/"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
payload = {
"reference": "ORDER-10045",
"items": [
{
"product_id": "682718261723",
"sku_id": "5001",
"quantity": 2,
"price": 4850,
},
],
"shipping_method": "air",
"state": "Lagos",
"station": "Ikota",
"first_name": "Ada",
"last_name": "Obi",
"phone": "08031234567",
"preview": True,
}
response = requests.post(url, headers=headers, json=payload, timeout=60)
print(response.json())
{
"code": 200,
"status": "successful",
"callID": 18500,
"scope": "place",
"amountPaid": 30676,
"initialBalance": 50000,
"finalBalance": 19324,
"date": "2026-10-13T10:05:40+01:00",
"api_response": "Order placed.",
"order": {
"orderId": 5231,
"reference": "ORDER-10045",
"dropship": true,
"createdAt": "2026-10-13T10:05:40+01:00",
"cancellableUntil": "2026-10-13T12:05:40+01:00",
"shippingMethod": "air",
"recipient": { "firstName": "Ada", "lastName": "Obi", "phone": "08031234567" },
"pickupStation": { "name": "Ikota", "address": "Ikota Shopping Complex, Lekki", "state": "Lagos" },
"amounts": {
"itemsNgn": 9700,
"serviceFeeNgn": 1900,
"shippingPaidNgn": 16676,
"shippingDueNgn": 0,
"deliveryNgn": 2400
},
"items": [
{
"itemId": 88120,
"productId": "682718261723",
"skuId": "5001",
"title": "Wireless Bluetooth Earbuds Noise Cancelling Headset",
"variation": "Black / Standard",
"image": "https://gsubz.com/store/image_proxy.php?url=https%3A%2F%2Fimg.example.com%2Fk1.jpg",
"quantity": 2,
"unitPriceNgn": 4850,
"lineTotalNgn": 9700,
"serviceFeeNgn": 1900,
"status": "PAID",
"shipping": {
"method": "air",
"weightKg": null,
"volumeCbm": null,
"status": "paid",
"unitNgn": 8338,
"totalNgn": 16676,
"paidNgn": 16676,
"dueNgn": 0
},
"trackingNumber": null,
"cancellable": true,
"cancelledAt": null
}
]
}
}
{
"code": 406,
"status": "failed",
"description": "PRICE_CHANGED",
"api_response": "The price of 1 item(s) went up. Nothing was charged. Check the new prices and send the order again.",
"callID": 18501,
"items": [
{ "product_id": "682718261723", "sku_id": "5001", "expectedPriceNgn": 4850, "currentPriceNgn": 4990 }
]
}
Returns one order when you send order_id or reference, in the same format as Place an Order. Without them it returns your API orders, newest first, 20 at a time. It is free. Use it to check an order after a timeout, or if you missed a webhook.
| Query parameter | Description |
|---|---|
order_id
integer
Optional |
The orderId from Place an Order. Example:
5231 |
reference
string
Optional |
Or your own reference. Example:
ORDER-10045 |
page
integer
Optional |
Page number when listing, starting at 1. Example:
1 |
Try it live
Sent only to GSUBZ, through this page's server. We never store it. It stays in this browser tab until you close it.
About the response. order has exactly the fields shown in Place an Order (shortened here). Without order_id or reference the response has page, pageSize, count, hasMore and an orders list instead.
curl --location 'https://api.gsubz.com/api/store/order/?order_id=5231&reference=ORDER-10045' \ --header 'Authorization: Bearer YOUR_API_KEY'
<?php
$ch = curl_init('https://api.gsubz.com/api/store/order/?order_id=5231&reference=ORDER-10045');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY'],
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
print_r($data);
const response = await fetch("https://api.gsubz.com/api/store/order/?order_id=5231&reference=ORDER-10045", {
headers: { Authorization: "Bearer YOUR_API_KEY" },
});
const data = await response.json();
console.log(data);
import requests
url = "https://api.gsubz.com/api/store/order/"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
payload = {
"order_id": "5231",
"reference": "ORDER-10045",
}
response = requests.get(url, headers=headers, params=payload, timeout=60)
print(response.json())
{
"code": 200,
"status": "successful",
"callID": 18510,
"scope": "orders",
"amountPaid": 0,
"initialBalance": 19324,
"finalBalance": 19324,
"date": "2026-10-14T09:00:00+01:00",
"api_response": "Order details.",
"order": {
"orderId": 5231,
"reference": "ORDER-10045",
"items": []
}
}
{
"code": 404,
"status": "failed",
"description": "CONTENT_NOT_FOUND",
"api_response": "Order not found.",
"callID": 18511
}
Cancels an order and refunds your wallet at once. You can cancel within 2 hours of placing the order, and only items that are still PAID (not yet being processed). Leave out item_id to cancel the whole order: this works only when no item is being processed yet. Otherwise cancel items one by one. Each cancelled item refunds its price, its service fee and any shipping paid. The delivery fee is refunded when the last item of the order is cancelled.
| Body field | Description |
|---|---|
action
string
Required |
Always cancel. Example:
cancel |
order_id
integer
Or reference |
The order to cancel. You can send reference instead. Example:
5231 |
reference
string
Optional |
Your own reference, instead of order_id. Example:
ORDER-10045 |
item_id
integer
Optional |
Cancel only this item (itemId). Leave it out to cancel the whole order. Example:
88120 |
Try it live
Sent only to GSUBZ, through this page's server. We never store it. It stays in this browser tab until you close it.
About the response. order is the updated order, in the same format as Place an Order (shortened here).
curl --location 'https://api.gsubz.com/api/store/order/' \ --header 'Authorization: Bearer YOUR_API_KEY' \ --form 'action="cancel"' \ --form 'order_id="5231"' \ --form 'item_id="88120"'
<?php
$ch = curl_init('https://api.gsubz.com/api/store/order/');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY'],
CURLOPT_POSTFIELDS => [
'action' => 'cancel',
'order_id' => '5231',
'item_id' => '88120',
],
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
print_r($data);
const form = new FormData();
form.append("action", "cancel");
form.append("order_id", "5231");
form.append("item_id", "88120");
const response = await fetch("https://api.gsubz.com/api/store/order/", {
method: "POST",
headers: { Authorization: "Bearer YOUR_API_KEY" },
body: form,
});
const data = await response.json();
console.log(data);
import requests
url = "https://api.gsubz.com/api/store/order/"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
payload = {
"action": "cancel",
"order_id": "5231",
"item_id": "88120",
}
response = requests.post(url, headers=headers, data=payload, timeout=60)
print(response.json())
{
"code": 200,
"status": "successful",
"callID": 18520,
"scope": "cancel",
"amountPaid": 0,
"initialBalance": 19324,
"finalBalance": 50000,
"date": "2026-10-13T10:40:12+01:00",
"api_response": "1 item(s) cancelled. ₦30,676.00 was refunded to your wallet.",
"refundedNgn": 30676,
"cancelled": [
{ "itemId": 88120, "refundNgn": 30676, "itemNgn": 9700, "serviceFeeNgn": 1900, "shippingNgn": 16676, "deliveryNgn": 2400 }
],
"order": { "orderId": 5231, "reference": "ORDER-10045", "items": [] }
}
{
"code": 406,
"status": "failed",
"description": "CANCEL_NOT_ALLOWED",
"api_response": "Orders can only be cancelled within 2 hours of ordering.",
"callID": 18521
}
When we weigh an item whose shipping was pending, or the weight turns out higher than listed, its shipping.status becomes due and you get a webhook with the new weight, size and fee. This pays everything due on the order from your wallet (or only one item with item_id). Items move to processing once their shipping is paid. Nothing waits on a deadline: an item stays on hold until it is paid.
| Body field | Description |
|---|---|
action
string
Required |
Always pay_shipping. Example:
pay_shipping |
order_id
integer
Or reference |
The order. You can send reference instead. Example:
5231 |
reference
string
Optional |
Your own reference, instead of order_id. Example:
ORDER-10045 |
item_id
integer
Optional |
Pay only this item. Leave it out to pay everything due on the order. Example:
88121 |
Try it live
Sent only to GSUBZ, through this page's server. We never store it. It stays in this browser tab until you close it.
About the response. amountPaid is the shipping taken from your wallet. order is the updated order (shortened here).
curl --location 'https://api.gsubz.com/api/store/order/' \ --header 'Authorization: Bearer YOUR_API_KEY' \ --form 'action="pay_shipping"' \ --form 'order_id="5231"'
<?php
$ch = curl_init('https://api.gsubz.com/api/store/order/');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY'],
CURLOPT_POSTFIELDS => [
'action' => 'pay_shipping',
'order_id' => '5231',
],
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
print_r($data);
const form = new FormData();
form.append("action", "pay_shipping");
form.append("order_id", "5231");
const response = await fetch("https://api.gsubz.com/api/store/order/", {
method: "POST",
headers: { Authorization: "Bearer YOUR_API_KEY" },
body: form,
});
const data = await response.json();
console.log(data);
import requests
url = "https://api.gsubz.com/api/store/order/"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
payload = {
"action": "pay_shipping",
"order_id": "5231",
}
response = requests.post(url, headers=headers, data=payload, timeout=60)
print(response.json())
{
"code": 200,
"status": "successful",
"callID": 18530,
"scope": "pay_shipping",
"amountPaid": 4356,
"initialBalance": 19324,
"finalBalance": 14968,
"date": "2026-10-16T14:20:00+01:00",
"api_response": "Shipping paid for 1 item(s).",
"paid": [ { "id": 88121, "amount": 4356 } ],
"order": { "orderId": 5231, "reference": "ORDER-10045", "items": [] }
}
{
"code": 406,
"status": "failed",
"description": "NOTHING_DUE",
"api_response": "No shipping fee is due on this order right now.",
"callID": 18531
}
Transactions
Check the status and response of a purchase using the requestID you sent when you made it, or the transactionID GSUBZ returned. Use this whenever a purchase request times out or returns no response, before you try again. Electricity purchases also return their token, and social media orders return their live progress.
status field, not just the response code.- Send either
requestIDortransactionID: whichever you have. Only your own transactions are searched. If you send neither, the request is refused with code400. - Electricity. The response carries
token, the meter token. If the token was not available when you bought, it is fetched for you now, so a purchase whose token you never received can be recovered by calling this endpoint. If the token is still not ready,tokenis left out: try again in a minute. A failed or refunded purchase never has a token. - Social media. The response carries
order: the live progress of the order, withstatus,start_count(the count when the order started) andremains(how many are still to be delivered). It is left out if the progress cannot be read right now.
| Body field | Description |
|---|---|
api
string
Required |
Your API key. Send the same key you use in the Authorization header. Example:
YOUR_API_KEY |
requestID
string
Or transactionID |
The requestID you passed during the purchase. Send this or transactionID. Example:
7wbd7wbdw7d72g6vd |
transactionID
string
Optional |
The transactionID from the purchase response. Send this or requestID. Example:
3574357094 |
Try it live
Sent only to GSUBZ, through this page's server. We never store it. It stays in this browser tab until you close it.
About the response. transaction_id is GSUBZ's reference and amount is what the purchase cost you, in naira. Electricity adds "token": "47488383838383838383833". Social media adds "order": { "status": "In progress", "start_count": "0", "remains": "850" }. Other services return neither.
curl --location 'https://api.gsubz.com/api/verify/' \ --header 'Authorization: Bearer YOUR_API_KEY' \ --form 'api="YOUR_API_KEY"' \ --form 'requestID="7wbd7wbdw7d72g6vd"'
<?php
$ch = curl_init('https://api.gsubz.com/api/verify/');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY'],
CURLOPT_POSTFIELDS => [
'api' => 'YOUR_API_KEY',
'requestID' => '7wbd7wbdw7d72g6vd',
],
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
print_r($data);
const form = new FormData();
form.append("api", "YOUR_API_KEY");
form.append("requestID", "7wbd7wbdw7d72g6vd");
const response = await fetch("https://api.gsubz.com/api/verify/", {
method: "POST",
headers: { Authorization: "Bearer YOUR_API_KEY" },
body: form,
});
const data = await response.json();
console.log(data);
import requests
url = "https://api.gsubz.com/api/verify/"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
payload = {
"api": "YOUR_API_KEY",
"requestID": "7wbd7wbdw7d72g6vd",
}
response = requests.post(url, headers=headers, data=payload, timeout=60)
print(response.json())
{
"code": "200",
"status": "success",
"description": "TRANSACTION_SUCCESSFUL",
"transaction_id": "3574357094",
"amount": "1100",
"api_response": "Dear Customer, You have successfully shared 1GB Data to 2349063648020. Your SME data balance is 28955.68GB expires 30/01/2024. Thankyou"
}
{
"code": "404",
"description": "CONTENT_NOT_FOUND_API_OR_NOT_FOUND",
"status": "TRANSACTION_FAILED"
}