Creating invoices
How invoices are generated, referenced, and rendered
Overview
An invoice is created by selecting one or more uninvoiced ledger entries on a single policy. Root creates the invoice, attaches a line item per ledger entry, allocates a reference, computes the total, queues the PDF, and moves the invoice to pending, all in a single atomic operation.
There are two ways to trigger this:
- Via the API — call Create an invoice with the policy ID and the ledger entry IDs to bundle. This is the path used by the dashboard's "New invoice" flow.
- Via a lifecycle hook — a product module can call the
generate_invoicelifecycle hook to raise invoices automatically as part of its own billing logic. The platform does not infer eligibility or run a billing schedule for you; your product module decides which ledger entries to bundle and when.
Find what is available to invoiceUse List uninvoiced ledger entries to see which ledger entries on a policy have not yet been placed on an invoice. Each ledger entry can appear on at most one invoice.
What you supply
| Field | Required | Notes |
|---|---|---|
type | Yes | One of proforma, receipted, or credit_note. |
ledger_entry_ids | Yes | At least one. Each must belong to the policy and must not already be invoiced. |
tax_point_date | Yes | The calendar date that renders on the document. |
reference | No | Your own reference. Must be unique within your organization. If omitted, Root generates one. |
original_invoice_id | No | Only for credit notes. See Credit notes and refunds. |
line_item_refund_mappings | No | Only for credit notes. Maps original lines to their reversing lines. |
The invoice's currency is inherited from the policy. You do not supply it.
How the total is computed
The invoice total is the sum of the amounts of the referenced ledger entries. Like all monetary amounts on the Root API, it is an integer amount in cents.
For a credit_note, the bundled ledger entries must sum to a negative total, because a credit note reduces what is owed.
References
A reference is a human-readable identifier that is unique per organization.
- Supplied by you. Pass
referencein the request. If it collides with an existing reference in your organization, the request is rejected with a validation error. - Generated by Root. Omit
reference, and Root allocates one of the formINV-XXXXXXXX(the prefixINV-followed by eight uppercase hexadecimal characters). Generation retries automatically on the rare collision; if it cannot find a free value, the request fails and asks you to supply an explicit reference.
A reference is only allocated when an invoice is finalised. An open draft has no reference yet.
Document rendering
After an invoice is finalised, its PDF is rendered asynchronously, after the invoice has been committed. The render uses the invoice template registered on the policy's product module:
- If the product module has no invoice template configured, no PDF is produced. The invoice is still valid.
- Otherwise, Root builds a render context from the invoice, its policy and policyholder, and its line items, renders your template to HTML, and produces a PDF.
- The resulting file is stored and the invoice's
document_file_idis set.
document_file_idappears after creationBecause rendering happens after the invoice is committed, the
document_file_idis not present in the response to the create call. Re-fetch the invoice with Retrieve an invoice to get the file reference once rendering has completed. Theinvoice_createdevent also omits the file reference for the same reason.
Your template branches on invoice.type to choose between proforma, receipted, and credit-note layouts.
Validation rules
A create call is rejected if any of the following hold:
- Invoicing is not enabled for the organization (
invoicing_not_enabled). - No ledger entries are supplied.
- The same ledger entry is supplied more than once.
- A ledger entry does not belong to the policy.
- A ledger entry is already attached to another invoice (
ledger entries already invoiced). - The reference you supplied already exists in your organization.
- The invoice is a
credit_noteand its total is not negative. - The invoice is a
credit_noteand nooriginal_invoice_idis supplied, ororiginal_invoice_idis supplied on a non-credit-note type.
See Create an invoice for the full request and response, and Errors below for the codes.
Error codes
| Code | Meaning |
|---|---|
invoicing_not_enabled | Invoicing is not enabled for the organization. |
invoice_validation_error | The request failed a validation rule (see above). |
invoice_not_found | The invoice does not exist, or the caller cannot access its policy. |
illegal_invoice_transition | A status change was attempted that the lifecycle does not allow. |
concurrent_invoice_modification | Another writer changed the invoice before this transition could be applied. |
invoice_invariant_error | An internal consistency check failed; the operation was rolled back. |
Updated 2 days ago