Workspace states overview
Workspace states are work item states read and written at the workspace level, on /api/v2/workspaces/{slug}/states/. They are the same kind of record as the per-project states that work items sit in. They are not project states, which are the lifecycle stages a project moves through, such as Planning or Execution.
The route behaves in one of two ways, depending on whether the workspace has workspace governance turned on.
| Workspace | What the route returns | Writes |
|---|---|---|
| Governance on | The workspace's catalog states. These rows have no project. Each project uses the catalog states its workflows include. | Create, update, and delete work here. |
| Governance off | A read-only list of the states of every non-archived project you can see, each with its project_id. | Every write returns 409 states_managed_at_project. |
The triage state that intake uses is never part of this route in either mode. It doesn't appear in lists, a GET for its id returns 404, and you can't create, update, or delete it here.
The workspace state object
Attributes
idstring (uuid)Unique identifier for the state. In a governed workspace, this is the
state_idyou send on work items.namestringDisplay name. Catalog state names are unique in the workspace, compared case-insensitively.
Triageis reserved. Maximum 255 characters.descriptionstringFree-form description of what the state means.
colorstringHex color used wherever the state is rendered, for example
#3f76ff.groupstringThe workflow group the state belongs to. One of
backlog,unstarted,started,completed, orcancelled. Rows from the cross-project view can also carrytriage, because a project can assign that group to a state it owns.sequencenumberOrdering weight. Lower values sort first.
is_defaultbooleanIn the cross-project view, whether the state is its project's default. Catalog states created through this API always have
false. In a governed workspace, each workflow sets its own default state. See Workspace workflow states.is_triagebooleanAlways
falsehere, because the triage state is excluded from this route.project_idstring (uuid) or nullnullfor a catalog state. In the cross-project view, the project the state belongs to. Two projects can each have a state namedDone, andproject_idtells them apart.external_id,external_sourcestring or nullCorrelation fields for sync and import. In the catalog, a given
external_idandexternal_sourcepair can belong to only one state.created_atstring (date-time)When the state was created.
updated_atstring (date-time)When the state was last updated.
created_by_idstring (uuid) or nullThe user who created the state.
updated_by_idstring (uuid) or nullThe user who last updated the state.
{
"id": "5a9e2c71-1f3b-4d86-a0c4-7e2b9d5f8a13",
"name": "In Progress",
"description": "Actively being worked on",
"color": "#3f76ff",
"group": "started",
"sequence": 30000,
"is_default": false,
"is_triage": false,
"project_id": null,
"external_id": null,
"external_source": null,
"created_at": "2026-01-14T09:22:41.478363Z",
"updated_at": "2026-01-14T09:22:41.478363Z",
"created_by_id": "16c61a3a-512a-48ac-b0be-b6b46fe6f430",
"updated_by_id": "16c61a3a-512a-48ac-b0be-b6b46fe6f430"
}{
"id": "f960d3c2-8524-4a41-b8eb-055ce4be2a7f",
"name": "In Progress",
"description": "Actively being worked on",
"color": "#3f76ff",
"group": "started",
"sequence": 25000,
"is_default": false,
"is_triage": false,
"project_id": "4af68566-94a4-4eb3-94aa-50dc9427067b",
"external_id": null,
"external_source": null,
"created_at": "2026-01-14T09:22:41.478363Z",
"updated_at": "2026-01-14T09:22:41.478363Z",
"created_by_id": "16c61a3a-512a-48ac-b0be-b6b46fe6f430",
"updated_by_id": "16c61a3a-512a-48ac-b0be-b6b46fe6f430"
}Endpoints
| Method | Path | Description |
|---|---|---|
GET | /api/v2/workspaces/{slug}/states/ | List workspace states |
GET | /api/v2/workspaces/{slug}/states/{pk}/ | Get a workspace state |
POST | /api/v2/workspaces/{slug}/states/ | Create a workspace state |
PATCH | /api/v2/workspaces/{slug}/states/{pk}/ | Update a workspace state |
DELETE | /api/v2/workspaces/{slug}/states/{pk}/ | Delete a workspace state |
Access
| Operation | Who can call it | Scope |
|---|---|---|
| List and get, governance on | Workspace owners, admins, and members. Guests get 403 forbidden. | workspaces.states:read |
| List and get, governance off | Anyone in the workspace, guests included. Rows are limited to the projects you can see. | workspaces.states:read |
| Create, update, and delete | Workspace owners and admins, in a governed workspace only. | workspaces.states:write |
Catalog states and workflows
In a governed workspace, a catalog state takes part in work item transitions through the workspace's workflows. See Workspace workflows.
- If the workspace's plan doesn't include workflows, creating a catalog state also adds it to the workspace's default workflow, after the existing states of the same group.
- If the plan includes workflows, a new catalog state isn't added to any workflow. Add it with Workspace workflow states.
- A catalog state can't be deleted while any workflow still lists it, or while any work item or draft is still in it. Both cases return
409 conflict.
While a governance migration is running, every write to the workspace returns 409 governance_migration_in_progress. Reads keep working and return the cross-project view until the migration finishes.
Response shaping
Every workspace state read accepts ?fields= for sparse responses. See Sparse fields. Errors follow the shared problem+json contract.
Changed from v1
- v1's
workspaces/{slug}/states/is the same dual-mode route. A write in an ungoverned workspace returns409 states_managed_at_projectinstead of v1's400 workspace_not_managed. - A duplicate catalog name returns
409 conflictinstead of a400. - Filtering by
external_idandexternal_sourcealways returns a list. v1 returned the single matching object, or a409when more than one state matched. - Reads return
is_defaultinstead ofdefault, andproject_idinstead ofproject. They no longer returnworkspace.
See Migrating from v1 for the full list.

