---
updatedAt: 2026-09-30T12:24:57.000Z
agentTools:
  projectIndex: https://docs.interswitchgroup.com/llms.txt
---

# Airtime Recharge (Virtual Top up)

Quickteller service v5

## Table of Contents

1. [Overview](#overview)
2. [Supported Services](#supported-services)
3. [Getting Started](#getting-started)
4. [Authentication](#authentication)
5. [Integration Flow](#integration-flow)
6. [Step-by-Step Implementation](#step-by-step-implementation)
   * [Step 1: Get Categories](#step-1-get-categories)
   * [Step 2: Get Telcos/Billers](#step-2-get-telcosbillers)
   * [Step 3: Get Payment Items](#step-3-get-payment-items)
   * [Step 4: Process Recharge](#step-4-process-recharge)
   * [Step 5: Query Transaction Status](#step-5-query-transaction-status)
7. [Airtime vs Data Bundle Recharge](#airtime-vs-data-bundle-recharge)
8. [Telco-Specific Details](#telco-specific-details)
9. [Field Reference](#field-reference)
10. [Response Codes](#response-codes)
11. [Test Data](#test-data)
12. [Implementation Examples](#implementation-examples)
13. [Best Practices](#best-practices)
14. [Troubleshooting](#troubleshooting)
15. [API Summary](#api-summary)

***

## 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:** Airtime supports any amount within 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:

<Image src="https://files.readme.io/f02f601-030d561-airtime.jpg" align="center" />

**Process Flow:**

1. Customer requests airtime/data recharge on your app.
2. You identify the telco and payment item to obtain the `PaymentCode`.
3. You submit the recharge request to the API.
4. The telco credits the customer's phone.
5. Your virtual card is debited.
6. You earn commission.

> **Note:** Customer validation is not required for airtime and data recharge.

***

## 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`    |

### Amount Convention

> **All monetary amounts are in the minor unit of the currency (kobo for NGN).**
>
> * `10000` = ₦100.00
> * `100000` = ₦1,000.00
> * Multiply Naira by 100 to get kobo.

### Authentication Endpoint

```
POST https://passport-sandbox.interswitchng.com/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:**

```bash
curl --location 'https://passport-sandbox.interswitchng.com/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:**

```json
{
    "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
    │
    ▼
Step 4: Process Recharge
    │
    ▼
Step 5: Query Transaction Status
```

> **Note:** Customer validation is not required for airtime and data recharge.

***

## Step-by-Step Implementation

### Step 1: Get Categories

**Purpose:** Retrieve all available service categories to identify where airtime and data 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:**

```bash
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:**

```json
{
    "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**.

***

### 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:**

```bash
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:**

```json
{
    "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 (internal)            |
| `ProductCode`    | Product code (internal)                  |
| `Type`           | MO=Mobile Operator, MP=Mobile Product    |

> **Important:** `NetworkId` and `ProductCode` are internal fields. Use the `PaymentCode` obtained from the payment items endpoint for recharge requests.

***

### Step 3: Get Payment Items

**Purpose:** Retrieve specific data bundle options or fixed airtime denominations, and obtain the `PaymentCode` required for recharge.

**Description:** This step returns available packages with specific amounts and payment codes. It is **required** for data bundles and fixed-amount airtime. For any-amount airtime (`AmountType` 0), a payment item may still return the payment code to use.

**When to Use:**

* **Data Bundles:** Required — returns specific data plans.
* **Fixed Airtime:** Required — returns specific denominations.
* **Any-Amount Airtime:** Use to retrieve the applicable payment code.

**Endpoint:** `GET /services/options?serviceid={billerid}`

**Parameters:**

| Parameter   | Type    | Required | Description               |
| ----------- | ------- | -------- | ------------------------- |
| `serviceid` | Integer | Yes      | The biller ID from Step 2 |

**Request:**

```bash
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):**

```json
{
    "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: 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:**

```bash
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": "customer@example.com",
    "amount": "100000",
    "requestReference": "145300000001"
}' \
-X POST
```

**Request Body Fields:**

| Field              | Type   | Required | Description                                    |
| ------------------ | ------ | -------- | ---------------------------------------------- |
| `TerminalId`       | String | Yes      | Your terminal ID                               |
| `paymentCode`      | String | Yes      | Payment code from Step 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:**

```json
{
    "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:**

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 5: 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 4 |

**Request:**

```bash
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:**

```json
{
    "BillPayment": {
        "biller": "MTN",
        "customerId1": "234805673157",
        "customerId2": null,
        "paymentTypeName": "Airtime",
        "paymentTypeCode": "10903",
        "billerId": "109"
    },
    "amount": "100000",
    "currencyCode": "566",
    "customer": "234805673157",
    "customerEmail": "customer@example.com",
    "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)
* Use the payment code returned by the payment items endpoint for the selected telco.

**Example:**

```json
{
    "paymentCode": "10903",
    "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:**

```json
{
    "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 (internal)         |
| `ProductCode`    | String  | Product code (internal)               |
| `Type`           | String  | MO=Mobile Operator, MP=Mobile Product |

> **Important:** `ProductCode` and `NetworkId` are internal fields. Do not use them as `PaymentCode` in recharge requests.

### 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

For a complete list of response codes, their meanings, and resolutions, see the [Response Codes documentation](./Response_Codes_Documentation.md).

Common response codes for airtime and data recharge:

| Code    | Description                   | Action                        |
| ------- | ----------------------------- | ----------------------------- |
| `90000` | Transaction successful        | Recharge successful           |
| `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: 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

```javascript
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 3: Get payment items and select the airtime payment code
    const items = await fetchPaymentItems(mtn.Id);
    const airtimeItem = items.find(i => i.Name.includes("Airtime") || i.AmountType === 0);

    // Step 4: Process recharge
    const amountInKobo = amountInNaira * 100;
    const reference = `1453${Date.now()}`;

    const transaction = await processRecharge({
        TerminalId: "3PBL0001",
        paymentCode: airtimeItem.PaymentCode,
        customerId: phoneNumber,
        customerMobile: phoneNumber,
        customerEmail: "customer@example.com",
        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

```javascript
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 4: 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));
```

***

## 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 5 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 payment code for telco or product
* **Solution:** Verify payment code from Step 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/product?
* [ ] 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 payment items            |
| `/Transactions`                    | POST   | Process recharge             |
| `/Transactions?requestRef={ref}`   | GET    | Query transaction status     |

***

## Support

For technical support:

* **Email:** <support@interswitchng.com>
* **Documentation:** <https://docs.interswitchgroup.com>

***

**Document Version:** 2.0\
**Last Updated:** 2026-09-29\
**API Version:** v5