Airtime & Data API

Buy MTN Uganda airtime and data bundles using your MarzPay wallet. This is separate from bill payments (utilities/TV) and has no platform service charge.

API Overview

Base URL

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

Authentication

API Key (Basic Auth)

Market

Uganda (UGX) — MTN only
  • Subscribe to Airtime & Data in the service marketplace before using the API.
  • Purchases debit your UG wallet for the exact airtime or bundle amount (0% MarzPay charge).
  • No callbacks or webhooks — each purchase is processed synchronously and returns completed or failed in the same API response.
  • Airtel support is coming soon — only MTN numbers are accepted today.
  • POST requests require your IP to be on the API whitelist.

Synchronous processing — no callbacks

Unlike collections or some bill payments, Airtime & Data does not send webhook or callback notifications. When you call POST /airtime-data, MarzPay calls MTN immediately and the HTTP response already contains the final outcome.

On success: status is success and the transaction status is completed. Your wallet is debited and airtime/data is delivered to the MSISDN.

On failure: status is error and the transaction status is failed. Your wallet is not debited.

To reconcile later: use GET /airtime-data/{reference} or GET /airtime-data — do not wait for a callback that will never arrive.

Endpoints

GET /airtime-data/catalog List available MTN bundles (data, voice, combo, etc.)
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")

Get MTN bundles

Call GET /airtime-data/catalog to list every MTN bundle MarzPay supports. Bundles are grouped by category (data, voice, combo, etc.). Each item includes the bundle_id you pass when purchasing, plus the display name and price in UGX.

GET https://wallet.wearemarz.com/api/v1/airtime-data/catalog
{
  "status": "success",
  "data": {
    "country": "UG",
    "currency": "UGX",
    "networks": ["MTN"],
    "min_airtime_amount": 500,
    "airtime": {
      "name": "Airtime top-up"
    },
    "bundles": {
      "data": {
        "label": "Data Bundles",
        "items": [
          {
            "product_id": "RACT_UG_Data_201",
            "name": "Daily bundle of 165MB",
            "price": 1000
          },
          {
            "product_id": "RACT_UG_Data_79",
            "name": "Monthly Bundle of 48 GB",
            "price": 100000
          }
        ]
      },
      "voice": {
        "label": "Voice 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).

Purchase Airtime or Bundle

POST https://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 number (2567XXXXXXXX or 07XXXXXXXX)
bundle_id string Bundles only Required when purchase_type is bundle. Must not be sent for airtime.
amount integer Airtime only UGX amount (min 500). Must not be sent for bundles — price comes from the catalog.

The response is final. There is no pending state to poll and no callback URL to configure — treat the HTTP response (or a later GET by reference) as the source of truth.

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",
      "purchase_type": "airtime",
      "msisdn": "256771234567",
      "product_name": "Airtime top-up",
      "madapi_transaction_id": "...",
      "result": "success",
      "error_message": null
    }
  }
}

List & Lookup

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

GET https://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 — Only MTN numbers are supported for now.
DUPLICATE_REFERENCE — Use a new UUID for each purchase attempt.
Chat on WhatsApp