Services
Bill payments, airtime, data, and utility purchases through one order API.
A service is a purchasable digital product or bill: mobile top-up, data bundle, utility payment, subscription, or voucher. Every purchase produces a service order linked to a transaction entry: the transaction is the ledger truth, the order tracks fulfilment of the purchased item.
You never integrate with a fulfilment vendor directly. OuiPay routes each order to the fulfilment rail configured for the service and country, and exposes the same contract regardless of which rail executes it.
Service catalogue
service_code identifies the product family. Availability is per country: the
catalogue for a country only returns the services that country offers.
| Code | Category | Sells | Recipient |
|---|---|---|---|
airtime | mobile | Mobile airtime top-up | Phone number |
data | mobile | Mobile data bundles | Phone number |
electricity | utilities | Prepaid token / postpaid bill | Meter number |
water | utilities | Water utility bills | Meter/account no. |
internet | utilities | ISP and broadband subscriptions | Customer ID |
tv | entertainment | Cable and satellite subscriptions | Smartcard / IUC |
betting | entertainment | Betting wallet funding | Account ID / phone |
gift_cards | entertainment | Digital gift cards | Recipient email |
education | education | Exam PINs and result-checker products | Candidate/profile |
insurance | finance | Insurance premiums and cover packages | Policy holder |
Two pricing models exist. Fixed-price services (data, tv, internet,
education, insurance, gift_cards) sell a plan selected from
/plans. Open-amount
services (airtime, electricity, water, betting) take a customer-entered
provider_cost_minor.
The operators behind each service (mobile networks, DisCos, TV providers, exam bodies) resolve per country: see Supported networks for per-market coverage.
The purchase flow
GET /services?country= catalogue for the service country
GET /services/{code} form schema + rules + country_context
GET /services/{code}/operators networks, DisCos, providers for the service
GET /services/{code}/plans bundles/bouquets for an operator
GET /services/{code}/variants variants (e.g. prepaid / postpaid meter)
POST /services/{code}/validate verify the recipient before quoting
POST /services/quote locked price, fee, and FX
POST /services/orders create the order and collect payment
GET /services/orders/{id}/status poll, or wait for the webhookNot every step applies to every service. The steps array on the
service definition tells the
client which inputs to collect, and requires_validation tells it whether to
call /validate before quoting.
The service order object
{
"id": "01M2S18...",
"transaction_id": "01M2S18...",
"payment_transaction_id": "01M2S18...",
"country_code": "NG",
"service_code": "electricity",
"status": "fulfilling",
"customer_amount_minor": 510000,
"fee_minor": 10000,
"provider_cost_minor": 500000,
"currency": "NGN",
"operator_code": "ikeja-electric",
"meter_type": "prepaid",
"account_ref": "04591234567",
"provider_reference": "IKEDC-99218...",
"quote_id": "01M2S17...",
"created_at": "2026-09-18T02:00:00Z",
"updated_at": "2026-09-18T02:00:41Z"
}| Field | Type | Notes |
|---|---|---|
transaction_id | string | The type=service transaction entry: source of truth |
payment_transaction_id | string | The collection transaction once payment is initiated |
country_code | string | Service country the order executes in (ISO 3166-1 alpha-2) |
customer_amount_minor | int | What the customer pays, in currency |
provider_cost_minor | int | Destination service value, in the destination currency |
fee_minor | int | OuiPay fee included in customer_amount_minor |
meter_type | string | Selected variant when the service has one (e.g. prepaid) |
provider_reference | string | Fulfilment reference once the order is dispatched |
quote_id | string | The locked quote this order was priced from |
fulfillment_snapshot | object | Fulfilment detail: tokens, pins, and receipts land here |
Same-currency orders always satisfy
customer_amount_minor = provider_cost_minor + fee_minor. Cross-currency
orders carry the locked FX terms in pricing_snapshot.
Order status
pending -> awaiting_payment -> fulfilling -> completed
|-> failed | retry_required | refund_pending -> refunded
|-> unknown (reconciled to completed or failed)
pending|awaiting_payment -> cancelled| Status | Meaning |
|---|---|
pending | Created; payment not yet initiated |
awaiting_payment | Waiting on the collection to settle |
fulfilling | Paid; purchase dispatched to the fulfilment rail |
completed | Delivered: fulfillment_snapshot carries tokens/pins |
failed | Definite failure; customer funds released or refunded |
unknown | Timed out with no definite outcome: reconciled, never re-purchased |
retry_required | Queued for a controlled fulfilment retry |
provider_funding_failure | Paid, but the rail could not fund the purchase; refund path opens |
manual_fulfilment | Held for an authorized operator to complete |
refund_pending | Refund in progress on the payment |
refunded | Customer money returned; terminal |
cancelled | Cancelled before fulfilment; terminal |
unknown is not failed: a timed-out purchase may have reached the rail.
Treat it as in-flight and wait for the terminal webhook or a later status poll.
Webhooks
Fulfilment is asynchronous. Subscribe to service_order.completed and
service_order.failed rather than polling
/status in a tight loop. See
Webhook Events.
Country scoping
Every services call takes a service country: the country the purchase
executes in, which decides the catalogue, operators, plans, currency, and
limits. It is independent of the customer's account country. See
Countries for the home vs service
country model and the country_context selector contract.
Endpoints
| Method | Path | Description |
|---|---|---|
| GET | /v1/services | Catalogue for a country |
| GET | /v1/services/{code} | Definition, steps, limits |
| GET | /v1/services/{code}/availability | Effective country selector for this customer |
| GET | /v1/services/{code}/payment-methods | Payable methods for this service and country |
| GET | /v1/services/{code}/operators | Networks / billers |
| GET | /v1/services/{code}/plans | Bundles and fixed-price plans |
| GET | /v1/services/{code}/variants | Variants (meter type, etc.) |
| POST | /v1/services/{code}/validate | Verify a recipient |
| POST | /v1/services/quote | Locked price quote |
| POST | /v1/services/orders | Create an order |
| GET | /v1/services/orders/{id} | Order detail |
| GET | /v1/services/orders/{id}/status | Compact status poll |