Credit notes
A credit note is the accounting document that reverses or adjusts a previously-issued invoice. Finalised invoices are immutable, so every adjustment - refund, service-credit, billing correction, downgrade - flows through a credit note. Credit notes carry their own number, lifecycle, and tax mirroring so the net VAT position over an (invoice, credit_note) pair is exactly zero.
Credit notes can be standalone too - invoice_id is optional. A goodwill credit issued to a customer with no specific invoice to attribute it to (a wallet promo, a manual adjustment) is just a credit note with invoice_id: null.
Lifecycle
Code
| Status | Meaning |
|---|---|
draft | Mutable - lines can be added/removed; not yet a numbered document |
issued | Locked, numbered (credit_note_number assigned), customer-visible. amount_remaining = total |
partially_applied | Some of the credit has been applied to one or more invoices; amount_remaining > 0 still |
applied | Fully consumed (amount_remaining == 0). Terminal |
void | Cancelled before full application. Terminal |
Transitions are state-machine enforced - invalid transitions return 409 INVALID_TRANSITION. The two-step issue → apply flow exists so finance can review issued credit notes before money or wallet credit moves; there's no auto-apply.
Webhook events: credit_note.created, credit_note.issued, credit_note.applied, credit_note.voided.
Reason codes
reason_code is a typed enum that drives reporting and downstream behaviour. Pair it with reason (a free-form human-readable string).
| Code | Use for |
|---|---|
REFUND | Customer-initiated refund - money flows back through the original gateway when applied |
VOID | Reversing an issued-in-error invoice |
BILLING_ERROR | Mistake in pricing, quantity, or tax that needs correction |
OVERPAYMENT | Customer paid more than owed - credit the surplus back |
CANCELLATION | Subscription cancelled mid-period; credit the unused portion |
DOWNGRADE | Mid-cycle downgrade; credit the prepaid difference |
ITEM_REMOVAL | Item removed from a subscription; credit the prepaid balance for that item |
PROMOTIONAL_CREDIT | A promotion's wallet_credit effect is applied as a credit note |
GOODWILL | Discretionary customer-service credit - no specific invoice to attribute it to |
OTHER | Anything else - pair with a clear reason string |
Anatomy
| Field | Notes |
|---|---|
customer_id | The customer the credit belongs to |
invoice_id | Optional - when set, the credit is attributed to that invoice for reporting (and the typical apply target). When null, this is a standalone credit |
credit_note_number | Assigned at issue from the org's number sequence; null while draft |
currency | The credit's currency. When applying to an invoice, currencies must match |
subtotal, tax_total, total | Locked at issue |
amount_applied / amount_remaining | Maintained as applications post - amount_remaining = total - amount_applied. Drives partially_applied vs applied status |
reason_code, reason | Typed enum + free-form string |
lines | The line set; structure mirrors InvoiceLine (description, quantity, unit_price, tax_rate, tax_type, period_start/end) |
issued_at, voided_at | Lifecycle timestamps |
Creating
Credit notes always start as draft. Lines can be tied to specific invoice lines via invoice_line_id (recommended - preserves the audit chain) or stand alone (product_id only):
Code
tax_rate is required per line so the credit mirrors the original line's VAT exactly - the engine doesn't infer it from the referenced invoice line. Same goes for tax_type when the credit needs to mirror a non-default category.
Issuing
Code
Locks the credit note, assigns credit_note_number, sets amount_remaining = total, and emits credit_note.issued. After issue, lines can no longer be edited.
Applying
Application is a separate, explicit step - issued credit notes don't auto-apply.
Code
Each application:
- Reduces the target invoice's
amount_duebyamount - Reduces the credit note's
amount_remainingby the same - Writes a
CreditNoteApplicationrow (auditable: which credit, which invoice, how much, when) - Advances the credit-note status to
partially_appliedorappliedbased on remaining
Apply the same credit note multiple times against different invoices until amount_remaining == 0. Each call must be against an invoice in the same currency.
GET /v1/credit-notes/{id}/applications returns the application history.
Customer credit balance
GET /v1/customers/{id}/credit-balance returns the customer's total amount_remaining across all of their issued credit notes - useful for showing a "credit available" widget on the customer's account page.
Voiding
Code
Allowed only from draft, issued, or partially_applied. Voiding a partially_applied credit doesn't reverse the already-posted applications - they stay on the audit trail; voiding only stops further applications. Use a fresh credit note (or rebill the affected invoice) if you need to undo a posted application.
Tax mirroring
Each credit note line carries its own tax_rate, tax_type, tax_category_code, and tax_exemption_reason. The convention is to mirror the original invoice line's tax treatment so the net VAT position over the (invoice, credit_note) pair is exactly zero - your tax export adds and subtracts the same amounts and the auditor sees a clean trail. The credit note doesn't auto-mirror; you set the values on creation, typically copying from the referenced invoice_line_id.
Endpoints
All Credit Notes endpoints - covers list / get / create (draft), issue, apply, void, and the per-customer credit-balance endpoint.
Related
- Invoices - the documents credit notes adjust
- Wallets - for "credit to wallet" flows, post a wallet credit directly rather than issuing a credit note (credit notes are tied to invoices for accounting purposes; wallets are a separate balance ledger)
- Promotions -
promotional_creditreason code is set when a promotion'swallet_crediteffect produces a credit note - Taxes - the tax categories the lines mirror