---
title: "Create Credit Note"
method: POST
path: "/api/autopilot/invoices/{invoice_id}/credit-note"
tags: ["autopilot"]
---

# Create Credit Note

`POST /api/autopilot/invoices/{invoice_id}/credit-note`

## Request

- Base URL: `https://api.taxcompass.it` (the document declares no server; this is the origin it was published from)
- URL: `https://api.taxcompass.it/api/autopilot/invoices/{invoice_id}/credit-note`
- Auth: HTTP bearer

Open a TD04 **draft** crediting one issued invoice (AP-090).

Omitting ``lines`` credits the whole document; passing them credits part of
it. Either way the result is a draft: it is transmitted by ``POST
/invoices/{id}/issue`` like any other, which is what keeps one number
sequence per user and year and means a mistaken credit note can still be
deleted before it exists to SdI.

Two status codes, and the split matters:

* **404** — no invoice of that id for this caller. Unknown, somebody else's
  and soft-deleted stay indistinguishable, exactly as they do everywhere else
  on this router;
* **409** — the id names a real invoice of theirs that cannot be credited:
  still a draft or in flight, rejected by SdI (that is a re-issue, not a
  credit), already a credit note itself, or already credited up to its own
  total. The store's own message is passed through here rather than replaced
  with one of ours, because each of those four says something different about
  what to do next and the row is one the caller can already read — so naming
  the reason leaks nothing a ``GET`` would not.

Carries the AP-099 write limiter: it writes a row and reads two aggregates,
and it is the one write reachable against a document the caller can no longer
edit.

## Path parameters

- `invoice_id` string, uuid, required

## Request body

- CreditNoteCreate: ``POST /api/autopilot/invoices/{id}/credit-note`` body — all of it optional. ``lines`` **absent** credits the whole invoice: the store copies the original's own lines, so a full credit note cannot drift from the document it reverses. ``lines`` present makes it partial — a subset, or the same descriptions at reduced amounts — and the store refuses a total that would exceed what is still uncredited. Amounts stay positive here, as they are on the invoice: TD04 is what says the money goes the other way (see ``invoice_store``'s credit-note section), and ``InvoiceLine`` refuses a negative price anyway. ``[]`` is rejected up front rather than left to the store, because an empty list is a client bug and not a request to credit everything — that is what omitting the field means.
  - `lines` InvoiceLineInput[], nullable
    - `description` string, required
    - `unit_price` union, required
      - number
      - string
    - `quantity` union
      - number
      - string
    - `unit` string, nullable
  - `issue_date` string, date, nullable
  - `causale` string, nullable

## Response `201`

Successful Response

- InvoiceRead: One stored invoice as the API returns it (``payload`` decrypted). ``number`` is NULL until the issue transaction assigns it, so a draft is exactly the row whose ``status`` is ``draft`` and whose ``number`` is unset. ``total_amount`` is the imponibile the store computed from the lines, and ``bollo_applied`` the builder's verdict on it — both stored plaintext because the live estimate aggregates them in SQL. ``credit_note_of`` is what makes a TD04 legible on its own (AP-090): set, this row is a nota di credito and names the invoice it corrects; NULL on every ordinary document. It is the store's field and never a client's — a credit note is opened through its own route, not by writing this on a draft. ``client_label`` is the same kind of field for an ``imported`` row (AP-095): a pre-signup invoice names its customer as the text the user's own export carried, because there is no client record behind it and inventing one would put a half-filled customer — no address, no identifier — in the picker that issues real documents. It is NULL on every invoice that has a ``client_id``.
  - `client_id` string, uuid, nullable
  - `ateco` string, nullable
  - `issue_date` string, date, nullable
  - `due_date` string, date, nullable
  - `causale` string, nullable
  - `lines` InvoiceLineOutput[]
    - `description` string, required
    - `unit_price` string, required
    - `quantity` string
    - `unit` string, nullable
  - `id` string, uuid, required
  - `year` integer, required
  - `number` integer, nullable
  - `doc_type` string
  - `status` 'draft' | 'sending' | 'issued' | 'delivered' | 'not_delivered' | 'rejected' | 'error' | 'imported'
  - `total_amount` string
  - `bollo_applied` boolean
  - `credit_note_of` string, uuid, nullable
  - `client_label` string, nullable
  - `created_at` string, date-time, nullable
  - `updated_at` string, date-time, nullable
  - `payment` InvoicePayment: The payment side of one invoice — computed by ``services.invoice_payments``. Only ever computed on the server, from the ledger: a paid flag on the document would be a second copy of a fact the incassi table already holds, and the two would disagree the first time someone deleted a payment. * ``due`` — the invoice total minus the credit notes *issued* against it (a draft credit note has told the customer nothing yet, so it owes nothing less). * ``credited`` — that credit-note sum. * ``paid`` — net cash collected against this invoice: its own payments plus the refunds recorded against its credit notes (which are stored negative). * ``outstanding`` — what the customer still owes, never below zero. * ``overpaid_by`` — what arrived beyond ``due``, never below zero. * ``last_payment_date`` — the latest *incoming* payment (a refund is not a payment). * ``days_overdue`` — whole days past ``due_date`` while something is still owed; ``None`` when nothing is owed or the invoice has no due date.
    - `state` 'unpaid' | 'partly_paid' | 'paid' | 'overpaid' | 'credited', required
    - `due` string, required
    - `credited` string
    - `paid` string
    - `outstanding` string
    - `overpaid_by` string
    - `last_payment_date` string, date, nullable
    - `days_overdue` integer, nullable

## Other responses

- `409`: That invoice is not a document a credit note may correct
- `422`: Validation Error

---

[API](https://skmtc.dev/taxcompass/apis/taxcompass-api.md) · [All operations](https://skmtc.dev/taxcompass/apis/taxcompass-api/llms.txt) · [OpenAPI document](https://skmtc.dev/taxcompass/apis/taxcompass-api/revisions/fef5fc6a9b91?raw)
