List labels
Return the labels defined in a project. Use it to build a label picker, to resolve label names to ids before writing label_ids on a work item, or to look up a label you imported by its external_id.
Results are paginated. Labels from other projects are never included — a project's labels are its own.
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 whose labels you want.
Query Parameters
Filters
parent_id:optionalstring (uuid)Return only the labels nested under this label.
Pair it with parent_id__isnull=true to get the opposite view — every top-level label in the project. Use parent_id__isnull=false for every label that has a parent.
external_id:optionalstringReturn labels whose external_id matches. Combine with external_source to resolve a record from another system to its Plane label without keeping a local id map.
external_source:optionalstringReturn labels that came from this system, for example github or jira.
Search
search:optionalstringA search term matched against the label name. Use it to power type-ahead in a picker rather than downloading every page and filtering client-side.
Ordering
order_by:optionalstringField to sort by. Prefix with - for descending. Defaults to sort_order.
sort_order,-sort_order— the project's own label orderingcreated_at,-created_at— newest or oldest firstid,-id
A value outside this list is not rejected — it silently falls back to the default sort_order. Check your spelling: a typo in order_by fails silently and shows up as a differently sorted page, not as an error.
Pagination
per_page:optionalintegerPage size. Defaults to 50, maximum 200.
offset:optionalintegerNumber of rows to skip from the start of the result set. Maximum 10000. Read the next value from the response and send it back as offset to walk forward.
paginate:optionalstringSet to cursor to switch from the default offset envelope to the keyset cursor envelope, which skips the COUNT(*) and returns next_cursor and has_more instead of next and total_count. Send the returned next_cursor back as cursor to fetch the following page.
Only created_at and id are cursor-eligible, because a keyset needs a strictly ordered column and sort_order is neither unique nor monotonic. Pair paginate=cursor with order_by=created_at or order_by=id — the default sort_order ordering is rejected with 400 ordering_not_cursor_eligible.
Most projects have few enough labels that the default offset envelope is all you need.
count:optionalbooleanDefaults to true. Set to false to omit total_count and skip the count query.
Scopes
projects.labels:read
Errors
| Status | Code | Cause |
|---|---|---|
401 | unauthorized | Missing or invalid credentials. |
403 | forbidden | Your role or token scope can't read labels. |
404 | resource_not_found | No such workspace or project, or it's outside your tenant. |
429 | rate_limited | Throttled. Honor the Retry-After header before retrying. |
curl -X GET \
"https://api.plane.so/api/v2/workspaces/my-team/projects/4af68566-94a4-4eb3-94aa-50dc9427067b/labels/?per_page=50&order_by=sort_order" \
-H "X-Api-Key: $PLANE_API_KEY"import requests
response = requests.get(
"https://api.plane.so/api/v2/workspaces/my-team/projects/4af68566-94a4-4eb3-94aa-50dc9427067b/labels/",
headers={"X-Api-Key": "your-api-key"},
params={"per_page": 50, "order_by": "sort_order"},
)
print(response.json())const response = await fetch(
"https://api.plane.so/api/v2/workspaces/my-team/projects/4af68566-94a4-4eb3-94aa-50dc9427067b/labels/?per_page=50&order_by=sort_order",
{
method: "GET",
headers: {
"X-Api-Key": "your-api-key",
},
}
);
const data = await response.json();{
"data": [
{
"id": "2b7d5e94-3c1a-4f60-9a8d-7e1c4b0f2d35",
"name": "Area",
"description": "Which part of the product",
"color": "#6b7280",
"sort_order": 32767,
"parent_id": null,
"external_id": null,
"external_source": null,
"created_at": "2026-01-09T11:04:18.220914Z",
"created_by_id": "16c61a3a-512a-48ac-b0be-b6b46fe6f430"
},
{
"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"
}
],
"next": null,
"previous": null,
"total_count": 2,
"pagination": {
"style": "offset"
}
}{
"type": "https://api.plane.so/errors/resource-not-found",
"title": "Not Found",
"status": 404,
"code": "resource_not_found",
"detail": "No project matches the given query."
}
