X-API-Key / X-API-Secret headers
because the customer paying the invoice is not your API client. The base URL is
the same: https://api.hyparrow.cloud/api/v1.
Amounts are in kobo.
payableAmount, totalAmount and friends are in the
minor unit (100000 = ₦1,000.00).Payment methods
The customer-facing options on the checkout page are:
Which methods appear depends on the merchant’s payment preferences and the
invoice currency — the NGN-only rails (bank transfer, USSD) are hidden for
non-NGN invoices. The active set is returned as
allowedPaymentMethods from
GET /checkout/{invoiceId}.
End-to-end flow
1
Customer opens the checkout page
The page calls
GET /checkout/{invoiceId} to load the invoice, amounts and
allowed payment methods.2
Customer picks a method
Depending on the choice, the page calls
…/va, …/ussd, …/card,
…/opay or …/crypto to start that payment.3
Customer pays
Transfer to the virtual account, dial the USSD code, complete the card /
OPay redirect, or send crypto to the address.
4
Page polls for status
The page polls
GET /checkout/{invoiceId}/status until paid is true.5
Callback fires
Hyparrow
POSTs a checkout.payment.* event to the invoice’s
checkoutCallbackUrl (if set) as the payment progresses.Load the checkout
GET /checkout/{invoiceId}
Returns sanitized invoice data for rendering the page. Canceled invoices return
404.
payableAmount is what the customer actually pays. When the invoice’s
tax_direction is customer, the service fee (capped) and VAT are added on top
of totalAmount; when it’s merchant, payableAmount equals totalAmount and
the fees are settled from the merchant’s payout.
Bank transfer (virtual account)
POST /checkout/{invoiceId}/va
Creates (or returns the existing active) virtual account for the invoice.
expiryMinutes accepts 10, 15 or 30; anything else defaults to 15.
200 instead of creating
a duplicate.
GET /checkout/{invoiceId}/va returns the current active, non-expired account,
or 404 if there is none (e.g. it expired).
USSD
POST /checkout/{invoiceId}/ussd
Generates a USSD dial code for the customer’s bank.
checkout.payment.pending callback fires when the code is generated.
Card
POST /checkout/{invoiceId}/card
Charges a card via the card network. Card details are encrypted before they
leave the browser.
responseCode:
00— approved. The invoice is settled and acheckout.payment.completedcallback fires.T0/S0— processing (e.g. an OTP/3-DS step). Acheckout.payment.pendingcallback fires; keep polling status.- anything else — declined. A
checkout.payment.failedcallback fires.
OPay
POST /checkout/{invoiceId}/opay
Initializes an OPay payment and returns a redirectUrl to send the customer to.
checkout.payment.pending callback fires on
initialization.
Crypto
POST /checkout/{invoiceId}/crypto
Generates a stablecoin payment address. The fiat total is converted to USD.
token is USDC or USDT. The customer sends the asset to address before
expiresAt (30 minutes). GET /checkout/{invoiceId}/crypto returns the active
address. Settlement arrives asynchronously once the on-chain transfer confirms.
Poll status
GET /checkout/{invoiceId}/status
The checkout page polls this until the payment lands.
paid is true once the invoice is paid (or a receipt exists). Use this as
the source of truth on the page; the asynchronous methods (transfer, USSD, OPay,
crypto) flip it when settlement confirms.
Payment links
A payment link lets you collect a payment without pre-creating an invoice — useful for a shareable “pay me” page. The public URL isCHECKOUT_BASE_URL/pay/{identifier}, where identifier is the link’s custom
slug or its id.
GET /checkout/pay/{identifier} returns the link’s page data (name,
description, amount, allowed methods):
POST /checkout/pay/{identifier} turns the customer’s submission into an invoice
so the normal payment rails can settle it. If the link has a fixed amount it
wins; otherwise the customer-entered amount is used.
invoiceId to the standard checkout flow above
(…/va, …/card, etc.) to complete payment.
Edge cases
Checkout callback webhook
If the invoice has acheckoutCallbackUrl, Hyparrow POSTs an event to it as
the payment progresses. The body is:
checkout.payment.pending— payment started, awaiting settlement (transfer pending, USSD/OPay in progress, card in 3-DS).checkout.payment.completed— settled; the invoice ispaid.checkout.payment.failed— the attempt failed (e.g. a declined card).
GET /checkout/{invoiceId}/status before fulfilling.
Sandbox
In the sandbox, the hosted checkout URL carries?sandbox=true and
points at the sandbox API (https://sandbox.hyparrow.cloud/api/v1). You don’t
need a real bank transfer or card to test — complete the payment instantly:
Use the “Simulate payment” button on the sandbox checkout page, or call
POST /checkout/{invoiceId}/simulate-payment directly. It runs the invoice
through the normal payment path — marking it paid, issuing a receipt and
firing the checkout.payment.completed callback — with simulated money. It is
available only on the sandbox deployment (returns 404 in production).200 with "invoice already paid".
