Update an invoice

Operation ID: updateInvoice

Group: Accounting › Invoices

Open in the interactive reference

PATCH /accounting/invoices/{id}

Retry-safe: A write that accepts Idempotency-Key: repeating a request with the same key replays the stored answer instead of executing twice.

Updates an invoice with the fields you send. A field you leave out keeps its current value.

Use the invoice's id, not its invoiceNumber.

You can change invoiceDate, paymentTerm, customerMessage, and purchaseOrderOverride on the invoice, and description and dutiesAndCustomsAmount on each line. Amounts, tax, the set of lines, deliveryStatus, the addresses and invoiceEmail can't be changed.

To clear purchaseOrderOverride, send an empty string, and the sales order's PO references apply again. An empty paymentTerm, customerMessage, or invoiceDate is ignored, so customerMessage can't be cleared.

Each item in updateLines changes one existing line of this invoice, identified by its id. Lines you leave out don't change, and you can't add or remove lines.

The response contains only the invoice's id. To see the recalculated totals, use GET accounting/invoices/:id.

Parameters

Name In Type Required Description
Api-Version header string · v1 yes The API version this request targets, named by its public identifier. Required on every request; omitting it, or naming a version this company does not have, is answered with 400. This document describes version v1.
Idempotency-Key header string no An opaque caller-chosen string (1-255 characters) that makes this request safe to retry. Repeating the same key with an identical request body replays the original response instead of re-executing - but only once that original request succeeded; a failed attempt re-executes on retry. Repeating the key with a different body is answered with 422. A key still in flight is answered with 409 - as is a key whose original request was interrupted before it finished, for a few minutes afterwards, until that attempt is presumed dead. A completed response stays replayable for 24 hours. The key is scoped to the caller, not to the action: reusing it for a different action is answered with 409 or 422 rather than treated independently. On read actions this header is ignored. On write actions that cannot offer the guarantee it is answered with 400 IDEMPOTENCY_NOT_SUPPORTED rather than silently ignored.
id path string yes The unique identifier of the invoice you want to update.

Request body

Required, application/json: updateInvoiceInput.

Field Type Required Description
invoiceDate date no The date the invoice was issued. Format YYYY-MM-DD. Omit to leave unchanged. Changing it re-derives the due date from the payment term and moves which tax period the invoice falls in. Example: "2026-09-05".
paymentTerm string no The payment term governing when payment falls due, as the term's configured code. Omit to leave unchanged. An empty string is ignored rather than clearing it. This field is write-only: the read endpoints publish the resolved paymentTermDays instead of the term itself.
customerMessage string no A free-form message printed on the invoice for the customer. Omit to leave unchanged. It cannot be cleared through this endpoint. An empty string is ignored, not stored. Example: "Thank you for your business.".
purchaseOrderOverride string no A manually entered PO number that overrides the references derived from the sales order. Omit to leave unchanged. Unlike the other fields here, pass an empty string to clear it and fall back to the sales order's own PO references.
updateLines array<object> no The line edits to apply, each addressing one existing line of this invoice by its id. Omit to leave the lines untouched. Lines cannot be added or removed here, because the set of lines comes from the sales order's invoice plan. Example: [{"id":"5e2a7c81-9d34-4b06-8f19-2c7e4a0d3b58","description":"Platform subscription — September 2026","dutiesAndCustomsAmount":"45.00"}].
updateLines[].id string yes The unique identifier for the invoice line to edit, as returned by GET accounting/invoices/:id. It must be a line of this invoice, and may appear at most once in the request.
updateLines[].description string no The new line description, as shown to the customer. Omit to leave unchanged.
updateLines[].dutiesAndCustomsAmount decimal no The duties and customs charged on this line, in the invoice's currency. Requires the entity's Duties and Customs feature to be enabled, and setting it recalculates the invoice's journal entry. Omit to leave unchanged.
{
  "invoiceDate": "2026-09-05",
  "paymentTerm": "<paymentTerm>",
  "customerMessage": "Thank you for your business.",
  "purchaseOrderOverride": "<purchaseOrderOverride>",
  "updateLines": [
    {
      "id": "5e2a7c81-9d34-4b06-8f19-2c7e4a0d3b58",
      "description": "Platform subscription — September 2026",
      "dutiesAndCustomsAmount": "45.00"
    }
  ]
}

Response

200 Success

Under data (updateInvoiceOutput):

Field Type Required Description
id string yes The unique identifier for the updated invoice. Read the invoice back with GET accounting/invoices/:id to see the recalculated totals. Example: "f3b9c1d4-2a68-4e07-8c15-9d0b7e5a3f62".
{
  "data": {
    "id": "f3b9c1d4-2a68-4e07-8c15-9d0b7e5a3f62"
  },
  "diagnostics": [
    {
      "code": "<code>",
      "message": "<message>",
      "severity": "error",
      "path": [
        "<path>"
      ],
      "details": "<details>"
    }
  ]
}

Response headers

Errors

Code Status
INVOICE_NOT_FOUND 400
LINE_NOT_ON_INVOICE 400
DUPLICATE_LINE 400
IDEMPOTENCY_KEY_CONFLICT 409
IDEMPOTENCY_PAYLOAD_MISMATCH 422

Statuses