Credit notes and refunds
How to reverse a finalised invoice
Overview
Finalised invoices are immutable. To refund or correct one, you do not edit it: you raise a new credit note invoice against it. The credit note is a credit_note-type invoice with a negative total, linked back to the original through original_invoice_id. Creating it moves the original invoice to refunded and fires the invoice_refunded event.
This keeps a complete, auditable trail: the original invoice and the credit note both remain on record, and the relationship between them is explicit.
How a refund works
- Raise new credit ledger entries on the policy for the amounts being refunded (and, where applicable, any admin-fee or tax debits that go with the refund).
- Call Create an invoice with:
typeset tocredit_note,ledger_entry_idsreferencing the new credit entries (their amounts must sum to a negative total),original_invoice_idset to the invoice being refunded,- optionally,
line_item_refund_mappingsto record which original line each credit line reverses.
- Root creates the credit note, finalises it, and atomically moves the original invoice to
refunded, firinginvoice_refundedwith the original and the refund invoice IDs. - The credit note renders through your template's
credit_notelayout.
A credit note must be a true creditThe bundled ledger entries on a
credit_notemust sum to a negative total. A credit note is always finalised on creation; it cannot be created as anopendraft.
What can be refunded
The original invoice must be in a refundable status: pending, sent, or paid. You cannot raise a credit note against an invoice that is open, already void, or already refunded.
The credit note must be on the same policy as the original invoice.
Per-line refunds
To record that specific lines were reversed (rather than the whole invoice), supply line_item_refund_mappings. Each mapping links:
original_line_item_id— a line item on the original invoice, torefund_ledger_entry_id— the ledger entry on the credit note that reverses it.
Root validates these mappings and sets refunded_by_line_item_id on each original line so dashboards and templates can show "this line was reversed by line X on credit note Y."
Mappings must be 1:1Within a single credit note, no original line item may be mapped twice, and no refund ledger entry may be mapped twice. Duplicate mappings are rejected with a validation error. Each
refund_ledger_entry_idmust be one of the ledger entries on the credit note, and eachoriginal_line_item_idmust be a line on the original invoice.
Result
- The credit note exists as its own invoice, with
original_invoice_idpointing at the refunded invoice. - The original invoice's status becomes
refunded(terminal). invoice_refundedfires on the policy, carrying the originalinvoice_idand therefund_invoice_id.
See Invoice events for the event payloads.
Updated 2 days ago