NEW APP AVAILABLE FOR DOWNLOAD NOW

Get it on Google PlayDownload on the App Store

Data Plans

Purchase mobile data bundles for all major networks

Buy daily, weekly, and monthly data bundles for MTN, Airtel, Glo, and 9mobile.

Supported Networks

NetworkCode
MTN NigeriaMTN
Airtel NigeriaAIRTEL
GlobacomGLO
9mobile9MOBILE

Bundle Types

Each plan carries a free-form bundle_type tag describing the plan family (for example SME, NIGHT, SOCIAL, SG GIFTING). It can be null when a plan is not categorised. Use the duration field for validity. Filter the products endpoint by bundle_type to narrow results.

Purchase Flow

Data plan purchases are straightforward - no verification required.

  1. List products - Get available data plans
  2. Make purchase - Send the purchase request

Step 1: List Products

Filter by network and/or bundle type:

bash
curl -X GET \
  -H "Authorization: Bearer sk_live_your_secret_key" \
  "https://my.rizpay.app/api/partners/v1/products/dataplans?network=MTN&bundle_type=monthly"

Response:

json
{
  "status": { "code": 200, "message": "Success" },
  "data": [
    {
      "id": "prd_2270",
      "type": "data_plan",
      "attributes": {
        "display_name": "MTN 75MB / 1 Day (SG GIFTING)",
        "network": "MTN",
        "bundle_size": "75MB",
        "duration": "1 Day",
        "bundle_type": "SG GIFTING",
        "price": {
          "amount": "77.60",
          "currency": "NGN",
          "basis": "fixed"
        }
      }
    },
    {
      "id": "prd_2271",
      "type": "data_plan",
      "attributes": {
        "display_name": "MTN 2GB / 30 Days",
        "network": "MTN",
        "bundle_size": "2GB",
        "duration": "30 Days",
        "bundle_type": null,
        "price": {
          "amount": "1000.00",
          "currency": "NGN",
          "basis": "fixed"
        }
      }
    }
  ],
  "pagination": {
    "page": 1,
    "per_page": 20,
    "total_pages": 3,
    "total_count": 45
  }
}

Product ids are numeric with a prd_ prefix (e.g. prd_2270). Use the id from your own response in the purchase request. bundle_type may be null when the plan is not categorised.

The price block

Data plans are catalog-priced - RizPay returns a single fixed amount per plan. The amount is your cost, not the retail price: it is what RizPay bills you, and you set what your customer pays by adding your own markup. A figure in the plan name is a label, not the price, so don't parse the name yourself - when we can confidently read one, we return it as reference_price. See Pricing your products for worked examples.

FieldTypeNotes
amountstringWhat RizPay will bill you per unit of this plan
reference_pricestringOptional best-effort guide value; omitted when unknown
currencystringAlways NGN
basisstringfixed

Step 2: Make Purchase

bash
curl -X POST \
  -H "Authorization: Bearer sk_live_your_secret_key" \
  -H "Content-Type: application/json" \
  -d '{
    "product_id": "prd_2271",
    "phone_number": "08012345678",
    "network": "MTN",
    "external_reference": "1736234400C3D4E5"
  }' \
  https://my.rizpay.app/api/partners/v1/purchases

Note: For data plans, the amount is fixed by the plan. You don't need to specify it. Include the network matching the plan you selected.

Response:

json
{
  "status": { "code": 201, "message": "Purchase created successfully" },
  "data": {
    "id": "txn_abc123",
    "type": "transaction",
    "attributes": {
      "amount": "1000.0",
      "currency": "NGN",
      "status": "pending",
      "category": "purchase",
      "description": "Purchase of MTN 2GB - 30 Days",
      "reference": "a26e6eb0cd196076ea2b",
      "external_reference": "1736234400C3D4E5",
      "product_type": "data_plan",
      "phone_number": "08012345678",
      "meter_number": null,
      "price": {
        "product_amount": "1000.00",
        "fee_amount": "0.00",
        "total_debit": "1000.00",
        "currency": "NGN",
        "basis": "fixed"
      },
      "created_at": "2026-05-18T10:30:00+01:00",
      "updated_at": "2026-05-18T10:30:00+01:00"
    }
  }
}

The price breakdown

Same breakdown as airtime. For data plans the basis is fixed because the catalog price is the bill, with no partner-supplied amount.

Check Transaction Status

bash
curl -X GET \
  -H "Authorization: Bearer sk_live_your_secret_key" \
  "https://my.rizpay.app/api/partners/v1/purchases/txn_abc123"

Successful response:

json
{
  "status": { "code": 200, "message": "Purchase details retrieved" },
  "data": {
    "id": "txn_abc123",
    "type": "transaction",
    "attributes": {
      "amount": "1000.0",
      "currency": "NGN",
      "status": "successful",
      "category": "purchase",
      "description": "Purchase of MTN 2GB - 30 Days",
      "reference": "a26e6eb0cd196076ea2b",
      "external_reference": "1736234400C3D4E5",
      "product_type": "data_plan",
      "phone_number": "08012345678",
      "meter_number": null,
      "price": {
        "product_amount": "1000.00",
        "fee_amount": "0.00",
        "total_debit": "1000.00",
        "currency": "NGN",
        "basis": "fixed"
      },
      "created_at": "2026-05-18T10:30:00+01:00",
      "updated_at": "2026-05-18T10:30:02+01:00"
    }
  }
}

The transaction is done when status reaches successful, failed, or reversed. There is no separate completion timestamp: use updated_at.

Complete Example

javascript
// Generate external reference: 10-digit timestamp + 6 alphanumeric
function generateReference() {
  const timestamp = Math.floor(Date.now() / 1000);
  const chars =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  let suffix = "";
  for (let i = 0; i < 6; i++) {
    suffix += chars.charAt(Math.floor(Math.random() * chars.length));
  }
  return `${timestamp}${suffix}`;
}

async function purchaseDataPlan(network, bundleType, bundleSize, phoneNumber) {
  const API_KEY = "sk_live_your_secret_key";
  const BASE_URL = "https://my.rizpay.app/api/partners/v1";

  // Step 1: Find matching data plans
  const params = new URLSearchParams({
    network: network,
    bundle_type: bundleType,
  });

  const productsRes = await fetch(`${BASE_URL}/products/dataplans?${params}`, {
    headers: { Authorization: `Bearer ${API_KEY}` },
  });
  const products = await productsRes.json();

  // Find the plan matching the requested bundle size
  const product = products.data.find(
    (p) => p.attributes.bundle_size === bundleSize
  );
  if (!product) {
    throw new Error(`No ${bundleSize} ${bundleType} plan found for ${network}`);
  }

  // Step 2: Make purchase
  const purchaseRes = await fetch(`${BASE_URL}/purchases`, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      product_id: product.id,
      phone_number: phoneNumber,
      network: product.attributes.network,
      external_reference: generateReference(),
    }),
  });

  return await purchaseRes.json();
}

// Usage
purchaseDataPlan("MTN", "monthly", "2GB", "08012345678")
  .then((result) => console.log(result))
  .catch((error) => console.error(error));

Listing All Plans for a User

Build a plan selector by fetching all plans:

javascript
async function getDataPlans(network) {
  const API_KEY = "sk_live_your_secret_key";
  const BASE_URL = "https://my.rizpay.app/api/partners/v1";

  const response = await fetch(
    `${BASE_URL}/products/dataplans?network=${network}&per_page=100`,
    { headers: { Authorization: `Bearer ${API_KEY}` } }
  );
  const data = await response.json();

  // Group by bundle type. `bundle_type` may be null for uncategorised plans.
  const grouped = {};

  data.data.forEach((plan) => {
    const attrs = plan.attributes;
    const key = attrs.bundle_type || "other";
    (grouped[key] ||= []).push({
      id: plan.id,
      name: `${attrs.bundle_size} - ₦${attrs.price.amount}`,
      size: attrs.bundle_size,
      price: attrs.price.amount,
      duration: attrs.duration,
    });
  });

  return grouped;
}

Popular Plans

MTN

PlanPriceValidity
1GB~50030 days
2GB~1,00030 days
5GB~2,00030 days
10GB~3,50030 days

Airtel

PlanPriceValidity
1GB~50030 days
2GB~1,00030 days
6GB~2,00030 days

Prices may vary. Always check the products endpoint for current pricing.

Transaction States

StatusDescription
pendingProcessing with provider
successfulData plan activated
failedPurchase failed (balance refunded)

Required Scope

Requires the purchase_data scope on your API key.

Next Steps