List workspace property options
Return the selectable choices on a workspace-level OPTION property as a paginated list. This is how you resolve an option name to the id you store when setting the property on a work item, and how you build a picker that stays in sync with the property definition.
Results are ordered by sort_order by default, which is the order the option list is meant to be displayed in.
Reads work in either work item type mode. Only writes depend on the mode. 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.
property_id:requiredstring (uuid)The workspace-level property whose options you want. See Workspace work item properties.
This endpoint filters options by property instead of looking the property up, so an id that isn't a workspace-level property in this workspace, including a project-scoped property id, returns an empty list, not a 404.
Query parameters
Filters combine with AND. There is no search.
name:optionalstringReturn options with this name, compared case-insensitively. ?name=critical matches Critical, so you can resolve a label to its option id without reading the whole list.
external_id:optionalstringReturn options whose external_id matches exactly. Use it to find the option you created earlier for a value in another system.
external_source:optionalstringReturn options from one source system, for example jira. Combine it with external_id, because an external_id is unique only within its source.
Ordering
order_by:optionalstringField to sort by. Prefix with - for descending.
sort_order,-sort_order: the property's own display order. This is the default.created_at,-created_at: when each option was addedid,-id
A value outside this list is ignored and the default sort_order ordering is used, so a typo shows up as an unexpected order rather than an error.
Pagination
per_page:optionalintegerPage size. Defaults to 50, maximum 200. Most properties have fewer than 20 options, so one page is usually the whole list.
offset:optionalintegerNumber of rows to skip from the start of the result set. Maximum 10000. Use the next value from the response instead of computing offsets yourself.
paginate:optionalstringSet to cursor to switch to the keyset envelope, which skips the COUNT query and returns next_cursor and has_more instead of next and total_count. Leave it out to get the default offset envelope.
Cursor pagination needs a unique, monotonic sort key, and sort_order is neither. Pair it with order_by=created_at or order_by=id; a bare ?paginate=cursor falls back to the default sort_order ordering and is rejected with ordering_not_cursor_eligible.
count:optionalbooleanDefaults to true. Set to false to skip the COUNT(*) behind total_count; the field is then omitted from the response.
Scopes
workspaces.work_item_properties:read
Errors
| Status | Code | Cause |
|---|---|---|
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 read this workspace's properties. |
404 | not_found | No such workspace, or it's outside your tenant. |
406 | not_acceptable | The Accept header asks for a representation the API can't produce. |
429 | rate_limited | Throttled. Honor the Retry-After header before retrying. |
curl -X GET \
"https://api.plane.so/api/v2/workspaces/my-team/work-item-properties/9d0e1f3b-6a72-4c85-9e4d-2b7f1a6c8d54/options/?order_by=sort_order&per_page=50" \
-H "X-Api-Key: $PLANE_API_KEY"import requests
response = requests.get(
"https://api.plane.so/api/v2/workspaces/my-team/work-item-properties/9d0e1f3b-6a72-4c85-9e4d-2b7f1a6c8d54/options/",
headers={"X-Api-Key": "your-api-key"},
params={"order_by": "sort_order", "per_page": 50},
)
print(response.json())const params = new URLSearchParams({ order_by: "sort_order", per_page: "50" });
const response = await fetch(
`https://api.plane.so/api/v2/workspaces/my-team/work-item-properties/9d0e1f3b-6a72-4c85-9e4d-2b7f1a6c8d54/options/?${params}`,
{
headers: {
"X-Api-Key": "your-api-key",
},
},
);
const data = await response.json();{
"data": [
{
"id": "c31a7e04-5f6b-4d29-8a13-7e0c2b9f4a65",
"name": "Production",
"description": "Reported on live customer traffic",
"parent_id": null,
"is_default": true,
"is_active": true,
"sort_order": 10000,
"logo_props": {},
"external_id": null,
"external_source": null,
"updated_at": "2026-01-14T09:22:41.478363Z",
"updated_by_id": "16c61a3a-512a-48ac-b0be-b6b46fe6f430"
},
{
"id": "5e8b7d21-4a09-4c63-b7f2-90d1c3a86e57",
"name": "Staging",
"description": "Reported on the shared pre-release environment",
"parent_id": null,
"is_default": false,
"is_active": true,
"sort_order": 20000,
"logo_props": {},
"external_id": null,
"external_source": null,
"updated_at": "2026-01-14T09:22:41.478363Z",
"updated_by_id": "16c61a3a-512a-48ac-b0be-b6b46fe6f430"
},
{
"id": "a17f3c95-2d64-4b08-8e51-c94b7d60f382",
"name": "Development",
"description": "Reported on a local or branch environment",
"parent_id": null,
"is_default": false,
"is_active": true,
"sort_order": 30000,
"logo_props": {},
"external_id": null,
"external_source": null,
"updated_at": "2026-01-14T09:22:41.478363Z",
"updated_by_id": "16c61a3a-512a-48ac-b0be-b6b46fe6f430"
}
],
"next": null,
"previous": null,
"total_count": 3,
"pagination": {
"style": "offset"
}
}{
"data": [
{
"id": "c31a7e04-5f6b-4d29-8a13-7e0c2b9f4a65",
"name": "Production",
"description": "Reported on live customer traffic",
"parent_id": null,
"is_default": true,
"is_active": true,
"sort_order": 10000,
"logo_props": {},
"external_id": null,
"external_source": null,
"updated_at": "2026-01-14T09:22:41.478363Z",
"updated_by_id": "16c61a3a-512a-48ac-b0be-b6b46fe6f430"
}
],
"next_cursor": "b3A9MTcx",
"has_more": true,
"pagination": {
"style": "cursor"
}
}An empty list is a real answer
Three different situations all return 200 with an empty data array: an OPTION property that has no options yet, a property of some other property_type, and a property_id that isn't a workspace-level property at all. When an empty list is surprising, read the property itself and check both that it exists at the workspace level and that its property_type is OPTION.

