Skip to content

Create a label ​

POST/api/v2/workspaces/{slug}/projects/{project_id}/labels/

Add a label to a project. The new label is immediately available to every work item in that project, and to no other project.

Label names must be unique within a project — reusing one returns 409 conflict.

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.

project_id:requiredstring (uuid)

The project to add the label to.

Body Parameters ​

name:requiredstring

Display name for the label, unique within the project. Maximum 255 characters.

color:optionalstring

Hex color used wherever the label is rendered, for example #e5484d. Maximum 255 characters. Send one if the label needs to be recognizable at a glance on a board.

description:optionalstring

Free-form note about what the label is for and when to apply it.

parent_id:optionalstring (uuid)

The label this one nests under, for grouping related tags such as Billing and Search beneath an Area label. The parent must be a label in the same project — an id from another project is a 400, not a silent link.

Omit it, or send null, for a top-level label.

sort_order:optionalnumber

Ordering weight within the project. Lower values sort first. Assigned automatically when omitted, so send it only when you are recreating a specific order.

external_id:optionalstring

Your system's identifier for this label, for sync and import correlation. Maximum 255 characters. Store it here and you can find the label later with ?external_id=, without keeping a map of Plane ids.

external_source:optionalstring

The system external_id came from, for example github or jira. Maximum 255 characters.

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, id, name, parent_id, sort_order.

See Sparse fields.

Scopes ​

projects.labels:write

Errors ​

StatusCodeCause
400invalid_requestname missing or over 255 characters, or a parent_id that isn't a label in this project.
401unauthorizedMissing or invalid credentials.
402payment_requiredThe feature this endpoint belongs to isn't enabled on your plan, or is switched off.
403forbiddenYour role or token scope can't create labels.
404not_foundNo such workspace or project, or it's outside your tenant.
406not_acceptableThe Accept header asks for a representation the API can't produce.
409conflictA label with this name already exists in the project.
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 label
bash
curl -X POST \
  "https://api.plane.so/api/v2/workspaces/my-team/projects/4af68566-94a4-4eb3-94aa-50dc9427067b/labels/" \
  -H "X-Api-Key: $PLANE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Regression",
  "color": "#e5484d",
  "description": "Worked before the last release",
  "parent_id": "2b7d5e94-3c1a-4f60-9a8d-7e1c4b0f2d35"
}'
Response201
json
{
  "id": "9c1f0b3d-6d2e-4c9a-8b41-2f7e5a0d6c88",
  "name": "Regression",
  "description": "Worked before the last release",
  "color": "#e5484d",
  "sort_order": 65535,
  "parent_id": "2b7d5e94-3c1a-4f60-9a8d-7e1c4b0f2d35",
  "external_id": null,
  "external_source": null,
  "created_at": "2026-01-14T09:22:41.478363Z",
  "created_by_id": "16c61a3a-512a-48ac-b0be-b6b46fe6f430"
}
Response409
json
{
  "type": "conflict",
  "code": "conflict",
  "detail": "A label with this name already exists in the project."
}