---
title: "Delete or cancel an invoice"
method: DELETE
path: "/public-api/v1/invoices/{id}"
tags: ["Invoices"]
---

# Delete or cancel an invoice

`DELETE /public-api/v1/invoices/{id}`

## Request

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

Deletes a draft, or cancels an invoice that has been sent or is scheduled
to send. Either way it stops appearing in `GET /invoices`, and you get it
back one last time with `status: deleted`. Which of the two happens depends
on the invoice's `status` when you call:

- `drafted` invoices are deleted.
- `scheduled`, `outstanding` and `overdue` invoices are cancelled. The app
  keeps the invoice number and its history. A scheduled invoice is never
  sent, and for a sent one the payment link your client has stops
  accepting payment.

Hours and expenses billed on the invoice go back to unbilled so they can
be invoiced again. Nothing you logged is deleted.

Deleting an older invoice of a recurring series or subscription leaves the
series running. The most recent one carries the schedule, so it is
refused while the series is live: stop the recurrence first with
`DELETE /invoices/{invoice_id}/recurrence`, then delete it.

The call returns `422` and changes nothing when the invoice is `paid`, has
a payment or refund in progress, has payments recorded against it, is the
deposit a contract or proposal is waiting on, is the most recent invoice
of a live series, or is part of an invoice bundle. The error says which,
and what to do instead. Most of these have to be handled in the Bonsai
app.

An invoice that has already been deleted returns `404`, like any id this
token cannot see. There is no undo through the API.

## Path parameters

- `id` integer, required

## Response `200`

The invoice was deleted or cancelled. `data` is the invoice as it was removed, with `status: deleted`.

- object
  - `data` Invoice, required: A bill you send to a client for work on one project, with its line items.
    - `id` integer, required: Unique identifier for the invoice.
    - `invoice_number` string, nullable, required: Human-readable invoice reference, unique within your account. The list endpoint accepts it as `filter[invoice_number]`.
    - `title` string, nullable, required: Invoice title shown to the client.
    - `currency` string, required: Three-letter ISO 4217 currency code every amount on the invoice is expressed in.
    - `issued_date` string, date, nullable, required: Issue date printed on the invoice. Set when the invoice is created, so a draft has one too; `sent_date` says whether the client has received it.
    - `due_date` string, date, nullable, required: Date payment is due, or `null` when the invoice is payable on receipt.
    - `sent_date` string, date-time, nullable, required: When the invoice was sent to the client, by email or as a shared link, or `null` while it has not been sent. A `drafted` or `scheduled` invoice has none.
    - `project_id` integer, nullable, required: Id of the project the invoice bills.
    - `client_email` string, nullable, required: Email address the invoice is addressed to, captured from the client contact when the invoice was created.
    - `public_url_token` string, nullable, required: Token in the invoice's client-facing URL. Anyone holding that link can view and pay the invoice, so treat this value as a secret.
    - `created_at` string, date-time, required: When the invoice was created.
    - `total_amount` string, required: What the client owes, as a decimal string, after any discount and tax.
    - `discount_amount` string, nullable, required: Discount taken off the subtotal, as a decimal string, or `null` when there is none.
    - `status` 'new' | 'drafted' | 'scheduled' | 'outstanding' | 'overdue' | 'pending' | 'paid' | 'deleted', required: Where the invoice is in its lifecycle: - `new`, `drafted` — not sent to the client yet. - `scheduled` — queued to send automatically on a future date. - `outstanding` — sent and awaiting payment. - `overdue` — sent, unpaid and past `due_date`. - `pending` — a payment has started but has not settled. - `paid` — paid in full. - `deleted` — the invoice has been deleted. An invoice that is `paid` or `pending` can no longer be edited, and neither can its line items.
    - `due_date_option` 'upon_receipt' | 'after_x_days' | 'custom' | 'null', nullable, required: How `due_date` was arrived at: `upon_receipt`, `after_x_days` (a fixed number of days after the issue date) or `custom` (an explicit date).
    - `company_id` integer, nullable, required: Id of the company being invoiced, or `null` when the invoice is addressed to a client that is not a company record.
    - `client_name` string, nullable, required: Name the invoice is addressed to.
    - `subtotal` string, nullable, required: Sum of every line item, before discount and tax, as a decimal string.
    - `tax_amount` string, nullable, required: Total tax on the invoice, as a decimal string, whether it is charged on the whole invoice or per line item.
    - `kind` 'single' | 'recurring' | 'subscription' | 'bundled', required: How the invoice repeats: - `single` — a one-off invoice. Scheduling one to send later does not make it recurring; `status` reports that as `scheduled`. - `recurring` — reissued on `repeat_interval` until you stop it or `repeat_finish_date` arrives. - `subscription` — recurring, and charged automatically to the card the client has on file. - `bundled` — one of several invoices grouped to be sent and paid together. `bundled` is read-only: bundles are assembled in the Bonsai app from invoices that already exist, so it cannot be passed when creating one.
    - `repeat_interval` 'weekly' | 'every two weeks' | 'every four weeks' | 'monthly' | 'every two months' | 'quarterly' | 'every six months' | 'annually' | 'null', nullable, required: How often a `recurring` or `subscription` invoice is reissued, or `null` for a one-off. It records the cadence an invoice was issued under rather than whether its series still runs: stopping a series keeps the interval on every invoice so the series can be started again, including one stopped before it repeated, which then reads `kind` `single`. Only the last invoice a series issues on `repeat_finish_date` comes back `null`. Use `recurrence_active` to tell a running series from a stopped or finished one.
    - `repeat_finish_date` string, date, nullable, required: Date the series stops reissuing, or `null` for a one-off or a series that runs until you stop it. Only the newest invoice of a series carries it: each repeat hands the date on to the invoice it creates, so earlier invoices read `null` even when the series has an end. When the date falls a whole number of `repeat_interval`s after the issue date, the final invoice is issued on it; otherwise the series ends with the last repeat before it. Stopping a series keeps the date so the series can be started again.
    - `series_id` integer, nullable, required: Id of the first invoice of the series this one belongs to, the same for every invoice in it, so you can group them. `null` for an invoice that is not part of a series.
    - `recurrence_active` boolean, required: Whether the series this invoice belongs to still reissues. Unlike `kind` and `repeat_interval`, which describe the invoice, this describes the series, so every invoice in it reports the same answer and an already-issued one turns `false` once the series is stopped. It is `true` exactly when `DELETE /invoices/{invoice_id}/recurrence` has something to stop.
    - `url` string, required: Absolute link to the invoice in the Bonsai app. This is the contractor-facing view, not the client payment page — for that, use `public_url_token`.
    - `invoice_items` InvoiceItem[], required: The invoice's line items, in the order they appear on it.
      - `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

- `401`: The access token is missing, expired or invalid.
- `403`: This token is not allowed to delete invoices.
- `404`: No invoice with that id that this token can see, or the invoice has already been deleted.
- `422`: Nothing was deleted. The error message says why and what to do instead.
- `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)
