BILLS PAYMENT
Buy Airtime
Top up a phone number with airtime on any supported network.
POST /v1/bills/airtime
Use this endpoint to
- Purchase airtime for any phone number on a supported network
- Charge the business NGN wallet for amounts between NGN 50 and NGN 20,000
- Safely retry a purchase without double-charging, using
reference
Request
Body parameters
| Field | Type | Required | Description |
|---|---|---|---|
network |
string | Yes | Biller slug from Get Billers (e.g. MTN) |
phone |
string | Yes | Recipient phone number |
amount |
number | Yes | NGN 50–20,000 |
reference |
string | Yes | Your unique idempotency key for this purchase |
Code Samples
const response = await fetch("https://sandbox.hitchpay.ng/v1/bills/airtime", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_ACCESS_TOKEN",
"Content-Type": "application/json"
},
body: JSON.stringify({
network: "MTN",
phone: "08012345678",
amount: 500,
reference: "order-airtime-001"
})
});
const data = await response.json();
console.log(data);<?php
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => "https://sandbox.hitchpay.ng/v1/bills/airtime",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode([
"network" => "MTN",
"phone" => "08012345678",
"amount" => 500,
"reference" => "order-airtime-001"
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer YOUR_ACCESS_TOKEN",
"Content-Type: application/json"
]
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;import requests
url = "https://sandbox.hitchpay.ng/v1/bills/airtime"
headers = {
"Authorization": "Bearer YOUR_ACCESS_TOKEN",
"Content-Type": "application/json"
}
payload = {
"network": "MTN",
"phone": "08012345678",
"amount": 500,
"reference": "order-airtime-001"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())Response
Success
{
"status": "success",
"message": "Bill payment successful.",
"data": {
"reference": "HTCHB…",
"merchant_reference": "order-airtime-001",
"product": "airtime",
"provider": "MTN",
"amount": 500,
"fee": 0,
"amount_charged": 500,
"recipient": "08012345678",
"currency": "NGN",
"balance": 12450.75,
"paid_at": "2026-07-02T10:15:00.000Z"
}
}Pending
{
"status": "success",
"message": "Bill payment is processing",
"data": {
"reference": "HTCHB…",
"merchant_reference": "order-airtime-001",
"product": "airtime",
"provider": "MTN",
"amount": 500,
"recipient": "08012345678",
"currency": "NGN"
}
}If you get a pending response, poll Get Transaction Status or listen for the bill.success / bill.failed webhook to get the final state.
Fields
| Field | Type | Description |
|---|---|---|
reference |
string | Our transaction id — use this for status polling |
merchant_reference |
string | Echoes the reference you sent |
product |
string | airtime |
provider |
string | Network the airtime was sent to |
amount |
number | Amount requested |
fee |
number | Fee charged, if any |
amount_charged |
number | Total debited from your wallet (amount + fee) |
recipient |
string | Phone number credited |
currency |
string | NGN |
balance |
number | Your wallet balance after this transaction |
paid_at |
string | ISO 8601 timestamp |
Errors
| Code | Meaning |
|---|---|
INVALID_REQUEST |
Missing/invalid fields, or amount outside NGN 50–20,000 |
UNAUTHORIZED |
Business not found or inactive |
PRODUCT_UNAVAILABLE |
No matching network configured |
INSUFFICIENT_BALANCE |
Wallet balance too low |
BILL_FAILED |
Provider declined the purchase — wallet is auto-refunded |
PROVIDER_ERROR |
Provider call failed |
Idempotent by design: retrying this request with the same reference will never double-charge — you'll get the original transaction back instead.
Questions? Email [email protected]. Also on GitBook.