INSTANT DELIVERY Fast Bills & Electricity Payment — Guaranteed 24/7 Service
API Documentation Sandbox Environment
Documentation Data Services

POST Purchase Data Bundle

Programmatically dispatch mobile data subscriptions across MTN, Glo, Airtel, and 9mobile. Cashback commissions are calculated automatically and credited back to your API wallet.

Endpoint Details

HTTP Method
POST
Route Path
/api/v2/data-bundle
Base URL
https://app.9jabillz.com.ng
Authentication
HMAC SHA256
Alternative Alias Route
You can also call /api/reseller/data interchangeably.

Request Body Parameters

Send request parameters formatted as a raw JSON payload:

Parameter Type Required Description
network String Yes Telecom network operator. Supported values: MTN, GLO, AIRTEL, 9MOBILE
phone String Yes 11-digit recipient phone number (e.g., 08031234567)
variation_code String Yes The unique plan identifier obtained from /api/v2/data-plans (e.g., mtn-10mb-100)
request_ref String Yes Your unique merchant request reference string for idempotency and duplicate prevention

Sample Request JSON Payload

Request Body
{
  "network": "MTN",
  "phone": "08031234567",
  "variation_code": "mtn-10mb-100",
  "request_ref": "DAT-TEST-2001"
}

HMAC SHA256 Signature Formula

For POST requests, concatenate parameters using newline (\n) separators and include the SHA256 hex hash of the raw JSON request body:

Signature Payload Formula
CanonicalData = METHOD + "\n" + REQUEST_PATH + "\n" + TIMESTAMP + "\n" + NONCE + "\n" + SHA256(RawJsonBody)
Example       = "POST\n/api/v2/data-bundle\n1792008086\na1b2c3d4e5\n" + SHA256(RawJsonBody)
Signature     = LOWERCASE_HEX( HMAC_SHA256(CanonicalData, YOUR_SECRET_KEY) )

Integration Code Examples

Select your programming language below to view production-ready implementation snippets:

<?php
$apiKey    = "YOUR_LIVE_API_KEY";
$secretKey = "YOUR_LIVE_SECRET_KEY";

$path      = "/api/v2/data-bundle";
$url       = "https://app.9jabillz.com.ng" . $path;
$method    = "POST";
$timestamp = (string) time();$nonce     = bin2hex(random_bytes(8));

$payloadArray = [
    "network"        => "MTN",
    "phone"          => "08031234567",
    "variation_code" => "mtn-10mb-100",
    "request_ref"    => "DAT-" . uniqid()
];

$rawBody   = json_encode($payloadArray);
$bodyHash  = hash('sha256',$rawBody);

// Construct Canonical String Joined by Newline
$canonicalData = implode("\n", [
    strtoupper($method),
    $path,$timestamp,
    $nonce,$bodyHash
]);

$signature = hash_hmac('sha256', $canonicalData,$secretKey);

$headers = [
    "Content-Type: application/json",
    "Accept: application/json",
    "X-API-KEY: " . $apiKey,
    "X-API-SIGNATURE: " . $signature,
    "X-API-TIMESTAMP: " . $timestamp,
    "X-API-NONCE: " . $nonce
];

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS,$rawBody);
curl_setopt($ch, CURLOPT_HTTPHEADER,$headers);

$response = curl_exec($ch);
curl_close($ch);

echo $response;
const axios = require('axios');
const crypto = require('crypto');

const apiKey    = 'YOUR_LIVE_API_KEY';
const secretKey = 'YOUR_LIVE_SECRET_KEY';

const path      = '/api/v2/data-bundle';
const url       = `https://app.9jabillz.com.ng${path}`;
const method    = 'POST';
const timestamp = Math.floor(Date.now() / 1000).toString();
const nonce     = crypto.randomBytes(8).toString('hex');

const requestBody = JSON.stringify({
    network: "MTN",
    phone: "08031234567",
    variation_code: "mtn-10mb-100",
    request_ref: "DAT-" + Date.now()
});

const bodyHash = crypto.createHash('sha256').update(requestBody).digest('hex');

const canonicalData = [
    method.toUpperCase(),
    path,
    timestamp,
    nonce,
    bodyHash
].join('\n');

const signature = crypto.createHmac('sha256', secretKey)
                        .update(canonicalData)
                        .digest('hex');

axios.post(url, requestBody, {
    headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json',
        'X-API-KEY': apiKey,
        'X-API-SIGNATURE': signature,
        'X-API-TIMESTAMP': timestamp,
        'X-API-NONCE': nonce
    }
})
.then(response => console.log(response.data))
.catch(error => console.error(error.response ? error.response.data : error.message));
import time
import secrets
import hmac
import hashlib
import json
import requests

api_key    = "YOUR_LIVE_API_KEY"
secret_key = "YOUR_LIVE_SECRET_KEY"

path      = "/api/v2/data-bundle"
url       = f"https://app.9jabillz.com.ng{path}"
method    = "POST"
timestamp = str(int(time.time()))
nonce     = secrets.token_hex(8)

payload_data = {
    "network": "MTN",
    "phone": "08031234567",
    "variation_code": "mtn-10mb-100",
    "request_ref": f"DAT-{int(time.time())}"
}

raw_body  = json.dumps(payload_data, separators=(',', ':'))
body_hash = hashlib.sha256(raw_body.encode('utf-8')).hexdigest()

canonical_data = f"{method.upper()}\n{path}\n{timestamp}\n{nonce}\n{body_hash}"
signature = hmac.new(secret_key.encode('utf-8'), canonical_data.encode('utf-8'), hashlib.sha256).hexdigest()

headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
    "X-API-KEY": api_key,
    "X-API-SIGNATURE": signature,
    "X-API-TIMESTAMP": timestamp,
    "X-API-NONCE": nonce
}

response = requests.post(url, data=raw_body, headers=headers)
print(response.json())
// Postman Pre-request Script Tab:
const secretKey = "YOUR_LIVE_SECRET_KEY";

const timestamp = Math.floor(Date.now() / 1000).toString();
const nonce     = Math.random().toString(36).substring(2, 15);
const method    = pm.request.method.toUpperCase();
const path      = pm.request.url.getPath();
const body      = pm.request.body && pm.request.body.raw ? pm.request.body.raw : "";

const bodyHash  = CryptoJS.SHA256(body).toString(CryptoJS.enc.Hex);

const canonicalData = [method, path, timestamp, nonce, bodyHash].join("\n");
const signature = CryptoJS.HmacSHA256(canonicalData, secretKey).toString(CryptoJS.enc.Hex);

pm.variables.set("X-API-TIMESTAMP", timestamp);
pm.variables.set("X-API-NONCE", nonce);
pm.variables.set("X-API-SIGNATURE", signature);

Response Schema

Successful Response (200 OK)

JSON Response Payload
{
    "status": true,
    "message": "Data bundle delivered successfully.",
    "data": {
        "status": "successful",
        "request_ref": "DAT-TEST-2001",
        "reference": "APIDAT-20261014232213-3CB4E139",
        "amount": 100,
        "plan_name": "110MB Daily Plan (1 Day) - N100",
        "cashback_earned": 2.5,
        "recipient": "08031234567",
        "provider": "MTN"
    }
}

Field Definitions

Property Type Description
status Boolean true when request processing completes successfully.
message String Executive outcome description.
data.status String Order status (successful or pending).
data.request_ref String Your unique merchant request reference string.
data.reference String System transaction reference generated by 9jaBillz.
data.amount Float Face value amount charged to your wallet in Naira (NGN).
data.plan_name String Human-readable title of the delivered data bundle.
data.cashback_earned Float Cashback commission credited instantly to your wallet.
data.recipient String Recipient phone number that received the data top-up.
data.provider String Telecommunication provider name (MTN, GLO, AIRTEL, 9MOBILE).

Error Handling

HTTP Code Error Reason Example Response Payload
400 Bad Request Validation Error / Missing Fields {"status": false, "message": "Required fields missing: phone_number, provider, variation_code, request_ref."}
400 Bad Request Insufficient Balance {"status": false, "message": "Insufficient API wallet balance."}
401 Unauthorized Invalid HMAC Signature {"status": false, "message": "Invalid API request signature."}
404 Not Found Invalid Variation Code {"status": false, "message": "Invalid or inactive data plan variation code for specified provider."}
409 Conflict Replayed request_ref {"status": false, "message": "Duplicate request_ref detected."}
502 Bad Gateway Vendor Dispatch Failure {"status": false, "message": "Data dispatch failed."}