https://api.hyparrow.cloud/api/v1 and require your API key credentials on
every request:
Amounts are in kobo (the minor unit).
₦1,000.00 is 100000. Line-item
unitPrice and the persisted totals all follow this convention.Lifecycle
An invoice moves through a small set of statuses:
A new invoice starts as
draft. Calling
POST /invoices/{invoiceId}/send-email auto-publishes a
draft to pending so the customer can reach it. Once a payment settles (via the
hosted checkout or POST /invoices/{invoiceId}/pay), the
invoice becomes paid and can no longer be edited.
End-to-end flow
1
Create the invoice
POST /invoices/ with a title, currency, customer details and at least one
line item. Hyparrow assigns an invoiceNumber and computes the totals.2
Share the checkout URL
The checkout URL is
CHECKOUT_BASE_URL/pay/{invoiceId}. Send it to your
customer directly, or call
send-email to email the invoice PDF with the link
embedded. (Optionally generate a virtual account up front with
generate-va.)3
Customer pays
On the hosted checkout page the customer picks a payment method (bank
transfer / virtual account, USSD, card, OPay or crypto). See the
Checkout guide for the public API the page uses.
4
Status becomes paid
Poll the invoice (or the public checkout status
endpoint) until
status is paid. A receipt is generated automatically.5
Callback fires
If you set
checkoutCallbackUrl on the invoice, Hyparrow POSTs a
checkout.payment.completed event to it when the payment settles. See
the callback.Create an invoice
POST /invoices/
Creates an invoice with line items, optional invoice-level tax, discount,
shipping and customer details.
Body
Each line item:
If a line item links a
productId whose currency differs from the invoice
currency, you must send an explicit (converted) unitPrice. Hyparrow refuses
to silently reuse a price under a different currency label.Response 201
CHECKOUT_BASE_URL/pay/8f1c2e34-.... Note
that a freshly created invoice is draft — share it via
send-email (which publishes it) or publish it explicitly
before sending the link.
List invoices
GET /invoices/
Paginated list of your account’s invoices.
Search invoices
GET /invoices/search
Get an invoice
GET /invoices/{invoiceId}
Returns a single invoice (with totals and line items) for your account. Returns
404 if not found.
Update an invoice
PUT /invoices/{invoiceId}
Updates editable fields — customer details, currency, dates, tax/discount,
status, notes, metadata. Send only the fields you want to change.
Delete an invoice
DELETE /invoices/{invoiceId}
Record a payment
POST /invoices/{invoiceId}/pay
Marks an invoice paid using a payment you collected yourself (e.g. cash, or a
transfer in your own wallet system). For customer-driven payments, use the
hosted checkout instead.
Line items
Manage line items on an existing invoice. Totals are recalculated on every change.
Add a line item:
productId (auto-fills description/unitPrice) or a freeform
description + unitPrice (> 0).
Generate a virtual account
POST /invoices/{invoiceId}/generate-va
Creates a temporary virtual account (a dedicated bank account number) the
customer can transfer the exact invoice amount to. A transfer that matches the
amount settles the invoice automatically.
Virtual accounts are an NGN-only rail. They are not available for
non-NGN invoices.
Get the active virtual account
GET /invoices/{invoiceId}/va
Returns the current active, non-expired virtual account for the invoice, or
404 if none exists.
Receipt & PDFs
Once an invoice ispaid, a receipt becomes available.
The PDF endpoints stream a file with a
Content-Disposition: attachment
header — request them with your API key headers and save the binary body.
Email an invoice
POST /invoices/{invoiceId}/send-email
Generates the invoice PDF and emails it to the customer, with the hosted
checkout link embedded. This is the usual way to “send” an invoice.
- A
draftinvoice is auto-published topendingso the checkout link works. - For a
paidinvoice this sends the receipt instead. - A duplicate send is rejected (
"Invoice has already been mailed"/"Receipt has already been mailed"). - Fails with
400if the invoice has nocustomerEmail.
Next steps
- Checkout guide — the public API the hosted payment page uses, and the callback webhook.
- Sandbox — test the full flow with simulated money.

