Skip to main content

Overview

The Bills API lets you browse a catalog of billers, validate a customer (meter, smartcard/IUC, or account) before charging, and pay for airtime, data, cable TV, and electricity. Every successful payment debits your Hyparrow wallet. There are two route families:
  • /bills/*, the primary catalog-driven flow. You discover billers and payment items from the cache, validate a customer, then pay by paymentCode.
  • /bills/topup/*, an alternate bill-pay route set that resolves products by catalog ids (network / plan / provider) instead of payment codes, and also supports printable PIN products (exam PINs, recharge-card PINs, data PINs).
Both families ultimately route to the bill provider and the same wallet.
Base URL: https://api.hyparrow.cloud/api/v1Auth: every request requires X-API-Key and X-API-Secret headers.Sandbox: point at https://sandbox.hyparrow.cloud/api/v1 and use your pk_test_ key. In sandbox you can simulate outcomes with magic amounts, an amount ending in .01 forces a failed result, and .99 forces a pending result. Everything else succeeds.

Amount units

Discovering billers

The primary flow is driven by a cached catalog. Walk it from categories down to the specific payment item, whose PaymentCode you pass to /bills/pay.
1

List categories

GET /bills/categories returns the available bill categories (airtime, data, cable TV, electricity, and more).
2

List billers in a category

GET /bills/category/billers?category=<name|id> returns the billers under a category. You can also browse everything with GET /bills/services.
3

Get payment options

GET /bills/services/options?serviceId=<id> returns the payment items (plans / packages) for a biller, each carrying the PaymentCode and Amount you need to pay.
4

Find a specific biller (optional)

GET /bills/search?q=<term> free-text searches the catalog, and GET /bills/biller?category=<name>&biller=<name> returns a single biller matched by category + biller name.
List categories
Response

Validate before you pay

For services tied to a customer account, electricity meters and cable smartcards/IUCs, validate the customer first. This confirms the beneficiary name and that the account is payable before any money leaves the wallet.
Validate a customer
Response
/bills/validate accepts both the flat shape above and an array shape ({ "customers": [{ "CustomerId": "...", "PaymentCode": "..." }] }). Both customerId and paymentCode are required.

Paying a bill

POST /bills/pay charges the wallet and submits the payment. The amount is in kobo and, for fixed-price payment items, must exactly match the cached item amount, otherwise the request is rejected with the required amount. For flexible-price items you supply the amount; if you omit it on a fixed-price item, Hyparrow auto-fills it from the catalog.
1

Resolve the payment item

From the catalog, take the PaymentCode (and Amount for fixed items).
2

Validate (metered/cable services)

Confirm the beneficiary with /bills/validate.
3

Pay

Call /bills/pay. The wallet is debited and the payment is submitted to the bill provider in one call.
4

Confirm

Poll /bills/status?reference=<ref> to confirm the final outcome.
Pay a bill
Response
The data.TransactionRef (or your own requestRef) is what you use to check status later.

Examples by category

Checking status

GET /bills/status?reference=<ref> returns the latest status for a bill transaction. Pass either the provider TransactionRef returned by /bills/pay or your own requestRef.
Response
In sandbox, use the magic amounts to exercise status handling: an amount ending in .99 (e.g. "19999" for ₦199.99) lands in pending so you can test polling, and .01 lands in failed.

Edge cases

Wrong amount for a fixed-price item. If a payment item has a fixed price and your amount does not match it, the request is rejected before any charge:
Insufficient wallet balance. If the wallet cannot cover the amount, the deduction fails and the payment is never submitted:
Validation service unavailable. If the upstream customer-validation lookup times out, /bills/validate returns 503 with a retry-friendly message. Retry shortly; do not attempt to pay an unvalidated metered/cable customer.

Alternate route set, /bills/topup

/bills/topup/* is an alternate bill-pay route set. Instead of payment codes it resolves products by catalog ids (network, plan, provider), and it adds printable PIN products that the primary routes don’t cover. Hyparrow prices each category server-side and debits the result; if the provider declines or errors, the wallet deduction is automatically refunded.
Airtime costs less than face value. It carries no markup, Hyparrow passes part of its wholesale discount back to you, so chargeKobo is below the amount you sent: 1.5% off MTN and Airtel, 2% off GLO and 9mobile. ₦100 of MTN debits ₦98.50 and your customer still receives ₦100. Every other category adds a markup instead. Always trust the returned chargeKobo.

Resolve catalog ids

GET /bills/topup/services?service=<type> returns the catalog you need to build a request. Valid service values include network, data, cabletv, cable-provider, electricity, exampin, datapin, and recharge-card.
Fetch data plans
Response
priceKobo is what you will be charged. Three fields describe the price:Show the discount rather than only the net figure, a saving the buyer can’t see earns nothing. Display priceKobo as the price paid, and listPriceKobo struck through beside it if you want the contrast.
Do not send an amount for these products. Data bundles and cable bouquets are priced server-side from the plan id. Any amount in the request is ignored, and the authoritative figure comes back as chargeKobo in the payment response.This changed: amount was previously the base price you supplied. It could not stay that way, the provider selects the product from plan alone and never sees an amount, so a caller-supplied price decided the debit while the id decided the goods. amount is still required for airtime and electricity, which are genuinely open-value.
Catalog entries are cleaned before they reach you:
  • Labels disambiguate. A network commonly sells several plans of the same size that differ only by validity, so the duration is part of the label. Sizes are normalized (500 MB and 500MB both become 500MB), and provider-internal distribution terms are removed.
  • Structured fields, not string parsing. size, validityDays and tag (social, night, whatsapp, voice, …) are separate, so you can filter and group without pattern-matching the label.
  • Unsellable rows are dropped, including zero-priced entries the provider uses to broadcast notices.
  • available: false entries are still returned, sorted last, so you can grey them out rather than lose them.
id is always the provider’s identifier, unchanged, pass it straight back as plan, network, or provider.
If Hyparrow doesn’t yet recognise a catalog, the response carries "normalized": false and data is the raw upstream payload. Prices in that case are not retail, treat the catalog as unpriced and contact support.

Validate (cable / electricity)

POST /bills/topup/validate resolves the customer name for a cable IUC or an electricity meter. Airtime and data have nothing to validate.
Validate a meter
Response

Pay (airtime / data / TV / electricity)

POST /bills/topup pays a bill resolved by catalog ids. service is one of airtime, data, tv, electricity. Whether you send an amount depends on the category:
  • Airtime and electricity are open-value. amount is required, in kobo, and is the value your customer receives. Hyparrow applies the category’s pricing before debiting.
  • Data and cable TV are fixed-price. Omit amount, the price is resolved server-side from plan. Anything you send is ignored.
Either way, chargeKobo in the response is what actually left the wallet.
Response
The response exposes the full charge breakdown: baseKobo (what you sent), markupKobo (Hyparrow’s markup), cashbackKobo (the discount off face value, airtime only) and chargeKobo (what the wallet was debited). markupKobo and cashbackKobo are never both non-zero, a category is priced one way or the other.
Airtime response, charged below face value
Declined purchase is refunded. If the bill provider declines (e.g. invalid plan), the endpoint returns success: false with the provider message, and the wallet deduction is refunded automatically:

PIN products

These routes generate printable PINs. Pricing is server-side: send the product id and a quantity, and Hyparrow prices the order from the catalog. A declined purchase is refunded in full.
Do not send an amount. It is ignored. The provider selects the product from the id and quantity and never sees an amount, so a caller-supplied price would decide the debit while the id decided the goods. The figure charged comes back as chargeKobo.
Recharge-card PINs are sold at face value, a ₦500 card costs ₦500, and Hyparrow’s margin is the wholesale discount underneath. Denominations discounted less than 1% of face are not sold at all and will be rejected as unavailable.
Response
Status for /bills/topup/* payments is available through the same GET /bills/status?reference=<ref> endpoint, using the reference returned by the payment call.