Create a property context
Add a context to a workspace-level property. The context names the projects and work item types it covers, and carries the is_required, is_multi, default_value, settings, and option list that apply inside that scope.
Reach for this when one property definition needs different rules in different places — for example a Severity property that is required on Bug work items in two projects and optional everywhere else.
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 the context belongs to. A project-level property id is not addressable here and returns 404 resource_not_found.
Body Parameters
No single field is required by the schema, but the scope is: each of the two axes must be pinned down, either by setting its wildcard flag to true or by supplying a non-empty id list. Both flags default to false, so a body that omits project_ids and issue_type_ids entirely is a 400, not a context that covers everything.
name:optionalstringDisplay name, unique among this property's contexts. Maximum 255 characters. Always send one — the context Plane seeded with the property already occupies the name Default.
applies_to_all_projects:optionalbooleanSet to true to cover every project in the workspace instead of listing them. Defaults to false, which means project_ids is required.
Only one context per property may set this to true, and the seeded context normally holds that slot, so a second all-projects context returns 400.
project_ids:optionalarray of string (uuid)The exact projects this context covers. Required when applies_to_all_projects is false, and rejected with a 400 when it is true — the flag and the list are alternatives, never a combination.
Every id must belong to this workspace, and duplicates are rejected. This field is write-only as an input, but the resulting links are echoed back in the response's read-only project_ids.
applies_to_all_work_item_types:optionalbooleanSet to true to cover every work item type in the workspace instead of listing them. Defaults to false, which means issue_type_ids is required.
issue_type_ids:optionalarray of string (uuid)The exact work item types this context covers. Required when applies_to_all_work_item_types is false, and rejected with a 400 when it is true.
Every id must belong to this workspace, and duplicates are rejected. Write-only as an input; the response echoes the stored links in issue_type_ids.
is_required:optionalbooleanWhether the property must be filled in on work items inside this scope. This replaces the property's own is_required here — it does not combine with it.
is_multi:optionalbooleanWhether the property accepts several values inside this scope. Replaces the property's own is_multi here.
default_value:optionalarray of stringValues applied when a work item in this scope has nothing set. For OPTION properties, any option in this context flagged is_default takes precedence over this array.
options:optionalarray of objectThe choices this context offers for an OPTION property. Options belong to a context, so this list — not the property's full option list — is what work items in this scope can pick from.
Each entry either references an existing option of the property or creates a new one:
idstring (uuid) — an existing option of this property. Duplicate ids and ids from another property are rejected.namestring — creates a new option. Maximum 255 characters. Names must be unique within the payload, case-insensitively.descriptionstring — free-form description of the option.is_defaultboolean — preselect this option for new work items in this scope. Defaults tofalse.
Send either id or name on each entry — an entry with neither is a 400. Write-only as an input; the response returns the resulting options with their ids.
An option's own sort_order is read-only: Plane assigns it from the order of the entries you send, and it is returned on each option in the response.
settings:optionalanyType-specific configuration for this scope, as a JSON object. Replaces the property's own settings here.
sort_order:optionalnumberOrdering weight among this property's contexts. Lower values sort first. Omit it and Plane places the new context after the ones that already exist. Ordering is presentational — it does not affect which context wins.
external_id:optionalstringYour system's identifier for this context, for sync and import correlation. Maximum 255 characters. Must be sent together with external_source, and the pair must be unique within the property.
external_source:optionalstringThe system external_id came from, for example github or jira. Maximum 255 characters. Must be sent together with external_id.
Scopes
workspaces.work_item_properties:write
Errors
| Status | Code | Cause |
|---|---|---|
400 | validation_error | An axis left unpinned, a list sent alongside its wildcard flag, an id outside the workspace, a duplicate name, a half-filled external pair, or an overlap with a same-tier context. |
401 | unauthorized | Missing or invalid credentials. |
403 | forbidden | Your role or token scope can't change workspace property settings. |
404 | resource_not_found | No such workspace or property, the property is project-level, or it's outside your tenant. |
409 | work_item_types_managed_at_project | This workspace manages work item types per project, so workspace-level property writes are refused. |
429 | rate_limited | Throttled. Honor the Retry-After header before retrying. |
Same-tier overlap is rejected
Two contexts on the same property may overlap only when one is strictly more specific than the other — that is what makes narrow rules beat broad ones. Two contexts at the same level of specificity that share a project return 400: two listed-project/listed-type contexts sharing a project and a type, or two listed-project/all-type contexts sharing a project.
Workspace mode only
Creating a context requires the workspace to manage work item types at the workspace level. In project mode the request returns 409 work_item_types_managed_at_project — the capability exists, it just lives on the project surface. Reads are unaffected. See Work item type modes.
curl -X POST \
"https://api.plane.so/api/v2/workspaces/my-team/work-item-properties/d1f7a3c9-5b62-4e08-9a41-7c3e2f8b6d05/contexts/" \
-H "X-Api-Key: $PLANE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Bug severity",
"applies_to_all_projects": false,
"project_ids": [
"4af68566-94a4-4eb3-94aa-50dc9427067b",
"9c3d7e21-6b45-4a80-8f19-2e0c7b5d3a64"
],
"applies_to_all_work_item_types": false,
"issue_type_ids": ["b7e04a95-2f18-4c63-9d57-8a12e6b0f439"],
"is_required": true,
"is_multi": false,
"options": [
{ "name": "S1 — Critical" },
{ "name": "S2 — Major", "is_default": true },
{ "name": "S3 — Minor" }
]
}'import requests
response = requests.post(
"https://api.plane.so/api/v2/workspaces/my-team/work-item-properties/d1f7a3c9-5b62-4e08-9a41-7c3e2f8b6d05/contexts/",
headers={"X-Api-Key": "your-api-key"},
json={
"name": "Bug severity",
"applies_to_all_projects": False,
"project_ids": [
"4af68566-94a4-4eb3-94aa-50dc9427067b",
"9c3d7e21-6b45-4a80-8f19-2e0c7b5d3a64",
],
"applies_to_all_work_item_types": False,
"issue_type_ids": ["b7e04a95-2f18-4c63-9d57-8a12e6b0f439"],
"is_required": True,
"is_multi": False,
"options": [
{"name": "S1 — Critical"},
{"name": "S2 — Major", "is_default": True},
{"name": "S3 — Minor"},
],
},
)
print(response.json())const response = await fetch(
"https://api.plane.so/api/v2/workspaces/my-team/work-item-properties/d1f7a3c9-5b62-4e08-9a41-7c3e2f8b6d05/contexts/",
{
method: "POST",
headers: {
"X-Api-Key": "your-api-key",
"Content-Type": "application/json",
},
body: JSON.stringify({
name: "Bug severity",
applies_to_all_projects: false,
project_ids: ["4af68566-94a4-4eb3-94aa-50dc9427067b", "9c3d7e21-6b45-4a80-8f19-2e0c7b5d3a64"],
applies_to_all_work_item_types: false,
issue_type_ids: ["b7e04a95-2f18-4c63-9d57-8a12e6b0f439"],
is_required: true,
is_multi: false,
options: [{ name: "S1 — Critical" }, { name: "S2 — Major", is_default: true }, { name: "S3 — Minor" }],
}),
}
);
const data = await response.json();{
"id": "6e2b90d4-1c73-4f58-a09e-3d8b5c14e7f2",
"name": "Bug severity",
"is_required": true,
"is_multi": false,
"is_default": false,
"default_value": [],
"settings": {},
"sort_order": 75535,
"applies_to_all_projects": false,
"applies_to_all_work_item_types": false,
"external_id": null,
"external_source": null,
"created_at": "2026-02-03T11:05:17.204918Z",
"project_ids": ["4af68566-94a4-4eb3-94aa-50dc9427067b", "9c3d7e21-6b45-4a80-8f19-2e0c7b5d3a64"],
"issue_type_ids": ["b7e04a95-2f18-4c63-9d57-8a12e6b0f439"],
"options": [
{
"id": "c58e2f01-4d97-4b3a-8e26-1f0b7a9c5d34",
"name": "S1 — Critical",
"is_default": false,
"sort_order": 10000
},
{
"id": "a49b6c72-8e15-4d30-b57c-2f81e0a6d938",
"name": "S2 — Major",
"is_default": true,
"sort_order": 20000
},
{
"id": "f13c8a60-7d24-4e59-9b02-6a5f1c3e8d47",
"name": "S3 — Minor",
"is_default": false,
"sort_order": 30000
}
]
}{
"type": "https://api.plane.so/errors/validation-error",
"title": "Validation Error",
"status": 400,
"code": "validation_error",
"detail": "The request body failed validation.",
"errors": [
{
"field": "project_ids",
"message": "Required when applies_to_all_projects is false."
}
]
}{
"type": "https://api.plane.so/errors/work-item-types-managed-at-project",
"title": "Conflict",
"status": 409,
"code": "work_item_types_managed_at_project",
"detail": "Work item types are managed at the project level for this workspace."
}Pinning each axis
A context covers the intersection of a project set and a work item type set, and each set is expressed either by its wildcard flag or by its id list. Four shapes are valid, and they map one-to-one onto the precedence tiers Plane uses when it resolves a work item:
| Projects | Work item types | Covers |
|---|---|---|
project_ids: [...] | issue_type_ids: [...] | Those types, in those projects. Most specific. |
project_ids: [...] | applies_to_all_work_item_types: true | Every type, in those projects |
applies_to_all_projects: true | issue_type_ids: [...] | Those types, in every project |
applies_to_all_projects: true | applies_to_all_work_item_types: true | Everything. Least specific — normally the seeded context. |
Two mistakes produce a 400 rather than a surprising context:
- Neither the flag nor the list. Omitting
project_idswhileapplies_to_all_projectsisfalsedoes not quietly mean "all projects"; it means the context would cover nothing, so it is rejected. - Both the flag and the list. Sending
project_idswithapplies_to_all_projects: trueis rejected because the list could never take effect. Omit it.
The same two rules apply on the work item type axis.
Verify with a read-back
The response echoes project_ids and issue_type_ids as stored. A wildcard context always reads back with the matching list empty — "applies_to_all_projects": true with "project_ids": [] means every project, not none. Read the flag first.
What the new context changes
Inside its scope, the context's is_required, is_multi, default_value, settings, and options replace the property's own values wholesale. Nothing is merged, and option lists are not unioned: a Bug in the Platform project can only choose from S1, S2, and S3 above, even if the property's other contexts offer more.
Outside its scope, nothing changes — work items keep resolving to whichever context was already the most specific match for them.
See Property contexts overview for the full precedence rules, and Update a context for how scope changes affect values that were already recorded.

