KDA API Logo
API Docs
Services

Data

Purchase mobile data bundles 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 data vending across all four major Nigerian networks.

MTN

MTN

Provider ID: kds-data-mtn

Airtel

Airtel

Provider ID: kds-data-airtel

GLO

GLO

Provider ID: kds-data-glo

9mobile

9mobile

Provider ID: kds-data-9mobile

Supported Data Types

Across these networks, we support a wide variety of data classes. You can filter for specific classes using the type query parameter when fetching plans:

  • SME: Small and Medium Enterprise data (usually the cheapest).
  • Gifting (Direct): Standard network data gifting.
  • Corporate Gifting (CG): Bulk corporate data allocation.
  • Gifting Promo (GP): Promo data gifting.
  • and more...

Fetch Plans

curl -X GET https://kda-turbo-web.vercel.app/api/services/data/plans \
  -H "Authorization: Bearer kds_test_YOUR_API_KEY"
{
  "success": true,
  "count": 448,
  "data": [
    {
      "type": "SME",
      "plans": [
        {
          "id": "kds-data-mtn-sme-v1-003",
          "label": "2GB",
          "validity": "30days",
          "salePrice": "899",
          "isNightPlan": false,
          "isSocialPlan": false,
          "provider": "MTN"
        }
      ]
    },
    {
      "type": "CG",
      "plans": [...]
    }
  ]
}

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

Fetch a single plan directly by its id:

curl -X GET "https://kda-turbo-web.vercel.app/api/services/data/plans?id=kds-data-mtn-sme-v1-003" \
  -H "Authorization: Bearer kds_test_YOUR_API_KEY"

You can also filter plans by category using the type query parameter:

curl -X GET "https://kda-turbo-web.vercel.app/api/services/data/plans?type=SME" \
  -H "Authorization: Bearer kds_test_YOUR_API_KEY"

Anatomy of a Data Plan

When you fetch plans, the response groups them by their data type. Each group contains a plans array with individual plan objects:


{
  "type": "SME",
  "plans": [
    {
      "id": "kds-data-mtn-sme-v1-003",
      "label": "2GB",
      "validity": "30days",
      "salePrice": "899",
      "isNightPlan": false,
      "isSocialPlan": false,
      "provider": "MTN"
    }
  ]
}

Each plan object within a group:

Prop

Type

Purchase Flow

Identify Network from Phone Number

Before purchasing, validate the phone number client-side to confirm which network it belongs to. This helps prevent sending data 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/data \
  -H "Authorization: Bearer kds_test_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "planId": "kds-data-mtn-sme-v1-003",
    "number": "08012345678",
    "idempotencyKey": "550e8400-e29b-41d4-a716-446655440000",
    "isPorted": false
  }'
const response = await fetch("https://kda-turbo-web.vercel.app/api/services/data", {
  method: "POST",
  headers: {
    "Authorization": "Bearer kds_test_YOUR_API_KEY",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    planId: "kds-data-mtn-sme-v1-003",
    number: "08012345678",
    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/data",
    headers={
        "Authorization": "Bearer kds_test_YOUR_API_KEY",
        "Content-Type": "application/json",
    },
    json={
        "planId": "kds-data-mtn-sme-v1-003",
        "number": "08012345678",
        "idempotencyKey": str(uuid.uuid4()),
        "isPorted": False,
    },
)

data = response.json()
<?php

$ch = curl_init("https://kda-turbo-web.vercel.app/api/services/data");
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-data-mtn-sme-v1-003",
        "number" => "08012345678",
        "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": "Data Purchase purchase successful!",
  "transactionId": "KDS-DAT-YRGH1BZA-SN",
  "data": {
    "amount": 899,
    "label": "2GB",
    "provider": "MTN",
    "number": "08012345678",
    "status": "SUCCESS",
    "description": "Data Purchase purchase successful!",
    "transactionId": "KDS-DAT-YRGH1BZA-SN",
    "createdAt": "2026-06-17T10:08:23.538Z",
    "validity": "30days",
    "category": "SME",
    "type": "DATA",
    "idempotencyKey": "550e8400-e29b-41d4-a716-446655440000"
  }
}

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.