---
title: "List invoices"
method: GET
path: "/public-api/v1/invoices"
tags: ["Invoices"]
---

# List invoices

`GET /public-api/v1/invoices`

## Request

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

Lists your invoices, newest first, a page at a time. Each one arrives with
its line items.

## Filtering

- `filter[invoice_number]` — one or more invoice numbers. This is how you
  turn a number your client quoted you into an invoice id.
- `filter[project_id]` — one or more project ids.
- `filter[company_id]` — one or more client company ids.

## Query parameters

- `page[number]` integer
- `page[size]` integer
- `filter[invoice_number]` string
- `filter[project_id]` string
- `filter[company_id]` string

## Response `200`

A page of invoices, newest first, each with its line items.

- object
  - `data` Invoice[], required
    - `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` PaginatedMeta, required: Metadata returned alongside every list response.
    - `request_id` string, required: Identifier for this request. Quote it when contacting support about a specific call.
    - `pagination` Pagination, required: Where the returned page sits in the full result set.
      - `page` integer, required: The page that was returned.
      - `page_size` integer, required: How many records this page can hold.
      - `has_more` boolean, required: Whether at least one more page follows this one. Keep incrementing `page[number]` while this is `true`.

## Other responses

- `400`: A filter key is unknown, an id filter is not an integer, or a pagination parameter is not an integer.
- `401`: The access token is missing, expired or invalid.
- `403`: This token is not allowed to see invoices.
- `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)
