Skip to Content
TransactionsAirtime Async

Airtime Async

Async: the API stores the transaction, enqueues it, and returns immediately with HTTP 200 and response_code 02 (pending). Poll status until final.

RouteNotes
POST /v1/transactionsproduct: airtime or data
POST /v1/transactions/airtime/asyncForces product: airtime
POST /v1/transactions/data/asyncForces product: data

For sync creates (final outcome in the create response), see Airtime.

Bill products (ELECTRICITY, CABLE, BETTING) are sync on POST /v1/transactions — see Bill payments overview.

Request body

FieldRequiredDescription
merchant_codeYesYour merchant profile
customer_msisdnYesSubscriber number (234… or 080…)
networkYesmtn, glo, airtel, 9mobile
productYesairtime, data, ELECTRICITY, CABLE, or BETTING
amountYesAmount in Naira (string)
client_request_idYesYour unique idempotency key
plan_codeData & billsData: prefixed code from Data plans (e.g. MTN-8). Bills: catalog id from Electricity, Cable TV, or Betting. Legacy tariff/product ids still work for existing clients.

Create and status responses use the same envelope: status, response_code, response_message, and data. See Field conventions.

Buy airtime (async)

curl -X POST "https://api.breezeinnovations.io/v1/transactions" \ -H "Content-Type: application/json" \ -H "X-Merchant-Key: mk_your_key_id" \ -H "X-Merchant-Secret: your_issued_secret" \ -d '{ "merchant_code": "YOUR_MERCHANT", "customer_msisdn": "2348012345678", "network": "mtn", "product": "airtime", "amount": "100", "client_request_id": "req-20260517-003" }'

HTTP 200 — pending (poll status):

{ "status": "pending", "response_code": "02", "response_message": "Pending", "data": { "internal_reference": "019262ab-7c4d-7000-8000-000000000001", "msisdn": "2348012345678", "product": "airtime", "request_id": "req-20260517-003", "network": "MTN", "amount": "100", "plan": "", "merchant_id": 10 } }

Check status

Use after async creates, or to re-fetch an outcome. Pass the same client_request_id you sent on create as a query parameter (not in the URL path).

GET /v1/transactions/status?client_request_id={client_request_id}
QueryRequiredDescription
client_request_idYes*Your idempotency key from the create call (recommended)
request_idAlt.Same value — matches the request_id field in responses
request_refAlt.Same value — legacy alias for client_request_id

*One of client_request_id, request_id, or request_ref is required.

Example — poll after an async airtime create:

curl "https://api.breezeinnovations.io/v1/transactions/status?client_request_id=req-20260517-003" \ -H "X-Merchant-Key: mk_your_key_id" \ -H "X-Merchant-Secret: your_issued_secret"

If you used sync create (Airtime) and received response_code 00 or 01, you already have the final outcome — status polling is optional.

HTTP 400 — missing query param:

{ "status": "error", "code": 400, "message": "client_request_id, request_id, or request_ref query parameter is required" }

HTTP 200 — same envelope as create:

{ "status": "success", "response_code": "00", "response_message": "Successful", "data": { "internal_reference": "019262ab-7c4d-7000-8000-000000000001", "msisdn": "2348012345678", "product": "airtime", "request_id": "req-20260517-003", "network": "MTN", "amount": "100", "merchant_id": 10, "merchant_name": "YOUR_MERCHANT", "created_at": "2026-05-17 10:30:00", "updated_at": "2026-05-17 10:31:15" } }

updated_at is the last time the transaction row changed (for example when an MTN status check moves it from pending to success/failed). List transactions returns the same fields on each row.

response_codestatusMeaning
00successCompleted successfully
01failedFailed
02pendingStill processing

List transactions

GET /v1/transactions
QueryDefaultDescription
page1Page number
limit10Page size
msisdn—Filter by subscriber
network—Filter by network name
status—Filter by status code (integer)
curl "https://api.breezeinnovations.io/v1/transactions?page=1&limit=20" \ -H "X-Merchant-Key: mk_your_key_id" \ -H "X-Merchant-Secret: your_issued_secret"

HTTP 200:

{ "status": "success", "data": [], "pagination": { "total": 0, "page": 1, "size": 20, "total_pages": 0 } }

Idempotency

Reusing the same client_request_id for a merchant returns 422. Query status instead of resubmitting.

Last updated on