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
pendinguntil delivery is confirmed. Poll untilcompletedorfailed. - 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
/airtime-data/catalog
List available bundles by network (MTN and Airtel)
/airtime-data
Purchase airtime or a data bundle
/airtime-data
List purchases (paginated)
/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.
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; pollGET /airtime-data/{reference}untilcompletedorfailed - Daily, weekly, and monthly bundles are listed under
airtel.bundlesin the catalog
Lyca
- Airtime top-up only
- No data bundles — bundle purchases for Lyca numbers return
INVALID_PRODUCT
Purchase Airtime or Bundle
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 noteGET /app/airtime-data/detect-network?msisdn=... — preview network and gateway before purchaseGET /app/airtime-data — list purchases for the current businessPOST /app/airtime-data — purchase (body includes current_password)GET /app/airtime-data/{reference} — lookup by reference; auto-syncs pending Airtel data bundlesNetwork 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.
https://demo-wallet.wearemarz.com/api/v1/airtime-data/{reference}