Endpoint Details
HTTP Method
POST
Route Path
/api/v2/cable-tv
Base URL
https://app.9jabillz.com.ng
Authentication
HMAC SHA256
Request Body Parameters
Send request parameters formatted as a raw JSON payload:
| Field | Type | Required | Description |
|---|---|---|---|
provider |
String | Yes | Target cable provider code (dstv, gotv, startimes, showmax). Alias: service_id. |
smartcard_number |
String | Yes | Customer's Smartcard or IUC number. Alias: iuc_number. |
variation_code |
String | Yes | Stable merchant package code retrieved from /api/v2/cable-tv/packages (e.g. gotv-jolli). Aliases: package_code, plan_id. |
request_ref |
String | Yes | Your system's unique transaction reference for idempotency checking. Alias: reference. |
amount |
Number | Optional | Subscription cost in NGN. Automatically resolved via database lookup if omitted. |
phone_number |
String | Optional | Recipient contact phone number. Fallback to registered reseller phone if omitted. Alias: phone. |
Sample Request JSON Payload
Request Body
{
"provider": "gotv",
"smartcard_number": "7024163821",
"variation_code": "gotv-jolli",
"request_ref": "CAB_TEST_9JA_001",
"phone_number": "08012345678"
}
Required Request Headers
Requests require valid HMAC SHA256 security headers generated using your reseller public API key and secret key:
| Header Name | Type | Required | Description |
|---|---|---|---|
Content-Type |
String | Yes | Must be set to application/json |
Accept |
String | Yes | Must be set to application/json |
X-API-KEY |
String | Yes | Your public API key (9ja_live_pk_...) |
X-API-SIGNATURE |
String | Yes | Hex-encoded HMAC SHA256 signature generated with your Secret Key. |
X-API-TIMESTAMP |
String | Yes | Current Unix timestamp in seconds (time()). Max skew: 300s. |
X-API-NONCE |
String | Yes | Unique random alphanumeric string per request. |
HMAC SHA256 Signature Formula (POST Request)
Signature Payload Formula
CanonicalData = METHOD + "\n" + REQUEST_PATH + "\n" + TIMESTAMP + "\n" + NONCE + "\n" + SHA256(RawJsonBody)
Example = "POST\n/api/v2/cable-tv\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/cable-tv";
$url = "https://app.9jabillz.com.ng" . $path;
$method = "POST";
$timestamp = (string) time();$nonce = bin2hex(random_bytes(8));
$payloadArray = [
"provider" => "gotv",
"smartcard_number" => "7024163821",
"variation_code" => "gotv-jolli",
"request_ref" => "CAB_" . uniqid(),
"phone_number" => "08012345678"
];
$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/cable-tv';
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({
provider: "gotv",
smartcard_number: "7024163821",
variation_code: "gotv-jolli",
request_ref: "CAB_" + Date.now(),
phone_number: "08012345678"
});
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/cable-tv"
url = f"https://app.9jabillz.com.ng{path}"
method = "POST"
timestamp = str(int(time.time()))
nonce = secrets.token_hex(8)
payload_data = {
"provider": "gotv",
"smartcard_number": "7024163821",
"variation_code": "gotv-jolli",
"request_ref": f"CAB_{int(time.time())}",
"phone_number": "08012345678"
}
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_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
HTTP 200 OK (Success Response)
JSON Response Payload
{
"status": true,
"message": "Cable TV subscription processed successfully.",
"data": {
"status": "successful",
"request_ref": "CAB_TEST_9JA_001",
"reference": "API-CAB-9JABILLZ-839201",
"amount": 4850.00,
"package_name": "GOtv Jolli",
"cashback_earned": 0.00,
"smartcard_number": "7024163821",
"provider": "GOTV"
}
}
Response Field Definitions
| Field | Type | Description |
|---|---|---|
status |
Boolean | Indicates overall operation status (true on success). |
message |
String | Human-readable response summary. |
data.status |
String | Final transaction status (successful or pending). |
data.request_ref |
String | Reseller-provided unique request reference echoed back. |
data.reference |
String | System-generated unique transaction reference (API-CAB-...). |
data.amount |
Number | Total amount charged from reseller wallet in NGN. |
data.package_name |
String | Title of the activated cable package. |
data.cashback_earned |
Number | Reseller commission/cashback earned on transaction in NGN. |
data.smartcard_number |
String | Recipient Smartcard or IUC number credited. |
data.provider |
String | Uppercase target cable provider code (GOTV, DSTV, STARTIMES). |
Error Handling
| HTTP Code | Error Response Message | Description |
|---|---|---|
400 Bad Request |
Required fields missing: service_id, smartcard_number, variation_code, request_ref. | One or more required body parameters missing. |
400 Bad Request |
Insufficient API wallet balance. | Reseller wallet balance lower than package price. |
401 Unauthorized |
Authentication required. Invalid or missing API key or HMAC signature. | Header verification failed, timestamp expired, or signature mismatch. |
404 Not Found |
Invalid cable package variation code. | Supplied variation_code not found or inactive. |
405 Method Not Allowed |
Method Not Allowed | Sent request verb other than POST. |
409 Conflict |
Duplicate request_ref detected. | request_ref has already been processed previously. |
502 Bad Gateway |
Cable TV vendor dispatch failed. | Upstream vendor error; wallet automatically refunded. |
500 Internal Error |
Server error processing API Cable TV request. | Server or database exception. |