> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://api-docs.papertracc.com/core/sales/invoices/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://api-docs.papertracc.com/_mcp/server. # Overview Invoice endpoints mounted at `/invoices`. ## Quantities and units `quantity` on a line item accepts fractional values, and a line can carry a `unit`. What is accepted depends on whether the line is tied to an inventory item through `sku`. | Line | `quantity` | `unit` | | ------------------------------------------------- | ------------------------------------------ | ------------------------------------------------------------------------- | | No `sku`, or an item with no selling unit | Any value above zero, to 4 decimal places. | The label you send, for example `hours`. Optional, at most 50 characters. | | `sku` of an item sold `EACH` | Whole numbers only. | Always `EACH`. A `unit` on the request is ignored. | | `sku` of an item sold by weight, volume or length | Any value above zero, to 4 decimal places. | Always the item's selling unit. A `unit` on the request is ignored. | Selling units are `EACH`, `G`, `KG`, `OZ`, `LB`, `ML`, `L`, `FL_OZ`, `CM`, `M`, `IN`, `FT` and `YD`. A `sku` that matches no inventory item is rejected with `404`. ```json { "detail": "Site survey", "currency_code": "NGN", "quantity": 1.5, "unit": "hours", "rate": 20000 } ``` Line items in invoice responses return `quantity` as a number, `unit` when the line has one, and the `sku` of the item the line is tied to. ## Promotions and loyalty points Send `incentives` on create or update to apply promotions and redeem loyalty points. You only name what to apply; every amount is calculated by the server. ```json { "incentives": { "promotions": [ { "promotion_id": "5b0e6c5e-3a55-4a0b-9a55-2f1f4f0c7d11", "code": "LAUNCH10" } ], "loyalty_points": 250 } } ``` | Field | Description | | --------------------------- | ------------------------------------------------------------------------------------------------------------ | | `promotions[].promotion_id` | The promotion to apply. Each promotion may appear once, and promotions that cannot be combined are rejected. | | `promotions[].code` | Required for code-based promotions. | | `promotions[].account_id` | Account the discount posts to. Defaults to the workspace's Sales Returns & Allowances account. | | `loyalty_points` | Points to redeem. The customer needs an active loyalty account with enough points. | Each promotion and the loyalty redemption come back as an entry in `adjustments`, marked by `promotion_id`, `code_used` or `loyalty_points`, and each line reports its share of the discount in `discount`. ## Updating adjustments and incentives On `PATCH /invoices/{id}` manual adjustments and incentives are replaced independently of each other. | Field | Omitted | Sent | | ------------- | ------------------------------------------------------------------------------------- | ----------------------------------------------------------------- | | `adjustments` | Manual adjustments are kept. | Replaces the manual adjustments. An empty array removes them all. | | `incentives` | Promotions and the loyalty redemption are kept, and recalculated if the items change. | Replaces them. An empty object removes them. | ```json { "adjustments": [] } ``` ## Payment terms An invoice falls due either on a fixed `due_date` or on a payment term. Send `payment_term_id` on create or update to apply a term from `/configs/payment-terms`. | Request | Result | | ----------------- | ------------------------------------------------------------------------------------------------------------ | | `payment_term_id` | The term is applied. It wins when `due_date` is also sent. | | `due_date` only | The invoice is due on that date and `payment_schedule` is null. | | Neither | The customer's default term is used, then the workspace default term, then the workspace's default due days. | When a term is applied, the response carries `payment_schedule` with each instalment's due date and amount and any early-payment discount, and `due_date` is the final due date. `is_overdue` follows the instalments: it is true once any instalment is past due and not fully covered by `total_paid`. On `PATCH /invoices/{id}`, `payment_term_id` rebuilds the schedule from that term. A `due_date` different from the current one replaces the term with that fixed date and clears `payment_schedule`. Changing the invoice date or the total recalculates the schedule from the term already on the invoice. ```json { "payment_term_id": "a4d2e9f1-6b3c-4e8a-b7d5-1c9f0e2a3b47" } ``` ## API Docs - Invoices [List Invoices](https://api-docs.papertracc.com/core/sales/invoices/list-invoices.md) - Invoices [Create Invoice](https://api-docs.papertracc.com/core/sales/invoices/create-invoice.md) - Invoices [Get Invoice](https://api-docs.papertracc.com/core/sales/invoices/get-invoice.md) - Invoices [Update Invoice](https://api-docs.papertracc.com/core/sales/invoices/update-invoice.md) - Invoices [Post Invoice](https://api-docs.papertracc.com/core/sales/invoices/post-invoice.md) - Invoices [Void Invoice](https://api-docs.papertracc.com/core/sales/invoices/void-invoice.md) - Invoices [Amend Invoice](https://api-docs.papertracc.com/core/sales/invoices/amend-invoice.md) - Invoices [Reject Invoice](https://api-docs.papertracc.com/core/sales/invoices/reject-invoice.md) - Invoices [Approve Invoice](https://api-docs.papertracc.com/core/sales/invoices/approve-invoice.md) - Invoices [Prepare Invoice](https://api-docs.papertracc.com/core/sales/invoices/prepare-invoice.md) ## OpenAPI Specification The raw OpenAPI 3.1 specification for this API is available at: - [OpenAPI JSON](https://api-docs.papertracc.com/openapi.json) - [OpenAPI YAML](https://api-docs.papertracc.com/openapi.yaml)