---
title: "Update a line item on an invoice"
method: PATCH
path: "/public-api/v1/invoices/{invoice_id}/invoice_items/{id}"
tags: ["Invoices"]
---

# Update a line item on an invoice

`PATCH /public-api/v1/invoices/{invoice_id}/invoice_items/{id}`

## Request

- Base URL: `https://app.hellobonsai.com`
- URL: `https://app.hellobonsai.com/public-api/v1/invoices/{invoice_id}/invoice_items/{id}`
- Auth: one of:
  - OAuth 2
    - Authorization code: `https://app.hellobonsai.com/oauth/authorize`
    - Token URL: `https://app.hellobonsai.com/oauth/token`
  - HTTP bearer

Updates one line item and recalculates the invoice total. Every field is
optional, and anything you leave out keeps its current value.

Only invoices that have not been paid for work here. An invoice that is
paid, partially paid, or has a payment in progress is closed to changes
and returns `403`.

A line item built from a timesheet takes its `amount`, `rate` and
`unit_type` from the time entries behind it. Sending a different value
for one of those returns `422`. Sending the stored value is accepted, so
a full-representation update still works.

## Request body

- object
  - `invoice_item` object, required
    - `name` string: Line item name, as the client will see it. Cannot be blank.
    - `description` string: Longer description shown beneath the name.
    - `amount` string: Quantity billed, as a decimal string. Cannot be negative.
    - `rate` string: Price per unit, as a decimal string. Cannot be negative.
    - `unit_type` 'flat' | 'per_hour' | 'per_day' | 'per_item' | 'per_word' | 'per_week' | 'per_month' | 'per_year' | 'per_quarter': What the rate is charged per.

## Response `200`

The line item was updated and the invoice total recalculated.

- object
  - `data` InvoiceItem, required: A single line on an invoice: what you are billing for, how much of it, and at what rate.
    - `id` integer, required: Unique identifier for the line item.
    - `name` string, nullable, required: Line item name, as it appears on the invoice.
    - `description` string, nullable, required: Longer description shown beneath the name, or `null`.
    - `amount` string, nullable, required: Quantity billed, as a decimal string.
    - `rate` string, nullable, required: Price per unit, as a decimal string in the invoice currency.
    - `unit_type` 'flat' | 'per_hour' | 'per_day' | 'per_item' | 'per_word' | 'per_week' | 'per_month' | 'per_year' | 'per_quarter' | 'null', nullable, required: What the rate is charged per. Defaults to `flat`.
    - `total` string, required: `amount` multiplied by `rate`, rounded, as a decimal string.
  - `meta` Meta, required: Metadata returned alongside every single-resource response.
    - `request_id` string, required: Identifier for this request. Quote it when contacting support about a specific call.

## Other responses

- `400`: The request body is missing its `invoice_item` wrapper.
- `401`: The access token is missing, expired or invalid.
- `403`: This token is not allowed to edit invoices, or the invoice is paid, partially paid, or has a payment in progress and can no longer be changed.
- `404`: No such invoice or line item that this token can see.
- `422`: The line item could not be saved — `name` is blank, `unit_type` is not one of the listed values, or `amount` or `rate` is negative.
- `429`: Rate limit exceeded. Wait at least `Retry-After` seconds before trying again.

---

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