Update a work item type
Rename a type, rewrite its description, hide it from pickers, or correct its sync correlation fields. Work items already using the type are unchanged: this edits the type and does not change the type of any work item.
PATCH is partial. Send only the fields you want to change; anything you omit keeps its current value. Omitting a field is not the same as sending null.
This write requires project mode
If the workspace manages types at the workspace level, this returns 409 work_item_types_managed_at_workspace. Edit the type with the workspace endpoint instead. See Work item type modes.
Path parameters
slug:requiredstringThe workspace slug. It appears in your Plane URLs. In https://app.plane.so/my-team/projects/, the slug is my-team.
project_id:requiredstring (uuid)The project the type belongs to.
pk:requiredstring (uuid)The id of the work item type to update.
Body parameters
Every field is optional. Send only the fields you are changing.
name:optionalstringNew display name for the type. Maximum 255 characters. Renaming is safe: work items reference the type by type_id, not by name.
description:optionalstringWhat this type is for. It is returned as type_description by the schema endpoint, so this is the field to edit when integrations are choosing the wrong type.
is_active:optionalbooleanWhether the type can be assigned to new work items. Setting it to false hides the type from pickers without deleting it. Existing work items keep the type and stay readable. Use this instead of delete, which rejects a type that is in use.
external_id:optionalstringYour system's identifier for this type, for sync and import correlation. Maximum 255 characters, nullable.
external_source:optionalstringThe system external_id came from, for example github or jira. Maximum 255 characters, nullable.
is_default, is_epic and level are not accepted here
is_default moves through mark-default, which is a separate request because promoting one type demotes another. is_epic and level are read-only, as is logo_props.
Response shaping
fields:optionalstringComma-separated list of fields to return. Fields you don't request are left out of the response instead of coming back as null, so a missing key means you didn't ask for it and null means the value is null. id is always included, whether or not you name it.
Pass all to get every requestable field. An unknown field name returns 400 with the list of valid names and the closest match, so a typo is caught instead of being silently ignored.
Requestable here: created_at, description, external_id, external_source, governance_mode, id, is_active, is_active_in_project, is_default, is_default_in_project, is_epic, level, logo_props, name, project_ids, rollout, updated_at, updated_by_id.
See Sparse fields.
Scopes
projects.work_item_types:write
Errors
| Status | Code | Cause |
|---|---|---|
400 | invalid_request | A field over its 255-character limit, or "is_active": false on the default type. |
401 | unauthorized | Missing or invalid credentials. |
402 | payment_required | The feature this endpoint belongs to isn't enabled on your plan, or is switched off. |
403 | forbidden | Your role or token scope can't update work item types. |
404 | not_found | No such type, project, or workspace, or the type belongs to another project. |
406 | not_acceptable | The Accept header asks for a representation the API can't produce. |
409 | conflict | Another type in this project already uses this external_id and external_source pair. |
413 | payload_too_large | The request body is over the size limit. |
415 | unsupported_media_type | The Content-Type isn't one this endpoint accepts. |
429 | rate_limited | Throttled. Honor the Retry-After header before retrying. |
curl -X PATCH \
"https://api.plane.so/api/v2/workspaces/my-team/projects/4af68566-94a4-4eb3-94aa-50dc9427067b/work-item-types/d1e7a4c9-2b58-4f36-9a0e-7c3b5d81f240/" \
-H "X-Api-Key: $PLANE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Defect",
"description": "A verified regression in shipped behavior"
}'import requests
response = requests.patch(
"https://api.plane.so/api/v2/workspaces/my-team/projects/4af68566-94a4-4eb3-94aa-50dc9427067b/work-item-types/d1e7a4c9-2b58-4f36-9a0e-7c3b5d81f240/",
headers={"X-Api-Key": "your-api-key"},
json={
"name": "Defect",
"description": "A verified regression in shipped behavior",
},
)
print(response.json())const response = await fetch(
"https://api.plane.so/api/v2/workspaces/my-team/projects/4af68566-94a4-4eb3-94aa-50dc9427067b/work-item-types/d1e7a4c9-2b58-4f36-9a0e-7c3b5d81f240/",
{
method: "PATCH",
headers: {
"X-Api-Key": "your-api-key",
"Content-Type": "application/json",
},
body: JSON.stringify({
name: "Defect",
description: "A verified regression in shipped behavior",
}),
},
);
const data = await response.json();{
"id": "d1e7a4c9-2b58-4f36-9a0e-7c3b5d81f240",
"name": "Defect",
"description": "A verified regression in shipped behavior",
"logo_props": {
"in_use": "icon",
"icon": {
"name": "AlertCircle",
"background_color": "#EF5974"
}
},
"is_epic": false,
"is_default": false,
"is_active": true,
"is_active_in_project": true,
"is_default_in_project": false,
"level": 0,
"governance_mode": "any",
"rollout": "none",
"project_ids": ["4af68566-94a4-4eb3-94aa-50dc9427067b"],
"external_id": null,
"external_source": null,
"created_at": "2026-01-14T09:24:03.117482Z",
"updated_at": "2026-02-03T16:45:12.904117Z",
"updated_by_id": "16c61a3a-512a-48ac-b0be-b6b46fe6f430"
}{
"type": "invalid_request",
"code": "invalid_request",
"detail": "The default work item type cannot be deactivated.",
"errors": []
}The default type cannot be deactivated
The API rejects "is_active": false for the project's default type, because every project needs a type for untyped work items. Promote another type with mark-default first, then deactivate this one.
Deactivate rather than delete
Delete refuses to remove a type that still has work items. Setting "is_active": false is usually what you want anyway: the type stops appearing in pickers, existing work items still render correctly, and you can reverse the change.

