Invoicing
Bill a customer for sales you have already made, discount an invoice before it is issued, and correct one already sent with a void or a credit note.
ResellerHQ does not take payment from your customers. There is no card form, no payment
link and no payout. You collect the money however you already do, by bank transfer, your own
card processor or cash, and then mark the invoice paid here. paid is your own record that
the money arrived, and nothing checks it.
Raise an invoice
An invoice bills one customer for sales you have already made for them. Each line is a copy of a sale at the price it was made at, so an invoice reads the same for good.
curl -X POST https://resellerhq.com/api/v1/invoices \
-H "Authorization: Bearer $RHQ_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 2f1c9a52-7d0e-4a8e-9a53-0c1f6f3f2b11" \
-d '{ "customerId": "cus_01K6XJ4Q8ZT3M9R5V2B7WDHNCA", "dueInDays": 14, "taxBps": 2000 }'- With
customerIdalone, the invoice takes every sale of theirs that is not on an invoice yet, oldest first.saleIdsbills only the sales you name;GET /sales?invoiced=falselists the ones still waiting. dueInDaysis 14 when left out.taxBpsadds tax as a share of the subtotal, in basis points, rounded to the nearest minor unit; left out, there is no tax.noteis free text.- Invoices are numbered
INV-0001,INV-0002and so on across your account. A number is never used twice, and a refused request uses none. - An invoice is in one currency. If the customer has sales in two, the request is refused
with
mixed_currencies; sendcurrencyto bill one of them at a time. - An invoice holds at most 500 sales. With more waiting, the oldest 500 go on it and the rest go on the next.
| Error | Why |
|---|---|
nothing_to_invoice | The customer has no sales waiting to be invoiced |
mixed_currencies | The sales are in more than one currency |
sale_unavailable | A sale you named is not this customer's, or is already on an invoice |
invoice_not_open | The invoice is already paid, void or fully credited |
invoice_not_voidable | The invoice carries a credit note, so it has to stay standing |
invalid_paid_at | paidAt is in the future, or more than a year before the invoice was issued |
invalid_discount | A discount names a sale that is not on this invoice |
A sale is on at most one invoice that still stands. Each sale carries invoiceId, which is
null until it is invoiced.
Your billing details
PATCH /account/billing sets how you are identified on invoices, and the defaults a new one
falls back to when you do not say otherwise.
curl -X PATCH https://resellerhq.com/api/v1/account/billing \
-H "Authorization: Bearer $RHQ_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"legalName": "Northwind Telecom Ltd",
"addressLines": ["1 Market Street", "San Francisco, CA 94105"],
"taxId": "12-3456789",
"billingEmail": "billing@northwind.example",
"defaultDueDays": 30,
"defaultTaxBps": 2000,
"invoiceNote": "Thank you for your business"
}'- Send only what changes;
nullclears a field.GET /accountreads it all back underbilling,nullfor anything you have not set andaddressLines: []for none. defaultDueDays,defaultTaxBpsandinvoiceNoteare used on a new invoice only when that invoice's owndueInDays,taxBpsornoteis left out; sending one,0included, always wins over the default. With neither a default nor a value sent,dueInDaysis 14.- Every invoice and credit note keeps
issuer: a copy of your name and billing details as they stood the moment it was issued. Changing your billing details later never rewrites a document already issued, andissuerisnullon one made before you had set any. - Live and sandbox are separate accounts, so each keeps billing details of its own.
Discount an invoice
A discount is money off before an invoice is issued: send it in the POST /invoices body,
alongside the sales being billed.
curl -X POST https://resellerhq.com/api/v1/invoices \
-H "Authorization: Bearer $RHQ_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 9b3a1f2e-5c6d-4e7a-8f9b-1a2b3c4d5e6f" \
-d '{
"customerId": "cus_01K6XJ4Q8ZT3M9R5V2B7WDHNCA",
"discounts": [
{ "saleId": "sal_01K6XJ4Q8ZT3M9R5V2B7WDHNCA", "percentBps": 1000 },
{ "amount": 500, "description": "Loyalty credit" }
]
}'- A discount is either a line discount, naming the
saleIdit comes off, or a whole-invoice discount, applying to the sales' subtotal, whensaleIdis left out. - A discount is either a percentage,
percentBpsfrom 1 to 10,000 (1000is 10%), or a flat amount,amountin the invoice's currency above zero — exactly one of the two. - Each discount becomes its own line, after every sale line, with a negative
totaland nosaleIdof its own, in the order you sent them. Leavedescriptionout and one is written for you:Discount, 10% off northwind.com,Discount, northwind.com,Discount, 10%or plainDiscount, depending on whether it is a line or whole-invoice discount and a percentage or an amount. - A line discount cannot take that line below zero; discounts together cannot take the
invoice's subtotal below zero. Going past either is refused with
discount_too_largeand amaximum, what was left to discount. - Tax is worked out after the discount: it is a share of the subtotal with every line, discounts included, already added up. An invoice holds at most 20 discounts.
Mark it paid
curl -X POST https://resellerhq.com/api/v1/invoices/inv_01K6XJ4Q8ZT3M9R5V2B7WDHNCA/pay \
-H "Authorization: Bearer $RHQ_API_KEY"paidAt is when the money arrived, and is now when left out. An invoice is open until you
mark it paid, void it, or credit it in full, which closes it as credited instead — see
Void or credit below. paid and void are both final: a paid invoice
cannot be voided or paid again, and a void one cannot be reopened.
The due date is a whole day. An open invoice has overdue: true from 24 hours after
dueAt, when that day has ended everywhere, so an invoice made with dueInDays: 0 is due
today and not overdue today. Nothing else happens to an overdue invoice, and no reminder is
sent.
The public share link
curl -X POST https://resellerhq.com/api/v1/invoices/inv_01K6XJ4Q8ZT3M9R5V2B7WDHNCA/share \
-H "Authorization: Bearer $RHQ_API_KEY"This is how you hand an invoice to the customer it bills: it answers with
{ token, createdAt }, and the invoice is then readable at GET /public/invoices/{token}
with no API key at all. Pressing the button twice is safe, since a second call returns the
same token rather than minting a new one. The public page shows that one invoice and nothing
else: no id, no customer id, no sale ids, not even the token itself. DELETE /invoices/{id}/share kills the link at once; sharing again afterwards hands out a different
token, and the old one answers 404 for good.
A credit note has a public link of its own, POST /credit-notes/{id}/share and
DELETE /credit-notes/{id}/share, with the same meaning, readable at
GET /public/credit-notes/{token}.
Void or credit
Both withdraw something about an invoice. Which one is right depends on whether the invoice was ever correct:
- Void an invoice that should never have existed: it was raised on the wrong sales, for
the wrong customer, or by mistake.
POST /invoices/{id}/voidwithdraws it entirely and frees its sales to be billed again, on a new invoice that takes the next number. A void invoice is never paid, never credited, and nothing is owed on it. - Credit an invoice that was correctly issued and has already been sent: the work was done and billed right, but some or all of it now needs to come off, for a refund, a cancellation or a goodwill adjustment. A credit note corrects it without touching the original, which the customer may already have a copy of.
Once you have sent an invoice to a customer, voiding it is rarely the right move: they are holding a document that says one thing, and voiding it makes your records say another with no link between them. A credit note names the invoice it corrects, so both documents keep telling the same story.
The two are not interchangeable once either has happened. An invoice that already carries a
credit note can no longer be voided: POST /invoices/{id}/void answers
invoice_not_voidable, because the credit note names that invoice and has a number of its
own in your records, so the invoice has to stay standing. Credit the rest of it instead,
which closes it as credited. The same holds the other way: a void invoice takes no credit
note (invoice_not_creditable), there being nothing owed on it to correct.
Issue a credit note
curl -X POST https://resellerhq.com/api/v1/invoices/inv_01K6XJ4Q8ZT3M9R5V2B7WDHNCA/credit-notes \
-H "Authorization: Bearer $RHQ_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 7c4d5e6f-1a2b-4c3d-9e8f-0a1b2c3d4e5f" \
-d '{
"reason": "Number cancelled after the invoice was sent",
"lines": [{ "saleId": "sal_01K6XJ4Q8ZT3M9R5V2B7WDHNCA" }]
}'- Credit either
lines, naming the invoice lines to credit (leave a line'samountout to credit everything still left on it, or give one to credit only part), oramount, a flat sum off the invoice's subtotal with no lines named — never both. reasonis required, and kept with the credit note for good.GET /invoices/{id}/creditableshows what is still left to credit: each line with itscreditedso far and what remainscreditable, and the invoice's ownsubtotal,taxandtotalstill uncredited.- A credit note has its own number,
CN-0001and up, in its own gapless sequence across your account, never shared with invoice numbers. - Its tax carries the same proportion as the lines it credits: crediting a line that is 40% of the invoice's subtotal credits 40% of its tax, whatever rate the invoice was taxed at. Crediting an invoice down to nothing always comes out to its exact total, to the penny, whatever the rounding on the way.
- A credit note can never exceed what is still left uncredited on the invoice, on a line or
across it: asking for more answers
credit_too_largewith acreditablefigure, what was left before tax. - A credit note is never edited and never deleted. To correct a mistaken credit note, issue an invoice again for the amount, or a second credit note if there is more to take off.
- A
voidinvoice, or one alreadycreditedin full, cannot take another credit note:invoice_not_creditable.
curl https://resellerhq.com/api/v1/credit-notes/crn_01K6XJ4Q8ZT3M9R5V2B7WDHNCA \
-H "Authorization: Bearer $RHQ_API_KEY"GET /invoices/{id}/credit-notes lists the credit notes against one invoice, newest first.
GET /credit-notes lists every credit note on the account, newest first, narrowed with
customerId, invoiceId or q, which looks in the credit note's number and the customer's
name and email.
What a credit note does to the invoice
- Crediting part of an open invoice lowers what is still owed on it: the invoice stays
open, andamountDuefalls by the credit'stotal. - Crediting an open invoice in full closes it as
credited, notpaid— nothing more is owed on it, and it was never marked paid.creditedAtrecords when that happened. - Crediting a paid invoice, in part or in full, stays
paid: the money already arrived, so there is nothing left to collect. What the credit comes to is instead money owed back to the customer, which shows up on their balance.
Every invoice carries credited, what its credit notes come to so far, tax included, 0
when it has none, and amountDue, what is still owed: total less credited on an open
invoice, and 0 on one that is paid, void or fully credited.
What a customer owes
GET /customers/{id}/balance answers with one row for each currency the customer has been
sold in:
| Field | What it holds |
|---|---|
uninvoiced | Sold but not on an invoice yet. Before tax, since tax is set on the invoice. Under zero when the customer is owed a credit |
open | On invoices waiting to be paid, overdue ones included, net of any credit notes against them |
overdue | The part of open whose due date has passed |
paid | On invoices you marked paid, net of any credit notes against them |
credited | What credit notes have taken off invoices that are not void, credited ones included |
Four webhook events follow an invoice: invoice.created, invoice.paid,
invoice.voided and credit_note.issued. The first three carry the invoice's id,
number, customerId, currency, total and status; credit_note.issued carries the
credit note's own id, number, invoiceId, invoiceNumber, customerId, currency,
subtotal, tax, total and reason.
Not built yet
- Paying out what a credit note leaves owed to a customer. The amount is recorded on their balance; settling it is a separate issue.
- Sending an invoice or a credit note to the customer, reminders, scheduled invoicing, and editing an open invoice.
- Collecting payment from your customers. An invoice is a record; you take the money.