Airtime Recharge (Virtual Top up)

Table of Contents

  1. Overview
  2. Supported Services
  3. Getting Started
  4. Authentication
  5. Integration Flow
  6. Step-by-Step Implementation
  7. Airtime vs Data Bundle Recharge
  8. Telco-Specific Details
  9. Field Reference
  10. Response Codes
  11. Test Data
  12. Implementation Examples
  13. Best Practices
  14. 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:

  1. Customer requests airtime/data recharge on your app
  2. You charge customer's wallet/card
  3. API submits recharge request to telco
  4. Telco credits customer's phone
  5. Your virtual card is debited
  6. 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

EnvironmentBase URL
QA/Testinghttps://qa.interswitchng.com/quicktellerservice/api/v5
Productionhttps://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:

HeaderValueDescription
AuthorizationBasic <credentials>Base64 encoded client_id:client_secret
Content-Typeapplication/x-www-form-urlencodedRequest 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 GET

Response:

{
    "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:

ParameterTypeRequiredDescription
categoryIdIntegerYesUse 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 GET

Response:

{
    "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:

FieldDescription
IdUnique biller ID (e.g., 109 for MTN)
NameTelco name
ShortNameAbbreviation (e.g., MTNVTU1)
CustomerField1Input label for phone number
AmountType0=Any Amount, 2=Fixed (see Amount Types)
NetworkIdNetwork identifier
ProductCodeProduct code for transactions
TypeMO=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:

ParameterTypeRequiredDescription
serviceidIntegerYesThe 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 GET

Response (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:

FieldDescription
PaymentCodeCritical - Use this for recharge requests
AmountAmount in kobo (e.g., 10000 = ₦100)
IsAmountFixedIf true, amount cannot be changed
NameHuman-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 POST

Request Body:

FieldTypeRequiredDescription
customersArrayYesArray of customer objects
customers[].PaymentCodeStringYesPayment code from Step 2 or 3
customers[].CustomerIdStringYesPhone number to validate
TerminalIdStringYesYour 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 number
  • ResponseCode: 90001 or 90002 = 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 POST

Request Body Fields:

FieldTypeRequiredDescription
TerminalIdStringYesYour terminal ID
paymentCodeStringYesPayment code from Step 2 or 3
customerIdStringYesPhone number to recharge
customerMobileStringYesCustomer's mobile number (same as customerId)
customerEmailStringNoCustomer's email for receipts
amountStringYesAmount in kobo (e.g., "100000" for ₦1,000)
requestReferenceStringYesUnique 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:

FieldDescription
TransactionRefUnique transaction reference (save this!)
ApprovedAmountAmount processed in kobo
AdditionalInfoTransaction details
ResponseCode90000 = Success
ResponseDescriptionHuman-readable status

Transaction Flow:

  1. Submit recharge request
  2. API validates request
  3. Telco processes recharge
  4. Phone is credited (usually within 5-10 seconds)
  5. Your virtual card is debited
  6. 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:

ParameterTypeRequiredDescription
requestRefStringYesThe 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 GET

Response:

{
    "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:

StatusDescription
CompletedRecharge successful
PendingRecharge is processing
FailedRecharge failed
ReversedTransaction 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

FieldValue
Biller ID109
Short NameMTNVTU1
TypeMO (Mobile Operator)
AmountType2 (Fixed for data), varies for airtime
Network ID628051043
Product Code628051043
Customer FieldPhone Number
Min Amount₦50
Max Amount₦10,000

Test Number: 234805673157
Test Payment Code: 10903

Airtel Nigeria

FieldValue
Biller ID687 (Data), 120 (Airtime)
Short NameAirtel, ZainPIN
TypeMO/MP
Network ID6280510425
Product Code6280510425
Customer FieldPhone Number

Glo Nigeria

FieldValue
Biller ID402
Short NameGLOQCK
TypeMO
Network ID628051045
Product Code628051045
Customer FieldMobile number

9mobile (Etisalat)

FieldValue
Biller ID120
Short NameETILAT
TypeMO
Network ID6280510425
Product Code6280510490
Customer FieldPhone No

Field Reference

Category Fields

FieldTypeDescription
IdIntegerCategory ID (4 for Mobile/Recharge)
NameStringCategory name
DescriptionStringCategory description
BillersArrayList of billers (empty in categories endpoint)

Biller Fields

FieldTypeDescription
IdIntegerUnique biller ID
NameStringBiller/telco name
ShortNameStringAbbreviation
NarrationStringService description
CustomerField1StringPhone number input label
CurrencyCodeString566 = NGN
CurrencySymbolStringNGN
AmountTypeInteger0=Any, 2=Fixed
NetworkIdStringNetwork identifier
ProductCodeStringProduct code
TypeStringMO=Airtime, MP=Data

Payment Item Fields

FieldTypeDescription
PaymentCodeStringRequired for recharge
AmountStringAmount in kobo
NameStringPackage name
IsAmountFixedBooleanIf amount can be changed
BillerIdStringAssociated biller ID

Transaction Request Fields

FieldTypeRequiredDescription
TerminalIdStringYesYour terminal ID
paymentCodeStringYesPayment code
customerIdStringYesPhone number
customerMobileStringYesPhone number (confirmation)
customerEmailStringNoEmail for receipt
amountStringYesAmount in kobo
requestReferenceStringYesUnique reference

Response Codes

Success Codes

CodeDescription
90000Transaction successful
90000Validation successful

Error Codes

CodeDescriptionAction
90001Invalid customer/phone numberCheck phone number format
90002Customer not foundVerify phone number is active
90003Invalid amountCheck amount is within limits
90004Insufficient fundsCheck virtual card balance
90005Duplicate transactionUse unique request reference
90006Service unavailableRetry after some time
90007Invalid payment codeVerify payment code
90008Validation failedCheck all fields
90009Network errorTelco network issue, retry
90010TimeoutQuery transaction status

Response Code Grouping

GroupingDescription
SUCCESSFULRequest processed successfully
FAILEDRequest failed
PENDINGRequest is being processed

Test Data

Test Credentials

FieldValue
Terminal ID3PBL0001
Request Reference Prefix1453
Initiating Entity CodePBL

Test Virtual Card

FieldValue
Card Number6280511000000095
Expiry Date12/2026
CVV000
PIN0000

Test Phone Numbers

TelcoTest NumberPayment CodeCategory
MTN23480567315710903Mobile/Recharge (4)
Airtel23480567315710903Mobile/Recharge (4)
Glo23480567315710903Mobile/Recharge (4)
9mobile23480567315710903Mobile/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., 1453 for 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

EndpointMethodDescription
/services/categoriesGETGet all categories
/services?categoryId=4GETGet telcos (Mobile/Recharge)
/services/options?serviceid={id}GETGet data bundles (optional)
/Transactions/validatecustomersPOSTValidate phone number (optional)
/TransactionsPOSTProcess recharge
/Transactions?requestRef={ref}GETQuery transaction status

Support

For technical support:


Document Version: 2.0
Last Updated: 2026-05-29
API Version: v5