---
title: "List projects"
method: GET
path: "/public-api/v1/projects"
tags: ["Projects"]
---

# List projects

`GET /public-api/v1/projects`

## Request

- Base URL: `https://app.hellobonsai.com`
- URL: `https://app.hellobonsai.com/public-api/v1/projects`
- 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 projects, a page at a time. Only active projects come back
unless you ask for others with `filter[status]`.

## Filtering

- `filter[title]` — searches project titles, matching from the start of
  any word and ignoring case.
- `filter[public_url_token]` — one or more URL tokens, for looking up
  projects you already hold a client link for.
- `filter[board_group_id]` — one or more pipeline stage ids. Returns the
  projects whose board card sits in those stages.
- `filter[status]` — which projects to include:
  - `active` (the default) — neither archived nor completed.
  - `completed` — finished but not archived.
  - `archived` — archived, whether or not they were completed.
  - `not_archived` — everything except archived projects.
  - `all` — every project, whatever its state.
- `filter[has_budget]` — `true` for projects that track a budget,
  `false` for those that don't. Needs permission to see budgets.
- `filter[budget_amount_min]` and `filter[budget_amount_max]` — a range
  over the project's budget amount. Both bounds are inclusive, and
  either works alone. Projects that track no budget are left out.
  Needs permission to see budgets. Combining either bound with
  `filter[has_budget]=false` returns `400`, since nothing can match
  both.

The `budget` key is left out entirely for a token that is not allowed to
see budgets. The same token cannot filter on the budget either: that
would hand back what the key is hiding, so `filter[has_budget]`,
`filter[budget_amount_min]` and `filter[budget_amount_max]` return `403`
instead.

## Query parameters

- `page[number]` integer
- `page[size]` integer
- `filter[title]` string
- `filter[public_url_token]` string
- `filter[board_group_id]` string
- `filter[status]` 'active' | 'archived' | 'not_archived' | 'completed' | 'all'
- `filter[has_budget]` 'true' | 'false'
- `filter[budget_amount_min]` string
- `filter[budget_amount_max]` string

## Response `200`

A page of projects.

- object
  - `data` Project[], required
    - `id` integer, required: Unique identifier for the project.
    - `title` string, nullable, required: Project title.
    - `public_url_token` string, nullable, required: Token in the project's client-facing URL. The list endpoint accepts it as `filter[public_url_token]`.
    - `currency` string, required: Three-letter ISO 4217 currency code the project bills in.
    - `start_date` string, date, nullable, required: Date work on the project starts.
    - `finish_date` string, date, nullable, required: Date work on the project ends, or `null` when it is open-ended.
    - `sequence` integer, nullable, required: Counter behind `number`, incrementing per client. `null` until a number has been assigned.
    - `number` string, nullable, required: Human-readable project reference. `null` until one has been assigned.
    - `board_group_id` string, uuid, nullable, required: Id of the pipeline stage the project's board card sits in, or `null` when the project is not on a board. Send it to `PATCH /public-api/v1/projects/{id}` to move the project to another stage.
    - `company_name` string, nullable, required: Name of the client the project is for, or `null`.
    - `client_or_company_name` string, required: Deprecated — read `company_name` instead, which carries the same value. This field will be removed in a future release.
    - `billing_type` 'time' | 'fixed_fee' | 'retainer' | 'not_billable' | 'null', nullable: How the project bills: `time` (hourly), `fixed_fee` (a single agreed fee), `retainer` (a recurring fee) or `not_billable`. Absent unless the token is allowed to see project finances.
    - `billing_cycle` 'weekly' | 'monthly' | 'quarterly' | 'biannually' | 'yearly' | 'null', nullable: How often a retainer bills. `null` for every other billing type. Absent unless the token is allowed to see project finances.
    - `billing_fee` string, nullable: The agreed fee as a decimal string, in `currency`. Set on `fixed_fee` and `retainer` projects, `null` otherwise. Absent unless the token is allowed to see project finances.
    - `company_id` integer, nullable, required: Id of the client company the project is for, or `null` when the client is not a company record.
    - `url` string, required: Absolute link to the project in the Bonsai app. Share it to send someone straight to the record.
    - `budget` ProjectBudget: A ceiling on what a project may consume — money or hours — and how often it resets.
      - `id` integer, required: Unique identifier for the budget.
      - `amount` string, required: The budget ceiling as a decimal string — an amount in the project currency when `calculation_mode` is `fee`, a number of hours when it is `time`.
      - `over_budget_notification_threshold` string, required: Percentage of the budget that triggers the alert, as a decimal string.
      - `calculation_mode` 'fee' | 'time', required: What the budget is measured in: `fee` for money, `time` for hours.
      - `calculation_base` 'billable_time' | 'non_billable_time' | 'billable_and_non_billable_time' | 'billable_time_and_expenses' | 'expenses', required: What counts against the budget: logged time (`billable_time`, `non_billable_time`, `billable_and_non_billable_time`), billable time plus expenses (`billable_time_and_expenses`), or expenses alone (`expenses`).
      - `expenses_calculation_base` 'billable' | 'non_billable' | 'all', required: Which expenses count, when `calculation_base` includes them: `billable`, `non_billable` or `all`.
      - `reset_frequency` 'never' | 'weekly' | 'monthly' | 'quarterly', required: How often the budget starts over. `never` runs one cycle for the life of the project; the rest open a fresh cycle every `weekly`, `monthly` or `quarterly` period from the project start date.
      - `over_budget_notification` 'enabled' | 'disabled', required: Whether Bonsai alerts the project team when spending passes `over_budget_notification_threshold`.
      - `current_cycle` ProjectBudgetCycle, required: One run of a budget: the window it covers and how much of the budget it has used.
        - `opening_date` string, date, required: First day the cycle counts.
        - `closing_date` string, date, nullable, required: Last day the cycle counts, or `null` when the budget never resets and the project is open-ended.
        - `consumed_amount` string, required: How much of the budget this cycle has used, as a decimal string, in the same unit as the budget `amount`.
        - `consumed_percentage` integer, required: How much of the budget this cycle has used, as a whole percentage. Exceeds 100 once the budget is over.
  - `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, `filter[status]` or `filter[has_budget]` is not one of the listed values, a budget bound is not a number, `filter[has_budget]=false` is combined with a budget bound, or a pagination parameter is not an integer.
- `401`: The access token is missing, expired or invalid.
- `403`: This token is not allowed to read or create projects, or filtered on the budget without permission to see budgets.
- `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)
