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

  • The project's id.

Body

required
application/json

The attributes to change, wrapped in a project key. All of them are optional.

  • Properties: 7

Responses

  • application/json
  • application/json
  • application/json
  • application/json
  • application/json
  • application/json
  • application/json
Request Example for patch/public-api/v1/projects/{id}
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"
  }
}