Update a project
Updates a project. Every field is optional, and anything you leave out keeps its current value.
Sending null clears finish_date, billing_fee and billing_cycle.
title, start_date, billing_type and board_group_id can be
changed but not cleared.
Whenever you touch a billing field the resulting combination is checked,
not just the values you sent — so moving a retainer to time means
clearing the fee and cycle in the same request:
billing_type |
billing_fee |
billing_cycle |
|---|---|---|
fixed_fee |
required | must be empty |
retainer |
required | required |
time |
must be empty | must be empty |
not_billable |
must be empty | must be empty |
billing_type, billing_fee and billing_cycle need permission to see
billing; without it the whole request is rejected with 422
not_accessible and nothing is saved. Existing time entries keep the
rate they were logged at — a billing change applies to new ones only.
finish_date has to be on or after start_date, whether you send both
or only one of them — the other is taken from the project as it stands.
board_group_id moves the project to another stage of the project
board it is already on — a stage belonging to a different board is
rejected. Find one with
GET /public-api/v1/board_groups?filter[resource_type]=Project. A
project that is on no board yet can be filed onto any of them.
The client company and the currency are both fixed once a project
exists, so company_id and currency are ignored here. Amounts already
recorded against a project are never converted, so changing its currency
would silently restate them — set it when you create the project.
A project the token cannot see returns 404, and one it can see but may
not change returns 403.
Path Parameters
- Type: integeridrequired
The project's
id.
Body
The attributes to change, wrapped in a project key. All of them are optional.
- Properties: 7Type: objectprojectrequired
Responses
- application/json
- application/json
- application/json
- application/json
- application/json
- application/json
- application/json
curl https://app.hellobonsai.com/public-api/v1/projects/1 \
--request PATCH \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_SECRET_TOKEN' \
--data '{
"project": {
"title": "Acme Website",
"start_date": "2026-05-01",
"finish_date": "2026-09-30",
"billing_type": "retainer",
"billing_fee": "5000",
"billing_cycle": "monthly",
"board_group_id": "0c8f1e2a-3b4c-4d5e-6f70-8192a3b4c5d6"
}
}'
{
"data": {
"id": 51,
"title": "Acme Website",
"public_url_token": "acme-website-x4n2",
"currency": "USD",
"start_date": "2026-05-01",
"finish_date": "2026-09-30",
"sequence": 1,
"number": "ACME-0001",
"board_group_id": "0c8f1e2a-3b4c-4d5e-6f70-8192a3b4c5d6",
"company_name": "Acme Corp",
"billing_type": "fixed_fee",
"billing_cycle": "monthly",
"billing_fee": "5000.0",
"company_id": 42,
"url": "https://app.hellobonsai.com/projects/acme-website-x4n2",
"budget": {
"id": 41,
"amount": "5000.0",
"over_budget_notification_threshold": "80.0",
"calculation_mode": "fee",
"calculation_base": "billable_time_and_expenses",
"expenses_calculation_base": "all",
"reset_frequency": "monthly",
"over_budget_notification": "enabled",
"current_cycle": {
"opening_date": "2026-03-01",
"closing_date": "2026-03-31",
"consumed_amount": "1250.0",
"consumed_percentage": 25
}
}
},
"meta": {
"request_id": "b1f0d2c4-7a9e-4c3b-8d5f-1e2a3b4c5d6e"
}
}