Update a work item type
Rename a type, rewrite its description, retire it from pickers, or correct its sync correlation fields. Work items already using the type are untouched — you are editing the type, not retyping anything.
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 on the workspace surface 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 the subset 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 retires the type from pickers without deleting it — existing work items keep the type and stay readable. This is the safe alternative to delete, which a type in use rejects.
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 dedicated request precisely 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. 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: created_at, description, id, is_active, is_default, is_epic, level, logo_props, name.
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",
"is_active": true,
"is_default": false,
"is_epic": false,
"level": 0,
"logo_props": {
"in_use": "icon",
"icon": {
"name": "AlertCircle",
"background_color": "#EF5974"
}
},
"created_at": "2026-01-14T09:24:03.117482Z"
}{
"type": "invalid_request",
"code": "invalid_request",
"detail": "The default work item type cannot be deactivated.",
"errors": []
}The default type cannot be deactivated
Sending "is_active": false for the project's default type is rejected — every project needs a type for untyped work items to land on. 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. "is_active": false is the usual intent anyway: the type stops appearing in pickers, historical work items keep rendering correctly, and the change is reversible.

