Quickstart
Issue an invoice, open its payment page, and know when it has been paid.
Four calls take you from nothing to money in your balance: create the document, open its page, hand the customer the URL, then listen for the payment. Nothing happens between those steps on its own, which is the thing most people get wrong on their first invoice.
Live only, and your first invoice is real
Invoices do not exist in sandbox. Every /invoices route answers 403 with This feature is only available in live mode. to a sk_test. key, GET included, so there is nothing to try against
first. Issue your first one to yourself for a small amount. The feature is invoicing: 10
invoices in total on Pay as you go, unlimited from Growth upward.
1. Create the document
An invoice is created as a draft and stays there until you move it. Creating one writes a numbered document and nothing else: no money moves, no mail goes out, and the customer learns nothing.
Four fields are required, and a customer record is not among them. An invoice is addressed to a name, so you can bill someone who has never paid you before.
https://api.wajub.com/invoicescustomer_namestringrequireditemsarrayrequiredname, quantity and unit_price.invoice_datestring (date)requiredcurrencystringrequiredcustomer_emailstringoptionaldue_datestring (date)optionalinvoice_date. What decides when the invoice turns overdue.customer_idstring (uuid)optionalThe full field list, taxes, discounts and the rest, is on the Invoice page. Send this one with a live secret key.
curl https://api.wajub.com/invoices \
-H "Authorization: sk.kZ3qP8mWvL2xR7tB5nY4hC6dF9jS1aG0eU3i…" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: invoice-amina-september" \
-d '{
"customer_name": "Amina Traoré",
"customer_email": "amina@example.com",
"invoice_date": "2026-09-11",
"due_date": "2026-09-25",
"currency": "XAF",
"items": [
{ "name": "Consulting, September", "quantity": 3, "unit_price": 150000 }
]
}'The answer is 201 Created. Totals are computed from the lines, so subtotal, total and
amount_due come back filled even though you never sent them.
Keep the id: every call that follows takes it. invoice_number is the human reference printed on
the document, INV- plus the year and month, then a counter that restarts at 0001 each month.
2. Open its payment page
A draft invoice cannot be paid. Its public page answers 403 This invoice is not available for payment. to anyone who opens it, and only four statuses are payable: sent, viewed, overdue
and partial.
One call moves it out of draft.
https://api.wajub.com/invoices/{id}/sendcurl -X POST https://api.wajub.com/invoices/inv_LRQqYvlhrgUOE225KMKU/send \
-H "Authorization: sk.kZ3qP8mWvL2xR7tB5nY4hC6dF9jS1aG0eU3i…"It answers 200 with status: "sent" and sent_at stamped.
Send does not send anything
The call sets the status and the timestamp. That is all. It renders no PDF and it emails nobody. The mail with the PDF attached comes from the Dashboard's own Send button, a path the API does not reach. Read this step as opening the page, not as delivering it.
3. Hand over the URL
Delivery is yours: WhatsApp, SMS, your own email, whatever you already use with that customer. The address is the invoice id on its own host.
https://invoice.wajub.com/inv_LRQqYvlhrgUOE225KMKUThat URL is not in the API response, so build it from the id you kept. The host is the one thing
that varies: a merchant serving invoices from a verified custom domain gets that domain instead, and
the Dashboard shows the real address on the invoice.
What opens is an ordinary checkout carrying your branding, the invoice's lines and the operators
available for its currency. The first time the customer opens it, the invoice moves from sent to
viewed on its own.
4. Know when it has been paid
A paid invoice produces two events, and they are not interchangeable.
payment.succeeded is the money. It carries the amount, the channel, the provider reference, and
it is the one to fulfil on, because it is the only one that proves funds moved.
invoice.updated is the document. It fires on every change the invoice goes through, and paid is
just one of them.
invoice.updatedeventThere is no invoice.paid, no invoice.sent and no invoice.overdue. The three events an invoice
ever emits are invoice.created, invoice.updated and invoice.deleted, so the status on the
payload is what tells you which transition you are looking at.
Fulfil on the payment, reconcile on the invoice
Deliver what the customer bought when payment.succeeded arrives, and use invoice.updated to
keep your own copy of the document in step. Doing it the other way round means acting on a status
that a manual mark-paid can also produce.
When the money came in elsewhere
Cash, a bank transfer, a payment that never touched Wajub: record it against the document rather than leaving the invoice open.
https://api.wajub.com/invoices/{id}/mark-paidSend no amount and the invoice is settled in full. Send one and it is added to amount_paid,
which leaves the invoice partial until the total is covered. A cancelled or refunded invoice
refuses the call with 400.
The statuses, and who writes them
Only three of the eight are yours to set. The rest are written by the customer's own actions or by a nightly job, which is worth knowing before you build a state machine of your own on top.
| Status | Meaning | Written by |
|---|---|---|
draft | Created, not payable | Creation |
sent | Payable, waiting | Your /send call |
viewed | The customer opened the page | The customer, on first open |
partial | Some of the total is in | A payment, or your /mark-paid |
paid | Settled in full | A payment, or your /mark-paid |
overdue | Past due_date, still unpaid | A job, nightly at 01:00 |
cancelled | Closed, no longer payable | Your /cancel call |
refunded | Paid, then given back | A refund on the payment |
Related pages
- Invoice referenceEvery field, how the totals are computed, and the eight calls.
- Recurring invoicesWhat the recurring flag does today, and what it does not.
- Reminders & follow-upChasing an invoice that has gone quiet.
- CustomersBill a customer record rather than a name.
- Invoices API referenceEvery field and the eight endpoints.