Skip to content

Create a workspace state ​

POST/api/v2/workspaces/{slug}/states/

Add a state to the workspace catalog. Every project in the workspace can use the new state.

This works only in a workspace with governance turned on. In an ungoverned workspace, states belong to projects, and this endpoint returns 409 states_managed_at_project. Create the state with Create a state on the project instead.

If the workspace's plan doesn't include workflows, Plane also adds the new state to the workspace's default workflow, after the existing states of the same group. If the plan includes workflows, add the state to a workflow yourself with Workspace workflow states.

Path Parameters ​

slug:requiredstring

The workspace slug. It appears in your Plane URLs. In https://app.plane.so/my-team/projects/, the slug is my-team.

Body Parameters ​

name:requiredstring

Display name. Maximum 255 characters. It must be unique in the catalog, compared case-insensitively, and a clash returns 409 conflict. Triage is reserved regardless of case or surrounding spaces, and sending it returns 400 invalid_request.

color:requiredstring

Hex color used wherever the state is rendered, for example #3f76ff. Maximum 255 characters.

group:requiredstring

The workflow group the state belongs to.

  • backlog. Not yet scheduled.
  • unstarted. Scheduled but not begun.
  • started. Actively in progress.
  • completed. Finished successfully.
  • cancelled. Closed without completion.

triage is not accepted, because Plane manages the triage state itself.

description:optionalstring

Free-form description of what the state means.

sequence:optionalnumber

Ordering weight. Lower values sort first. Plane places a new state after the last catalog state and uses your value only when the catalog is empty. To reposition a state, send sequence in Update a workspace state.

external_id:optionalstring

Your system's identifier for this state, for sync and import correlation. Maximum 255 characters.

external_source:optionalstring

The system external_id came from, for example jira. Maximum 255 characters. When you send both external_id and external_source, the pair must be unused in the catalog. A clash returns 409 conflict with the existing state's id in the body.

Response shaping ​

fields:optionalstring

Comma-separated list of fields to return. Unrequested keys are omitted from the response, not returned as null, so absent means "not requested" and null means "actually null". id always comes back whether or not you name it.

Pass all for every requestable field. An unknown name is a 400 that lists the valid set and suggests the closest match, so a typo can't silently cost you the saving.

Requestable here: color, created_at, created_by_id, description, external_id, external_source, group, id, is_default, is_triage, name, project_id, sequence, updated_at, updated_by_id.

See Sparse fields.

Scopes ​

workspaces.states:write

Errors ​

StatusCodeCause
400invalid_requestMissing name, color, or group, a group outside the five catalog groups, or the name Triage.
401unauthorizedMissing or invalid credentials.
402payment_requiredThe feature this endpoint belongs to isn't enabled on your plan, or is switched off.
403forbiddenOnly workspace owners and admins can create catalog states, or your token lacks the scope.
404not_foundNo such workspace, or it's outside your tenant.
406not_acceptableThe Accept header asks for a representation the API can't produce.
409states_managed_at_projectThe workspace doesn't have governance turned on. Create the state on a project.
409conflictA catalog state already uses this name, or this external_id and external_source pair.
409governance_migration_in_progressA governance migration is running, so the workspace is read-only. Retry after it finishes.
413payload_too_largeThe request body is over the size limit.
415unsupported_media_typeThe Content-Type isn't one this endpoint accepts.
429rate_limitedThrottled. Honor the Retry-After header before retrying.
Create a workspace state
bash
curl -X POST \
  "https://api.plane.so/api/v2/workspaces/my-team/states/" \
  -H "X-Api-Key: $PLANE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "In Review",
  "color": "#8e4ec6",
  "group": "started",
  "description": "Awaiting code review"
}'
Response201
json
{
  "id": "9e1b7c35-2a4f-4d08-b6e3-1c5f8a2d7e90",
  "name": "In Review",
  "description": "Awaiting code review",
  "color": "#8e4ec6",
  "group": "started",
  "sequence": 60000,
  "is_default": false,
  "is_triage": false,
  "project_id": null,
  "external_id": null,
  "external_source": null,
  "created_at": "2026-02-03T16:45:12.904117Z",
  "updated_at": "2026-02-03T16:45:12.904117Z",
  "created_by_id": "16c61a3a-512a-48ac-b0be-b6b46fe6f430",
  "updated_by_id": null
}
Response409
json
{
  "type": "conflict",
  "code": "states_managed_at_project",
  "detail": "States are managed at the project level for this workspace."
}
Response409
json
{
  "type": "conflict",
  "code": "conflict",
  "detail": "A state with this name already exists in this workspace."
}
Response400
json
{
  "type": "invalid_request",
  "code": "invalid_request",
  "detail": "One or more fields failed validation.",
  "errors": [
    {
      "field": "group",
      "code": "invalid_choice",
      "message": "\"triage\" is not a valid choice."
    }
  ]
}