Airtime Recharge (Virtual Top up)
Table of Contents
- Overview
- Supported Services
- Getting Started
- Authentication
- Integration Flow
- Step-by-Step Implementation
- Airtime vs Data Bundle Recharge
- Telco-Specific Details
- Field Reference
- Response Codes
- Test Data
- Implementation Examples
- Best Practices
- Troubleshooting
Overview
The Airtime & Data Recharge API (also known as Virtual Top-Up or VTU) enables merchants to programmatically purchase airtime and data bundles for all major Nigerian telecommunications networks. This service provides real-time airtime and data top-up functionality directly integrated into your applications.
Key Features
- ✅ Instant Delivery: Airtime and data credited within seconds
- ✅ All Major Networks: MTN, Airtel, Glo, 9mobile, and more
- ✅ Flexible Amounts: Any amount (subject to network limits)
- ✅ Data Bundles: Purchase specific data packages
- ✅ Bulk Recharge: Support for multiple recharges
- ✅ Real-time Status: Query transaction status instantly
- ✅ Commission Earnings: Earn commission on every recharge
How It Works
The diagram below explains further:

Process Flow:
- Customer requests airtime/data recharge on your app
- You charge customer's wallet/card
- API submits recharge request to telco
- Telco credits customer's phone
- Your virtual card is debited
- You earn commission
Supported Services
Airtime Recharge (VTU)
- MTN Airtime - Any amount from ₦50 to ₦10,000
- Airtel Airtime - Any amount from ₦50 to ₦10,000
- Glo Airtime - Any amount from ₦50 to ₦10,000
- 9mobile Airtime - Any amount from ₦50 to ₦10,000
Data Bundle Recharge
- MTN Data Bundles - Daily, weekly, monthly plans
- Airtel Data Bundles - Daily, weekly, monthly plans
- Glo Data Bundles - Daily, weekly, monthly plans
- 9mobile Data Bundles - Daily, weekly, monthly plans
Getting Started
Prerequisites
Before integrating, ensure you have:
- ✅ Active merchant account with Interswitch
- ✅ Terminal ID for authentication
- ✅ OAuth credentials (Client ID and Secret)
- ✅ Virtual card linked to your account
- ✅ Valid test phone numbers
Base URLs
| Environment | Base URL |
|---|---|
| QA/Testing | https://qa.interswitchng.com/quicktellerservice/api/v5 |
| Production | https://interswitchng.com/quicktellerservice/api/v5 |
Authentication Endpoint
POST https://passport-v2.k8.isw.la/passport/oauth/token
Authentication
All API requests require a Bearer token. Generate your access token using OAuth 2.0 client credentials flow.
Token Generation
Request:
curl --location 'https://passport-v2.k8.isw.la/passport/oauth/token' \
--header 'Authorization: Basic <BASE64_ENCODED_CREDENTIALS>' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'scope=profile' \
--data-urlencode 'grant_type=client_credentials'Headers:
| Header | Value | Description |
|---|---|---|
Authorization | Basic <credentials> | Base64 encoded client_id:client_secret |
Content-Type | application/x-www-form-urlencoded | Request format |
Response:
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "bearer",
"expires_in": 43199,
"scope": "profile",
"merchant_code": "MX52988",
"terminalId": "3PBL0001",
"env": "TEST",
"client_name": "QTSVA UAT"
}Important: Tokens expire after approximately 12 hours. Implement token refresh in production.
Integration Flow
Step 1: Get Categories
│
▼
Step 2: Get Telcos/Billers (Category ID: 4)
│
▼
Step 3: Get Payment Items (Optional - for data bundles)
│
▼
Step 4: Validate Customer (Optional but recommended)
│
▼
Step 5: Process Recharge
│
▼
Step 6: Query Transaction Status
Step-by-Step Implementation
Step 1: Get Categories
Purpose: Retrieve all available service categories to identify where airtime recharge is located.
Description: This step returns all service categories. For airtime and data recharge, look for the "Mobile/Recharge" category with ID: 4.
Endpoint: GET /services/categories
Request:
curl 'https://qa.interswitchng.com/quicktellerservice/api/v5/services/categories' \
-H 'Authorization: Bearer <TOKEN>' \
-H 'terminalId: <YOUR_TERMINAL_ID>' \
-H 'Content-Type: application/json' \
-X GETResponse:
{
"BillerCategories": [
{
"Id": 1,
"Name": "Utility Bills",
"Description": "Pay your utility bills here",
"Billers": []
},
{
"Id": 2,
"Name": "Cable TV Bills",
"Description": "Pay for your cable TV subscriptions here",
"Billers": []
},
{
"Id": 4,
"Name": "Mobile/Recharge",
"Description": "Recharge your phone",
"Billers": []
}
],
"ResponseCode": "90000",
"ResponseCodeGrouping": "SUCCESSFUL"
}Key Point: Note the Id for "Mobile/Recharge" - this is 4 (not 3 as incorrectly stated in some docs).
Step 2: Get Telcos/Billers
Purpose: Retrieve all available telecom providers (billers) within the Mobile/Recharge category.
Description: This step returns all telcos (MTN, Airtel, Glo, 9mobile, etc.) with their unique biller IDs and configuration details. Use categoryId=4 for airtime/data services.
Endpoint: GET /services?categoryId={id}
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
categoryId | Integer | Yes | Use 4 for Mobile/Recharge |
Request:
curl 'https://qa.interswitchng.com/quicktellerservice/api/v5/services?categoryId=4' \
-H "Authorization: Bearer <TOKEN>" \
-H "Content-Type: application/json" \
-H "TerminalId: <YOUR_TERMINAL_ID>" \
-X GETResponse:
{
"BillerList": {
"Count": 25,
"Category": [
{
"Id": 4,
"Name": "Mobile/Recharge",
"Description": "Recharge your phone",
"Billers": [
{
"Id": 109,
"Name": "MTN e-Charge Prepaid",
"ShortName": "MTNVTU1",
"Narration": "Purchase MTN Virtual Airtime",
"CustomerField1": "Phone Number",
"CurrencyCode": "566",
"CurrencySymbol": "NGN",
"AmountType": 2,
"CategoryId": 4,
"CategoryName": "Mobile/Recharge",
"NetworkId": "628051043",
"ProductCode": "628051043",
"Type": "MO"
},
{
"Id": 120,
"Name": "Etisalat Recharge Top-Up",
"ShortName": "ETILAT",
"Narration": "Buy Etisalat recharge",
"CustomerField1": "Phone No",
"CurrencyCode": "566",
"CurrencySymbol": "NGN",
"AmountType": 0,
"CategoryId": 4,
"CategoryName": "Mobile/Recharge",
"NetworkId": "6280510425",
"ProductCode": "6280510490",
"Type": "MO"
},
{
"Id": 402,
"Name": "Glo QuickCharge",
"ShortName": "GLOQCK",
"Narration": "Mobile Top-Up",
"CustomerField1": "Mobile number",
"CurrencyCode": "566",
"CurrencySymbol": "NGN",
"AmountType": 0,
"CategoryId": 4,
"CategoryName": "Mobile/Recharge",
"NetworkId": "628051045",
"ProductCode": "628051045",
"Type": "MO"
},
{
"Id": 687,
"Name": "Airtel Data Bundles",
"ShortName": "Airtel",
"Narration": "Airtel Data",
"CustomerField1": "Phone Number",
"CurrencyCode": "566",
"CurrencySymbol": "NGN",
"AmountType": 0,
"CategoryId": 4,
"CategoryName": "Mobile/Recharge",
"NetworkId": "6280510425",
"ProductCode": "6280510425",
"Type": "MP"
}
]
}
]
},
"ResponseCode": "90000",
"ResponseCodeGrouping": "SUCCESSFUL"
}Key Fields:
| Field | Description |
|---|---|
Id | Unique biller ID (e.g., 109 for MTN) |
Name | Telco name |
ShortName | Abbreviation (e.g., MTNVTU1) |
CustomerField1 | Input label for phone number |
AmountType | 0=Any Amount, 2=Fixed (see Amount Types) |
NetworkId | Network identifier |
ProductCode | Product code for transactions |
Type | MO=Mobile Operator, MP=Mobile Product |
Step 3: Get Payment Items (Optional)
Purpose: Retrieve specific data bundle options or fixed airtime denominations.
Description: This step is optional for regular airtime (AmountType 0) but required for data bundles or fixed airtime amounts (AmountType 2 or 5). It returns available packages with specific amounts and payment codes.
When to Use:
- Airtime (Any Amount): Skip this step - use any amount between ₦50-₦10,000
- Data Bundles: Required - returns specific data plans
- Fixed Airtime: Required - returns specific denominations
Endpoint: GET /services/options?serviceid={billerid}
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
serviceid | Integer | Yes | The biller ID from Step 2 |
Request:
curl 'https://qa.interswitchng.com/quicktellerservice/api/v5/services/options?serviceid=687' \
-H "Authorization: Bearer <TOKEN>" \
-H "Content-Type: application/json" \
-H "TerminalID: <YOUR_TERMINAL_ID>" \
-X GETResponse (Data Bundle Example):
{
"PaymentItems": [
{
"Id": "01",
"Name": "Airtel 100MB Daily",
"BillerName": "Airtel Data Bundles",
"ConsumerIdField": "Phone Number",
"Code": "01",
"BillerType": "MP",
"ItemFee": "0",
"Amount": "10000",
"BillerId": "687",
"BillerCategoryId": "4",
"CurrencyCode": "566",
"CurrencySymbol": "NGN",
"IsAmountFixed": true,
"PaymentCode": "10903",
"AmountType": 2,
"PaydirectItemCode": "6280510425"
},
{
"Id": "02",
"Name": "Airtel 1.5GB Monthly",
"BillerName": "Airtel Data Bundles",
"ConsumerIdField": "Phone Number",
"Code": "02",
"BillerType": "MP",
"ItemFee": "0",
"Amount": "100000",
"BillerId": "687",
"BillerCategoryId": "4",
"CurrencyCode": "566",
"CurrencySymbol": "NGN",
"IsAmountFixed": true,
"PaymentCode": "10904",
"AmountType": 2,
"PaydirectItemCode": "6280510426"
}
],
"ResponseCode": "90000",
"ResponseCodeGrouping": "SUCCESSFUL"
}Key Fields:
| Field | Description |
|---|---|
PaymentCode | Critical - Use this for recharge requests |
Amount | Amount in kobo (e.g., 10000 = ₦100) |
IsAmountFixed | If true, amount cannot be changed |
Name | Human-readable bundle name |
Step 4: Validate Customer (Optional but Recommended)
Purpose: Verify that the phone number is valid and active before processing recharge.
Description: While optional for airtime recharge, this step is recommended to prevent failed transactions. It validates the phone number format and checks if the number is active on the network.
Endpoint: POST /Transactions/validatecustomers
Request:
curl 'https://qa.interswitchng.com/quicktellerservice/api/v5/Transactions/validatecustomers' \
-H "Authorization: Bearer <TOKEN>" \
-H "Content-Type: application/json" \
-H "TerminalID: <YOUR_TERMINAL_ID>" \
-d '{
"customers": [
{
"PaymentCode": "10903",
"CustomerId": "234805673157"
}
],
"TerminalId": "3PBL0001"
}' \
-X POSTRequest Body:
| Field | Type | Required | Description |
|---|---|---|---|
customers | Array | Yes | Array of customer objects |
customers[].PaymentCode | String | Yes | Payment code from Step 2 or 3 |
customers[].CustomerId | String | Yes | Phone number to validate |
TerminalId | String | Yes | Your terminal ID |
Response:
{
"Customers": [
{
"BillerId": 109,
"PaymentCode": "10903",
"CustomerId": "234805673157",
"ResponseCode": "90000",
"FullName": "MTN Customer",
"Amount": 0,
"AmountType": 0,
"AmountTypeDescription": "AnyAmount",
"Surcharge": 0
}
],
"ResponseCode": "90000",
"ResponseCodeGrouping": "SUCCESSFUL"
}Important:
ResponseCode: 90000= Valid phone numberResponseCode: 90001or90002= Invalid phone number- If validation fails, do not proceed with recharge
Step 5: Process Recharge
Purpose: Submit the airtime or data bundle recharge request.
Description: This is the main transaction endpoint. Upon success, the phone number is credited with airtime or data, and your virtual card is debited for the transaction amount.
Endpoint: POST /Transactions
Request:
curl 'https://qa.interswitchng.com/quicktellerservice/api/v5/Transactions' \
-H "Authorization: Bearer <TOKEN>" \
-H "Content-Type: application/json" \
-H "TerminalID: <YOUR_TERMINAL_ID>" \
-d '{
"TerminalId": "3PBL0001",
"paymentCode": "10903",
"customerId": "234805673157",
"customerMobile": "234805673157",
"customerEmail": "[email protected]",
"amount": "100000",
"requestReference": "145300000001"
}' \
-X POSTRequest Body Fields:
| Field | Type | Required | Description |
|---|---|---|---|
TerminalId | String | Yes | Your terminal ID |
paymentCode | String | Yes | Payment code from Step 2 or 3 |
customerId | String | Yes | Phone number to recharge |
customerMobile | String | Yes | Customer's mobile number (same as customerId) |
customerEmail | String | No | Customer's email for receipts |
amount | String | Yes | Amount in kobo (e.g., "100000" for ₦1,000) |
requestReference | String | Yes | Unique reference (max 20 chars) |
Amount Conversion:
- ₦100 = "10000" (multiply by 100)
- ₦500 = "50000"
- ₦1,000 = "100000"
- ₦5,000 = "500000"
Response:
{
"TransactionRef": "PBL|Web|3PBL0001|MTNVTU1|010223180453|4WNYQJ3NDB",
"ApprovedAmount": "100000",
"AdditionalInfo": {
"network": "MTN",
"phoneNumber": "234805673157",
"amountCredited": "1000.00"
},
"ResponseCode": "90000",
"ResponseDescription": "Success",
"ResponseCodeGrouping": "SUCCESSFUL"
}Response Fields:
| Field | Description |
|---|---|
TransactionRef | Unique transaction reference (save this!) |
ApprovedAmount | Amount processed in kobo |
AdditionalInfo | Transaction details |
ResponseCode | 90000 = Success |
ResponseDescription | Human-readable status |
Transaction Flow:
- Submit recharge request
- API validates request
- Telco processes recharge
- Phone is credited (usually within 5-10 seconds)
- Your virtual card is debited
- Commission is credited to your wallet
Step 6: Query Transaction Status
Purpose: Check the status of a recharge transaction.
Description: Use this endpoint to verify transaction status, especially useful for handling timeouts or when you need to confirm successful delivery of airtime/data.
Endpoint: GET /Transactions?requestRef={requestReference}
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
requestRef | String | Yes | The request reference from Step 5 |
Request:
curl 'https://qa.interswitchng.com/quicktellerservice/api/v5/Transactions?requestRef=145300000001' \
-H "Authorization: Bearer <TOKEN>" \
-H "Content-Type: application/json" \
-H "TerminalID: <YOUR_TERMINAL_ID>" \
-X GETResponse:
{
"billPayment": {
"biller": "MTN",
"customerId1": "234805673157",
"customerId2": null,
"paymentTypeName": "Airtime",
"paymentTypeCode": "10903",
"billerId": "109"
},
"amount": "100000",
"currencyCode": "566",
"customer": "234805673157",
"customerEmail": "[email protected]",
"customerMobile": "234805673157",
"paymentDate": "01/02/2023 18:04:53",
"requestReference": "145300000001",
"serviceCode": "10903",
"serviceName": "MTN Airtime",
"serviceProviderId": "109",
"status": "Completed",
"surcharge": "0",
"transactionRef": "PBL|Web|3PBL0001|MTNVTU1|010223180453|4WNYQJ3NDB",
"transactionResponseCode": "90000",
"transactionSet": "BillPayment"
}Status Values:
| Status | Description |
|---|---|
Completed | Recharge successful |
Pending | Recharge is processing |
Failed | Recharge failed |
Reversed | Transaction was reversed |
Airtime vs Data Bundle Recharge
Airtime Recharge (Any Amount)
Characteristics:
- AmountType: 0 (Any Amount)
- Amount Range: ₦50 to ₦10,000 (network dependent)
- Skip Step 3 (no payment items needed)
- Use biller ProductCode directly
Example:
{
"paymentCode": "628051043",
"customerId": "234805673157",
"amount": "100000" // ₦1,000
}Data Bundle Recharge
Characteristics:
- AmountType: 2 (Fixed Amount)
- Specific packages only
- Required Step 3 (get payment items)
- Use PaymentCode from payment item
Example:
{
"paymentCode": "10903", // From Step 3
"customerId": "234805673157",
"amount": "100000" // Fixed amount for 1.5GB
}Telco-Specific Details
MTN Nigeria
| Field | Value |
|---|---|
| Biller ID | 109 |
| Short Name | MTNVTU1 |
| Type | MO (Mobile Operator) |
| AmountType | 2 (Fixed for data), varies for airtime |
| Network ID | 628051043 |
| Product Code | 628051043 |
| Customer Field | Phone Number |
| Min Amount | ₦50 |
| Max Amount | ₦10,000 |
Test Number: 234805673157
Test Payment Code: 10903
Airtel Nigeria
| Field | Value |
|---|---|
| Biller ID | 687 (Data), 120 (Airtime) |
| Short Name | Airtel, ZainPIN |
| Type | MO/MP |
| Network ID | 6280510425 |
| Product Code | 6280510425 |
| Customer Field | Phone Number |
Glo Nigeria
| Field | Value |
|---|---|
| Biller ID | 402 |
| Short Name | GLOQCK |
| Type | MO |
| Network ID | 628051045 |
| Product Code | 628051045 |
| Customer Field | Mobile number |
9mobile (Etisalat)
| Field | Value |
|---|---|
| Biller ID | 120 |
| Short Name | ETILAT |
| Type | MO |
| Network ID | 6280510425 |
| Product Code | 6280510490 |
| Customer Field | Phone No |
Field Reference
Category Fields
| Field | Type | Description |
|---|---|---|
Id | Integer | Category ID (4 for Mobile/Recharge) |
Name | String | Category name |
Description | String | Category description |
Billers | Array | List of billers (empty in categories endpoint) |
Biller Fields
| Field | Type | Description |
|---|---|---|
Id | Integer | Unique biller ID |
Name | String | Biller/telco name |
ShortName | String | Abbreviation |
Narration | String | Service description |
CustomerField1 | String | Phone number input label |
CurrencyCode | String | 566 = NGN |
CurrencySymbol | String | NGN |
AmountType | Integer | 0=Any, 2=Fixed |
NetworkId | String | Network identifier |
ProductCode | String | Product code |
Type | String | MO=Airtime, MP=Data |
Payment Item Fields
| Field | Type | Description |
|---|---|---|
PaymentCode | String | Required for recharge |
Amount | String | Amount in kobo |
Name | String | Package name |
IsAmountFixed | Boolean | If amount can be changed |
BillerId | String | Associated biller ID |
Transaction Request Fields
| Field | Type | Required | Description |
|---|---|---|---|
TerminalId | String | Yes | Your terminal ID |
paymentCode | String | Yes | Payment code |
customerId | String | Yes | Phone number |
customerMobile | String | Yes | Phone number (confirmation) |
customerEmail | String | No | Email for receipt |
amount | String | Yes | Amount in kobo |
requestReference | String | Yes | Unique reference |
Response Codes
Success Codes
| Code | Description |
|---|---|
90000 | Transaction successful |
90000 | Validation successful |
Error Codes
| Code | Description | Action |
|---|---|---|
90001 | Invalid customer/phone number | Check phone number format |
90002 | Customer not found | Verify phone number is active |
90003 | Invalid amount | Check amount is within limits |
90004 | Insufficient funds | Check virtual card balance |
90005 | Duplicate transaction | Use unique request reference |
90006 | Service unavailable | Retry after some time |
90007 | Invalid payment code | Verify payment code |
90008 | Validation failed | Check all fields |
90009 | Network error | Telco network issue, retry |
90010 | Timeout | Query transaction status |
Response Code Grouping
| Grouping | Description |
|---|---|
SUCCESSFUL | Request processed successfully |
FAILED | Request failed |
PENDING | Request is being processed |
Test Data
Test Credentials
| Field | Value |
|---|---|
| Terminal ID | 3PBL0001 |
| Request Reference Prefix | 1453 |
| Initiating Entity Code | PBL |
Test Virtual Card
| Field | Value |
|---|---|
| Card Number | 6280511000000095 |
| Expiry Date | 12/2026 |
| CVV | 000 |
| PIN | 0000 |
Test Phone Numbers
| Telco | Test Number | Payment Code | Category |
|---|---|---|---|
| MTN | 234805673157 | 10903 | Mobile/Recharge (4) |
| Airtel | 234805673157 | 10903 | Mobile/Recharge (4) |
| Glo | 234805673157 | 10903 | Mobile/Recharge (4) |
| 9mobile | 234805673157 | 10903 | Mobile/Recharge (4) |
Test Scenarios
Scenario 1: Successful MTN Airtime Recharge
Payment Code: 10903
Phone Number: 234805673157
Amount: 100000 (₦1,000)
Expected: Success (90000)
Expected: Phone credited within 5-10 seconds
Scenario 2: Invalid Phone Number
Payment Code: 10903
Phone Number: 234000000000
Amount: 100000
Expected: Validation failed (90001)
Scenario 3: Amount Below Minimum
Payment Code: 10903
Phone Number: 234805673157
Amount: 1000 (₦10 - too low)
Expected: Invalid amount (90003)
Scenario 4: Duplicate Transaction
Payment Code: 10903
Phone Number: 234805673157
Amount: 100000
Request Reference: 145300000001 (same as previous)
Expected: Duplicate transaction (90005)
Implementation Examples
Example 1: Complete MTN Airtime Recharge
async function rechargeMTNAirtime(phoneNumber, amountInNaira) {
// Step 1: Get categories (cached usually)
// Step 2: Get MTN biller
const billers = await fetchBillersByCategory(4);
const mtn = billers.find(b => b.Name.includes("MTN"));
// Step 4: Validate phone number (optional but recommended)
const validation = await validateCustomer({
paymentCode: mtn.ProductCode,
customerId: phoneNumber
});
if (validation.ResponseCode !== "90000") {
throw new Error("Invalid phone number");
}
// Step 5: Process recharge
const amountInKobo = amountInNaira * 100;
const reference = `1453${Date.now()}`;
const transaction = await processRecharge({
TerminalId: "3PBL0001",
paymentCode: mtn.ProductCode,
customerId: phoneNumber,
customerMobile: phoneNumber,
customerEmail: "[email protected]",
amount: amountInKobo.toString(),
requestReference: reference
});
return {
success: transaction.ResponseCode === "90000",
transactionRef: transaction.TransactionRef,
amount: amountInNaira,
phoneNumber: phoneNumber
};
}
// Usage
rechargeMTNAirtime("234805673157", 1000)
.then(result => console.log(result))
.catch(error => console.error(error));Example 2: Airtel Data Bundle Purchase
async function purchaseAirtelDataBundle(phoneNumber, bundleId) {
// Step 2: Get Airtel Data biller
const billers = await fetchBillersByCategory(4);
const airtelData = billers.find(b =>
b.Name.includes("Airtel") && b.Name.includes("Data")
);
// Step 3: Get available data bundles
const bundles = await fetchPaymentItems(airtelData.Id);
const selectedBundle = bundles.find(b => b.Id === bundleId);
if (!selectedBundle) {
throw new Error("Invalid bundle ID");
}
// Step 5: Process purchase
const reference = `1453${Date.now()}`;
const transaction = await processRecharge({
TerminalId: "3PBL0001",
paymentCode: selectedBundle.PaymentCode,
customerId: phoneNumber,
customerMobile: phoneNumber,
amount: selectedBundle.Amount, // Fixed amount
requestReference: reference
});
return {
success: transaction.ResponseCode === "90000",
bundleName: selectedBundle.Name,
transactionRef: transaction.TransactionRef
};
}
// Usage
purchaseAirtelDataBundle("234805673157", "02")
.then(result => console.log(result))
.catch(error => console.error(error));Example 3: Multiple Network Support
const TELCO_CONFIG = {
mtn: {
billerId: 109,
productCode: "628051043",
name: "MTN"
},
airtel: {
billerId: 120,
productCode: "6280510425",
name: "Airtel"
},
glo: {
billerId: 402,
productCode: "628051045",
name: "Glo"
},
etisalat: {
billerId: 120,
productCode: "6280510490",
name: "9mobile"
}
};
async function rechargeAnyNetwork(network, phoneNumber, amountInNaira) {
const config = TELCO_CONFIG[network.toLowerCase()];
if (!config) {
throw new Error("Unsupported network");
}
const amountInKobo = amountInNaira * 100;
const reference = `1453${Date.now()}`;
const transaction = await processRecharge({
TerminalId: "3PBL0001",
paymentCode: config.productCode,
customerId: phoneNumber,
customerMobile: phoneNumber,
amount: amountInKobo.toString(),
requestReference: reference
});
return {
network: config.name,
success: transaction.ResponseCode === "90000",
transactionRef: transaction.TransactionRef,
amount: amountInNaira,
phoneNumber: phoneNumber
};
}
// Usage
rechargeAnyNetwork("mtn", "234805673157", 500)
.then(result => console.log(result));Best Practices
1. Phone Number Handling
- ✅ Always use full international format:
234+ 10 digits - ✅ Remove leading zero if present:
0805...→234805... - ✅ Validate phone number length (13 digits with 234 prefix)
- ✅ Strip non-numeric characters before sending
2. Amount Handling
- ✅ Convert Naira to Kobo (multiply by 100)
- ✅ Respect minimum amount limits (₦50 for most networks)
- ✅ Respect maximum amount limits (₦10,000 for most networks)
- ✅ For data bundles, use the exact amount from payment items
3. Request Reference
- ✅ Generate unique reference for each transaction
- ✅ Use consistent prefix (e.g.,
1453for test, your code for prod) - ✅ Include timestamp or sequence number
- ✅ Store reference for reconciliation
4. Error Handling
- ✅ Implement retry logic for network errors
- ✅ Query transaction status on timeouts
- ✅ Show user-friendly error messages
- ✅ Log all errors for debugging
5. Security
- ✅ Never expose OAuth credentials in frontend
- ✅ Use HTTPS for all API calls
- ✅ Validate phone numbers before submission
- ✅ Implement rate limiting
6. User Experience
- ✅ Show loading state during recharge
- ✅ Display confirmation before processing
- ✅ Show success message with transaction reference
- ✅ Provide option to retry on failure
- ✅ Send SMS/email receipt to customer
Troubleshooting
Common Issues
Issue 1: Transaction times out
- Cause: Network latency or telco delay
- Solution: Query transaction status after 30 seconds
- Action: Use Step 6 to check status
Issue 2: Phone not credited
- Cause: Invalid phone number or network issue
- Solution: Check transaction status
- Action: If failed, retry with correct number
Issue 3: Insufficient funds error
- Cause: Virtual card balance too low
- Solution: Fund your virtual card
- Action: Contact Interswitch support
Issue 4: Duplicate transaction error
- Cause: Reusing request reference
- Solution: Generate new unique reference
- Action: Use timestamp or UUID
Issue 5: Invalid payment code
- Cause: Wrong product code for telco
- Solution: Verify payment code from Step 2 or 3
- Action: Check biller configuration
Debugging Checklist
- Is the token valid and not expired?
- Is TerminalId correct?
- Is phone number in correct format (234...)?
- Is amount in kobo (not Naira)?
- Is requestReference unique?
- Is paymentCode correct for the telco?
- Is the virtual card funded?
API Summary
| Endpoint | Method | Description |
|---|---|---|
/services/categories | GET | Get all categories |
/services?categoryId=4 | GET | Get telcos (Mobile/Recharge) |
/services/options?serviceid={id} | GET | Get data bundles (optional) |
/Transactions/validatecustomers | POST | Validate phone number (optional) |
/Transactions | POST | Process recharge |
/Transactions?requestRef={ref} | GET | Query transaction status |
Support
For technical support:
- Email: [email protected]
- Documentation: https://docs.interswitchgroup.com
Document Version: 2.0
Last Updated: 2026-05-29
API Version: v5
Updated 7 days ago