Call any endpoint with your API keys — no Postman required. Open API playground

Airtime & Data API

Buy MTN, Airtel, and Lyca Uganda airtime and data bundles using your MarzPay Demo wallet. No platform service charge — you pay the exact bundle or airtime amount.

API Overview

Base URL

https://demo-wallet.wearemarz.com/api/v1

Authentication

API Key (Basic Auth)

Market

Uganda (UGX) — MTN, Airtel, Lyca
  • Subscribe to Airtime & Data in the service marketplace before using the API.
  • Purchases debit your UG wallet upfront for the exact airtime or bundle amount (0% MarzPay charge), like disbursements. Failed purchases are refunded automatically.
  • No merchant webhooks — MarzPay does not send outbound callbacks for airtime/data purchases. Poll GET /airtime-data/{reference} for pending Airtel data bundles.
  • MTN — airtime and data bundles. Airtel — airtime and data bundles. Lyca — airtime only (no data bundles).
  • Airtel data bundles may return pending until delivery is confirmed. Poll until completed or failed.
  • POST requests require your IP to be on the API whitelist.

Processing & delivery confirmation

Your wallet is debited immediately when you submit a purchase — the same pattern as disbursements. If the provider later rejects or fails the delivery, MarzPay refunds the amount automatically.

MTN purchases and Airtel/Lyca airtime usually complete synchronously — the HTTP response contains the final completed or failed outcome (refunded if failed).

Airtel data bundles may confirm delivery asynchronously. Your wallet is debited when you submit. MarzPay returns HTTP 202 with transaction status: "pending" while delivery completes. Poll GET /airtime-data/{reference} until completed or failed (refunded if failed).

Immediate success: status is success, transaction status is completed. Wallet was debited on submit.

Pending Airtel data: HTTP 202, transaction status is pending. Wallet already debited — poll until delivery confirms or fails.

Failure: transaction status is failed and your wallet is refunded.

Lyca: airtime top-up only — no data bundles. Bundle purchases for Lyca numbers are rejected.

Endpoints

GET /airtime-data/catalog List available bundles by network (MTN and Airtel)
POST /airtime-data Purchase airtime or a data bundle
GET /airtime-data List purchases (paginated)
GET /airtime-data/{reference} Get purchase by reference

Authentication

Authorization: Basic YOUR_API_CREDENTIALS

YOUR_API_CREDENTIALS = base64_encode("your_api_key:your_api_secret")

Catalog & networks

Call GET /airtime-data/catalog to list supported networks, gateways, and bundle catalogs. MarzPay auto-detects the network from the MSISDN when you purchase — you do not send a network field and cannot override routing. MTN → mtn_eretailer. Airtel/Lyca airtime → africastalking_airtime. Airtel data bundles → africastalking_mobile_data.

Preview routing: GET /airtime-data/detect-network?msisdn=256771234567 returns network and expected gateways.

GET https://demo-wallet.wearemarz.com/api/v1/airtime-data/catalog
{
  "status": "success",
  "data": {
    "country": "UG",
    "currency": "UGX",
    "networks": [
      { "code": "MTN", "airtime": true, "bundles": true, "min_airtime_amount": 500, "airtime_delivery": "immediate", "bundle_delivery": "immediate" },
      { "code": "AIRTEL", "airtime": true, "bundles": true, "min_airtime_amount": 500, "airtime_delivery": "immediate", "bundle_delivery": "async" },
      { "code": "LYCA", "airtime": true, "bundles": false, "min_airtime_amount": 500, "airtime_delivery": "immediate" }
    ],
    "mtn": {
      "airtime": { "name": "Airtime top-up" },
      "bundles": { "data": { "label": "Data Bundles", "items": [ ... ] } }
    },
    "airtel": {
      "airtime": { "name": "Airtime top-up" },
      "bundles": { "data": { "label": "Data Bundles", "items": [ ... ] } }
    }
  }
}

Use each item's product_id as bundle_id in POST /airtime-data with purchase_type: "bundle". The wallet is debited the listed price — do not send amount for bundles.
For airtime, skip the catalog product list: send purchase_type: "airtime" and your own amount (minimum min_airtime_amount per network).
Airtel bundles use bundle_delivery: "async" — poll the transaction reference until final status.

Airtel & Lyca

Airtel

  • Airtime — completes immediately in the API response
  • Data bundles — may return pending; poll GET /airtime-data/{reference} until completed or failed
  • Daily, weekly, and monthly bundles are listed under airtel.bundles in the catalog

Lyca

  • Airtime top-up only
  • No data bundles — bundle purchases for Lyca numbers return INVALID_PRODUCT

Purchase Airtime or Bundle

POST https://demo-wallet.wearemarz.com/api/v1/airtime-data

Airtime example

{
  "reference": "550e8400-e29b-41d4-a716-446655440000",
  "purchase_type": "airtime",
  "msisdn": "256771234567",
  "amount": 5000
}

Data bundle example

{
  "reference": "660e8400-e29b-41d4-a716-446655440001",
  "purchase_type": "bundle",
  "msisdn": "256771234567",
  "bundle_id": "RACT_UG_Data_201"
}
Parameter Type Required Description
reference uuid Yes Unique idempotency key for the purchase
purchase_type string Yes airtime or bundle
msisdn string Yes MTN, Airtel, or Lyca number (2567XXXXXXXX or 07XXXXXXXX). Network is detected automatically.
bundle_id string Bundles only Required when purchase_type is bundle. Must not be sent for airtime.
amount integer Airtime only UGX amount (minimum depends on network — see catalog). Must not be sent for bundles — price comes from the catalog.

The response is final for MTN and airtime purchases. For pending Airtel data bundles, poll GET /airtime-data/{reference} until the transaction leaves pending.

Pending response (Airtel data)

{
  "status": "success",
  "message": "Airtime & Data purchase submitted successfully.",
  "data": {
    "reference": "660e8400-e29b-41d4-a716-446655440001",
    "status": "pending",
    "provider_reference": "ATPid_xxxxxxxx",
    "amount": { "formatted": "500", "raw": 500, "currency": "UGX" },
    "airtime_data": {
      "network": "AIRTEL",
      "purchase_type": "bundle",
      "provider_transaction_id": "ATPid_xxxxxxxx",
      "provider_status": "queued",
      "result": "pending"
    }
  }
}

HTTP status 202. Poll GET /airtime-data/{reference} — MarzPay auto-syncs delivery status on each lookup.

Success response

{
  "status": "success",
  "message": "Airtime & Data purchase completed successfully.",
  "data": {
    "uuid": "...",
    "reference": "550e8400-e29b-41d4-a716-446655440000",
    "status": "completed",
    "provider_reference": "...",
    "amount": { "formatted": "5,000", "raw": 5000, "currency": "UGX" },
    "charge": { "formatted": "0", "raw": 0, "currency": "UGX" },
    "airtime_data": {
      "network": "MTN",
      "gateway": "mtn_eretailer",
      "purchase_type": "airtime",
      "msisdn": "256771234567",
      "product_name": "Airtime top-up",
      "madapi_transaction_id": "...",
      "result": "success",
      "error_message": null
    }
  }
}

Mobile app (Airtel, Lyca & MTN)

The MarzPay mobile app uses Sanctum bearer tokens. Base path: https://demo-wallet.wearemarz.com. Purchases require current_password confirmation.

GET /app/airtime-data/catalog — networks, gateways, MTN/Airtel bundle catalogs, Lyca airtime-only note
GET /app/airtime-data/detect-network?msisdn=... — preview network and gateway before purchase
GET /app/airtime-data — list purchases for the current business
POST /app/airtime-data — purchase (body includes current_password)
GET /app/airtime-data/{reference} — lookup by reference; auto-syncs pending Airtel data bundles

Network detection: send any supported MSISDN — MarzPay detects MTN, Airtel, or Lyca automatically.

Airtel data in the app: wallet is debited on submit. If the purchase returns pending, show a waiting state and poll GET /app/airtime-data/{reference} until completed or failed (refunded if failed).

Lyca in the app: show airtime top-up only; hide or disable the bundle tab when a Lyca number is detected.

List & Lookup

GET /airtime-data supports query params: page, per_page, status, purchase_type, msisdn, reference, start_date, end_date.

GET https://demo-wallet.wearemarz.com/api/v1/airtime-data/{reference}

Common errors

SERVICE_NOT_SUBSCRIBED — Subscribe to Airtime & Data in the marketplace.
INSUFFICIENT_BALANCE — Top up your UG wallet before purchasing.
UNSUPPORTED_NETWORK — MSISDN is not MTN, Airtel, or Lyca Uganda.
INVALID_PRODUCT — Invalid bundle ID, or Lyca numbers do not support data bundles (airtime only).
DUPLICATE_REFERENCE — Use a new UUID for each purchase attempt.
Chat on WhatsApp