---
title: "Create a project budget"
method: POST
path: "/public-api/v1/projects/{project_id}/budget"
tags: ["Projects"]
---

# Create a project budget

`POST /public-api/v1/projects/{project_id}/budget`

## Request

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

Starts tracking a budget on a project you already have. A project has at
most one budget, so creating a second one returns `422`.

`calculation_mode` sets the unit of every number in the budget: `fee`
counts money in the project's currency, `time` counts hours. `amount` is
a plain decimal in that unit, not cents — `"5000"` on a `fee` budget is
5,000.00 and `"37.5"` on a `time` budget is 37.5 hours.

`calculation_base` has to be one the mode can count, and any other is
rejected:

| `calculation_mode` | `calculation_base` |
| --- | --- |
| `fee` | `billable_time`, `billable_time_and_expenses`, `expenses` |
| `time` | `billable_time`, `non_billable_time`, `billable_and_non_billable_time` |

Every setting you leave out is taken from the company's budget settings
in Bonsai, the ones the app pre-fills. A default `calculation_base` the
mode cannot count becomes `billable_time`.

The project needs a `start_date`, because budget cycles run from it; set
one with `PATCH /public-api/v1/projects/{id}` first. A project that
starts in the future gets its budget right away, and its first cycle
opens on the start date.

A project the token cannot see returns `404`. One it can see returns
`403` when the token may not change the project or see its budget, or
when the plan does not include budgets.

## Request body

- object
  - `budget` object, required
    - `calculation_mode` 'fee' | 'time', required: What the budget counts: `fee` for money in the project currency, `time` for hours. Required.
    - `amount` string, required: The budget ceiling as a decimal string above zero: money in the project currency for `fee`, hours for `time`. Not cents. Required.
    - `calculation_base` 'billable_time' | 'non_billable_time' | 'billable_and_non_billable_time' | 'billable_time_and_expenses' | 'expenses': What counts against the budget. Must be one `calculation_mode` can count; see the table above. Defaults to the company's setting when the mode can count it, otherwise `billable_time`.
    - `expenses_calculation_base` 'billable' | 'non_billable' | 'all': Which expenses count. Only read when `calculation_base` includes expenses, but stored either way. Defaults to the company's setting, otherwise `billable`.
    - `reset_frequency` 'never' | 'weekly' | 'monthly' | 'quarterly': How often the budget starts over. `never` runs one cycle for the life of the project; the others open a new cycle every period from the project start date. Defaults to the company's setting, otherwise `never`.
    - `over_budget_notification` 'enabled' | 'disabled': Whether Bonsai alerts the project team when spending passes `over_budget_notification_threshold`. Defaults to the company's setting, otherwise `enabled`.
    - `over_budget_notification_threshold` string: Percentage of `amount` that triggers the alert, as a decimal string above zero. It can exceed 100. Defaults to the company's setting, otherwise `100`.

## Response `201`

The budget was created.

- object
  - `data` ProjectBudget, required: 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` 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 `budget` wrapper.
- `401`: The access token is missing, expired or invalid.
- `403`: This token can see the project but may not change it or see its budget, or the plan does not include budgets.
- `404`: No project with that `id` that this token can see. Sample projects return `404` too.
- `422`: The budget could not be created. `blank` means `calculation_mode` or `amount` is missing. `invalid_value` on a field means it is not one of the listed values, not a number above zero, or a `calculation_base` the mode cannot count. `invalid_value` at `/data/attributes` means the project has no `start_date` or already has a budget.
- `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)
