KDA API Logo
API Docs
Services

Airtime

Purchase airtime for any Nigerian network.

Endpoints

All API requests must be made over HTTPS to: https://kda-turbo-web.vercel.app

Supported Providers

KDA currently supports instant airtime vending across all four major Nigerian networks via VTU and Share & Sell channels.

MTN

MTN

Provider ID: kds-airtime-mtn

Airtel

Airtel

Provider ID: kds-airtime-airtel

GLO

GLO

Provider ID: kds-airtime-glo

9mobile

9mobile

Provider ID: kds-airtime-9mobile

Supported Channels

  • VTU → Virtual Top-Up: standard airtime vending at a discount.
  • Share & Sell → Transfer airtime credit from one line to another.

Fetch Plans

curl -X GET https://kda-turbo-web.vercel.app/api/services/airtime/plans \
  -H "Authorization: Bearer kds_test_YOUR_API_KEY"
{
  "success": true,
  "count": 12,
  "data": [
    {
      "id": "kds-airtime-mtn-vtu-v2",
      "name": "MTN",
      "airtimeType": "VTU",
      "salePercentage": "3"
    },
    {
      "id": "kds-airtime-glo-vtu-v1",
      "name": "GLO",
      "airtimeType": "VTU",
      "salePercentage": "4"
    }
  ]
}

Fetching without any filter returns all plans. Pass ?id=<planId> to fetch a single plan.

Fetch a single provider by its id:

curl -X GET "https://kda-turbo-web.vercel.app/api/services/airtime/plans?id=kds-airtime-mtn-vtu-v2" \
  -H "Authorization: Bearer kds_test_YOUR_API_KEY"

The salePercentage indicates the discount applied to the face value. For example, "3" means purchasing ₦100 airtime will actually only deduct ₦97 from your wallet.

Anatomy of an Airtime Plan

Each plan object represents a provider channel combination:

{
  "id": "kds-airtime-mtn-vtu-v2",
  "name": "MTN",
  "airtimeType": "VTU",
  "salePercentage": "1.5"
}

Prop

Type

Purchase Flow

Validate Phone Number

Before purchasing, validate the phone number client-side to confirm which network it belongs to. This helps prevent sending airtime to the wrong provider.

See Network Prefixes for the full list of prefixes and a client-side validation snippet.

Purchase Request

Request Body

Prop

Type

Example

curl -X POST https://kda-turbo-web.vercel.app/api/services/airtime \
  -H "Authorization: Bearer kds_test_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "planId": "kds-airtime-mtn-vtu-v2",
    "number": "08012345678",
    "amount": 100,
    "idempotencyKey": "681227cc-2638-49fe-bbe3-d2500cf54767",
    "isPorted": false
  }'
const response = await fetch("https://kda-turbo-web.vercel.app/api/services/airtime", {
  method: "POST",
  headers: {
    "Authorization": "Bearer kds_test_YOUR_API_KEY",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    planId: "kds-airtime-mtn-vtu-v2",
    number: "08012345678",
    amount: 100,
    idempotencyKey: crypto.randomUUID(),
    isPorted: false
  })
});

const data = await response.json();
import requests
import uuid

response = requests.post(
    "https://kda-turbo-web.vercel.app/api/services/airtime",
    headers={
        "Authorization": "Bearer kds_test_YOUR_API_KEY",
        "Content-Type": "application/json",
    },
    json={
        "planId": "kds-airtime-mtn-vtu-v2",
        "number": "08012345678",
        "amount": 100,
        "idempotencyKey": str(uuid.uuid4()),
        "isPorted": False,
    },
)

data = response.json()
<?php

$ch = curl_init("https://kda-turbo-web.vercel.app/api/services/airtime");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer kds_test_YOUR_API_KEY",
        "Content-Type: application/json",
    ],
    CURLOPT_POSTFIELDS => json_encode([
        "planId" => "kds-airtime-mtn-vtu-v2",
        "number" => "08012345678",
        "amount" => 100,
        "idempotencyKey" => bin2hex(random_bytes(16)),
        "isPorted" => false,
    ]),
    CURLOPT_RETURNTRANSFER => true,
]);

$response = curl_exec($ch);
curl_close($ch);

$data = json_decode($response, true);
print_r($data);

Success Response

{
  "success": true,
  "message": "Airtime Purchase purchase successful!",
  "transactionId": "KDS-AIR-HCKXV8TF-SN",
  "data": {
    "amount": 100,
    "planId": "kds-airtime-mtn-vtu-v1",
    "provider": "MTN",
    "number": "08101886979",
    "status": "SUCCESS",
    "description": "Airtime Purchase purchase successful!",
    "transactionId": "KDS-AIR-HCKXV8TF-SN",
    "createdAt": "2026-06-17T10:54:51.202Z",
    "discountRate": "4",
    "type": "AIRTIME",
    "idempotencyKey": "fbb3ae62-72c9-4383-afd3-85b9fa136119"
  }
}

Best Practices & Next Steps

Safe Retries with Idempotency: Always attach a unique idempotencyKey (UUID v4) to your request body. If your connection drops or times out, you can safely resubmit the exact same request without risk of debiting your wallet twice.

Handling Pending Statuses: While most purchases complete in under 3 seconds, vendor delays can occasionally leave a transaction in a PENDING state. Do not retry with a new idempotency key. Instead, listen for real-time status updates via Webhooks.