Skip to content
Knowledge ERP Docs

API Reference ↗
Sales

Customer Invoices & Payments

A customer invoice is a payment request issued to a customer — tracking line items, tax, and the full payment history from draft through paid or voided.

A customer invoice is the formal request for payment you send to a customer. It carries a list of line items (what was sold and for how much), an optional tax rate, and a running payment history that tracks every dollar received until the balance reaches zero. Invoices can be created manually or generated directly from a sales order, and they move through a clear status lifecycle so you always know what is outstanding, overdue, or closed.

Invoices and the payments against them are separate records — deleting or voiding an invoice soft-deletes it but the underlying payment records are retained for audit purposes.

Creating an invoice #

New invoices are created from Sales → Invoices → New Invoice. A handful of fields drive most of the behavior:

  • Customer — required. Selecting a customer enables the Sales Order field and pre-loads any payment terms set on that customer's record (Net 15, Net 30, etc.), which automatically computes the Due Date from the invoice date.
  • Sales Order — optional link to an existing sales order. Scoped to the selected customer.
  • Invoice # — auto-generated as INV-0001, INV-0002, and so on, but you can override it with your own numbering scheme.
  • Status — read-only on the form. It starts as Draft and moves as you send, record payments against, or void the invoice; see Invoice statuses below.
  • Invoice Date and Due Date — both optional; if you set an invoice date and the customer has payment terms, the due date is filled in automatically. The due date cannot fall before the invoice date — an invoice dated 14 August with a due date of 15 June would be two months overdue the moment it was saved, in the aging report and in that night's reminder run. The rule is applied on the form, in the API and in the MCP tools alike, in both directions: you cannot move the invoice date past a due date already on file either.
  • Tax Rate — choose from your configured tax rates. Changing the rate recalculates amount_due and tax_amount immediately using the current line-item subtotal.
  • Notes — free-form memo printed on or shared with the invoice.
  • Invoice Total — read-only display; always the sum of line-item totals plus tax. It is what the customer was billed, not what they still owe — the balance owed is shown as Balance Due on the invoice's view page, and stored as amount_due minus amount_paid.
  • Custom fields — any extra attributes defined for invoices appear at the bottom of the form.

Invoice statuses #

An invoice is always in exactly one of six statuses, shown as a badge in the list:

  • Draft — created but not yet sent; the default.
  • Sent — issued to the customer; can become Overdue automatically.
  • Partially Paid — at least one payment has been recorded, but the balance is not yet zero.
  • Paidamount_paid equals or exceeds amount_due; set automatically when the last payment clears the balance.
  • Overdue — a Sent or Partially Paid invoice whose due date is in the past. Status is checked and updated automatically.
  • Voided — cancelled; once voided the status is locked and no further payments can be applied.

The status is a consequence of what has happened to the invoice, not a field you fill in. Paid and Partially Paid are derived from the payments recorded against it and cannot be set by hand — in the app or through the API, which returns a 422 if you try. Use Record Payment, Mark as Sent, Mark as Overdue and Void on the invoice's own page. Voided is permanent.

This is why accounts receivable can never disagree with the money: the Invoice Aging report, the dashboard's Outstanding AR tile and the Accounts Receivable list all read the balance owed (amount_due − amount_paid), never the status badge. Only Draft invoices, which have not been issued, and Voided ones, which are no longer collectible, stand outside the ledger.

Mark as Sent only records a status — it does not email anything. It is there for an invoice you issued some other way. To actually send one, use Email Invoice below, which marks it as sent for you.

Emailing an invoice #

The Email Invoice button on the invoice's page sends the invoice to your customer without leaving the app. The email is branded as your business — the subject reads "Invoice INV-0020 from Tallgrass Outfitters" (your business name), the sender name and the header logo are yours, and replies go to your support address — with the invoice attached as the same PDF the Download PDF button produces. See Branding for what the sending address itself looks like.

The To address defaults to the customer's address and is always shown before anything is sent, so you can correct it. If the customer has no address on file, the button still opens and says so, with a link to the customer record where you can add one; you can still type an address to send this one now.

Sending a Draft invoice is what marks it Sent — and a sent invoice is what your customer can see and pay in the customer portal. Emailing an invoice that is already Sent, Partially Paid, Overdue or Paid just sends another copy and leaves the status alone. A Voided invoice cannot be emailed.

The send happens in the background. You get a notification in the app when it has actually gone out — or one that says why it could not. An address that has hard-bounced or reported a previous message as spam is refused before anything is sent, rather than being quietly dropped.

Emailing an invoice needs the Email sales documents permission, which is separate from editing invoices — so a salesperson can chase payment on an invoice they are not allowed to change. See Users, Roles & Permissions.

Every send is recorded on the invoice's Change Log and on the customer's email history, so did we send it, when, and to whom is always answerable.

Line items #

The Line Items tab on an invoice's page is where you add, edit, and remove what is being charged. Each line item carries:

  • Description — a free-text label for the line (required if no Product is chosen).
  • Product — optional link to an Product. When set, the Product's name appears in the description placeholder.
  • Quantity — numeric, supports decimals (e.g. 2.5 hours, 0.75 lb).
  • Unit Price — entered in dollars in the UI; stored and returned in cents over the API (5000 = $50.00).
  • Notes — per-line memo.

The line total is quantity × unit_price. Adding or removing a line item triggers an immediate recalculation of the invoice's amount_due and tax_amount.

Recording payments #

Record a payment right from the invoice's view page with the Record Payment action — enter the amount, payment date, method, an optional reference number, and notes. The Record Payment button is only available once the invoice has been sent and while it still owes something (it is hidden on Draft and Voided invoices, and on any invoice whose balance is zero). The Payment History tab then lists every payment received against the invoice, showing each one's date, amount, method, reference number, and any notes. That tab is read-only — you add payments through the Record Payment button (or the API, see below), not by editing the list.

Payment methods are: Cash, Check, Credit Card, Bank Transfer, and Other. A payment's amount must not exceed the invoice's remaining balance. Over-paying is refused rather than trimmed to fit — the form names the balance and keeps your figure on screen, and the API returns a 422 validation error — so a payment is never recorded for an amount other than the one you entered. When the balance hits zero the invoice status moves to Paid automatically.

Taking a payment larger than the balance, and holding the surplus as a credit against the customer's next invoice, is not something the app does yet. Record what settles this invoice and raise a credit memo for the rest.

Amount remaining is amount_due − amount_paid. The API exposes both fields as integers in cents so you can always compute the outstanding balance without rounding surprises.

The invoice list #

The invoice list (Sales → Invoices) shows each invoice's Invoice #, Customer, linked SO #, Status badge, Invoice Date, Due Date, and Amount. Sort by any column and search by invoice number or customer name.

Filters:

  • Status — one or more of the statuses above.
  • Customer — searchable, for everything owed by one account.
  • Invoice dateDated from / Dated until, which is how you ask for "everything dated in August" at month end.
  • Unpaid only — invoices with a balance still owed. This reads the balance, not the status badge, so nothing drops out of it because a field says Paid.
  • Trashed — soft-deleted records.

Deleting an invoice, and why you usually cannot #

A draft can be deleted. An issued invoice cannot.

Once an invoice has been sent, deleting it does not undo it: the customer still has it, their bookkeeper has still entered it, and the payment that arrives next week still quotes its number. What deletion would remove is your side of the story — the amounts, the payment history, the change log, and the gap left in your invoice numbering.

So an invoice in any status other than Draft refuses to be deleted, in the app and through the API, whatever permissions you hold. Void it instead: the number and the audit trail survive, the invoice stops being collectible, and anything it billed goes back onto the sales order to be invoiced again. If that order had already closed, voiding re-opens it — see When a closed order re-opens — so the order you have just given work back to is one you can still find.

This is also why Void matters more than it looks. On the invoice page it stays visible with a padlock when you do not have permission to use it, rather than disappearing — because it is now the only way to take an issued invoice back.

Chasing what is owed #

The Accounts Receivable list (Finance → Accounts Receivable) is the invoice list scoped to invoices with a balance. Select any number of rows and:

  • Send Reminder — emails each overdue invoice in the selection to its customer, using the same reminder the nightly job sends. Invoices that are not overdue, are settled, or have no email address on file are skipped, and the confirmation tells you how many.
  • Email Statement — sends one statement per customer, covering their whole account, with a PDF attached. Not one email per invoice: three ticked invoices for the same customer produce one statement.
  • Download PDFs — every selected invoice as a PDF, in a single zip.

There is deliberately no bulk delete here. Nothing in this list is a draft, and an issued invoice cannot be deleted at all.

What lives on the invoice page #

Open any invoice to find:

  • Details — the core fields (customer, dates, tax rate, notes, amount due).
  • Line Items — add, edit, or remove lines; totals recalculate live.
  • Payment History — a read-only log of every payment received.
  • Attachments — upload a PDF copy or supporting documents.
  • Change history — a full audit trail of every edit.

Relationship to sales orders and other modules #

An invoice is often the downstream output of a sales order — the sales order tracks what was committed, and the invoice requests payment. The sales_order_id field on an invoice makes this link explicit. Separately, rental agreements generate their periodic invoices through the billing cycle, which also land here as standard customer invoices. Credit memos are the mechanism for issuing refunds or adjustments against a paid invoice.

Doing it from the API #

# Create an invoice for a customer
curl -X POST "https://your-domain.com/api/v1/customer-invoices" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"customer_id": "<id>", "invoice_date": "2026-06-02", "status": "draft", "tax_rate_id": "<id>"}'

# Add a line item (unit_price in cents)
curl -X POST "https://your-domain.com/api/v1/customer-invoice-items" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"customer_invoice_id": "<id>", "description": "Consulting", "quantity": 2, "unit_price": 15000}'

# Record a payment (amount in cents)
curl -X POST "https://your-domain.com/api/v1/customer-payments" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"customer_invoice_id": "<id>", "amount": 30000, "payment_date": "2026-06-02", "payment_method": "bank_transfer"}'

# Email the invoice to its customer. Omit "to" to use the customer's own
# address. Returns 202 — the send is queued, and a draft invoice becomes
# "sent" once the mail has gone out.
curl -X POST "https://your-domain.com/api/v1/customer-invoices/<id>/email" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"to": "ap@customer.com", "message": "Invoice attached — net 30."}'

All money fields — amount_due, amount_paid, tax_amount, unit_price, and payment amount — are integers in cents over the API (30000 = $300.00). The UI converts them to dollars automatically.