Property contexts overview
A context scopes a workspace-level work item property to a set of projects and a set of work item types, and overrides how that property behaves inside that scope.
A property is defined once for the whole workspace, so it has one is_required flag, one is_multi flag, one default value, and one list of options. Most workspaces need more than that. Contexts let one property definition follow different rules in different places.
The problem a context solves
Your workspace has a Severity property. You want it to be required on Bug work items in the Platform and Mobile projects, with a full S1/S2/S3 scale, and optional, with a shorter list, everywhere else.
That is two sets of rules for one property, so it takes two contexts:
- The context Plane seeds with the property covers all projects and all work item types. Leave it at
is_required: false. This is the "everywhere else" rule. - A second context names the two projects and the
Bugtype, and setsis_required: truewith its own options. This is the narrow rule.
The narrow context is the one that wins on a Bug in Platform, because Plane always resolves the most specific matching context. On a Task in Platform, or on a Bug in a third project, nothing narrow matches and the seeded context applies instead.
Creating the narrow rule is a single request:
{
"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" }
]
}Every property already has one context
When you create a workspace-level property, Plane seeds a context named Default that covers all projects and all work item types and mirrors the property's own is_required, is_multi, default_value, and settings. It is a normal context: you can read, update, and delete it through these endpoints. Its is_default flag is a historical marker and does not affect resolution.
The property context object
Attributes
idstring (uuid)Unique identifier for the context.
namestringDisplay name, unique among the contexts of this property. Maximum 255 characters.
is_requiredbooleanWhether the property must be filled in inside this scope. Overrides the property's own
is_required.is_multibooleanWhether the property accepts several values inside this scope. Overrides the property's own
is_multi.is_defaultbooleantrueon the context Plane seeded with the property. It is only a marker. The scope flags decide precedence, not this field.default_valuearray of stringValues applied when a work item in this scope has nothing set. For
OPTIONproperties, options in this context flaggedis_defaulttake precedence over this array.settingsanyType-specific configuration for this scope, as a JSON object. Overrides the property's own
settings.sort_ordernumberOrdering weight among this property's contexts. Lower values sort first, and lists are returned in this order by default.
applies_to_all_projectsbooleanWhen
true, the context covers every project in the workspace andproject_idsis empty. Whenfalse,project_idsis the exact list of projects covered.applies_to_all_work_item_typesbooleanWhen
true, the context covers every work item type andissue_type_idsis empty. Whenfalse,issue_type_idsis the exact list of types covered.project_idsarray of anyThe ids of the projects this context covers. Empty when
applies_to_all_projectsistrue, so read the flag before reading this list.issue_type_idsarray of anyThe ids of the work item types this context covers. Empty when
applies_to_all_work_item_typesistrue.optionsarray of anyThe choices this context offers for an
OPTIONproperty. Each entry hasid,name,is_default, andsort_order. Options belong to a context, not to the property, so two contexts on the same property can offer different lists.external_id,external_sourcestringCorrelation fields for sync and import. Together they let you map a context to a record in another system and find it again later. A pair is unique within a property.
created_atstring (date-time)When the context was created.
updated_atstring (date-time)When the context was last updated.
updated_by_idstring (uuid) or nullThe user who last updated the context.
nulluntil someone updates it.
{
"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-01-14T09:22:41.478363Z",
"updated_at": "2026-01-14T09:22:41.478363Z",
"updated_by_id": null,
"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
}
]
}Endpoints
| Method | Path | Description |
|---|---|---|
GET | /api/v2/workspaces/{slug}/work-item-properties/{property_id}/contexts/ | List property contexts |
GET | /api/v2/workspaces/{slug}/work-item-properties/{property_id}/contexts/{pk}/ | Get a property context |
POST | /api/v2/workspaces/{slug}/work-item-properties/{property_id}/contexts/ | Create a property context |
PATCH | /api/v2/workspaces/{slug}/work-item-properties/{property_id}/contexts/{pk}/ | Update a property context |
DELETE | /api/v2/workspaces/{slug}/work-item-properties/{property_id}/contexts/{pk}/ | Delete a property context |
{property_id} must be a workspace-level property. A project-level property id is not addressable here and returns 404 not_found.
Scope: wildcards and explicit lists
A context covers the intersection of a project set and a work item type set. Each of those two sets is expressed in one of two ways, and the wildcard flag decides which:
| Flag | Companion list | Coverage |
|---|---|---|
applies_to_all_projects: true | project_ids empty | Every project in the workspace |
applies_to_all_projects: false | project_ids listed | Exactly the projects you listed |
applies_to_all_work_item_types: true | issue_type_ids empty | Every work item type in the workspace |
applies_to_all_work_item_types: false | issue_type_ids listed | Exactly the types you listed |
The flag and the list are mutually exclusive:
- On write, sending
project_idswithapplies_to_all_projects: truereturns400. The list would have no effect, so Plane rejects it instead of dropping it silently. The same rule applies toissue_type_idsandapplies_to_all_work_item_types. - On read,
project_idsandissue_type_idsare computed from the links Plane stores. Turning a wildcard on removes those links, so a wildcard context always reads back with an empty list.
An empty list does not mean "nothing"
"project_ids": [] with "applies_to_all_projects": true means every project. "project_ids": [] never appears with the flag false, because a context can never be scoped to nothing. Always branch on the flag first, then read the list.
Each axis must use either the flag or a list. On create, omitting both the flag and the list for an axis returns 400 (see Create a context). On update, you can't leave an axis empty either: to turn a wildcard off, send the ids that replace it in the same request.
Only one context per property can use applies_to_all_projects
The context Plane seeds with the property already uses it. Creating a second all-projects context returns 400. To move it, update the seeded context or delete it first.
How Plane picks the context
For a given work item, Plane picks one context from the property's list by checking four tiers against the work item's project and type, most specific first:
- Listed project and listed type.
- Listed project and all types.
- All projects and listed type.
- All projects and all types (the seeded context).
The first tier with a match wins. Plane doesn't check the remaining tiers, and nothing is merged between them. Contexts at different tiers are meant to overlap, because that's how a narrow rule beats a broad one. Overlap within the same tier is ambiguous, so Plane rejects it at write time with 400.
No matching context means the property disappears
If no tier matches a work item's project and type, the property doesn't appear on that work item at all. Deleting the all-projects, all-types context leads to this. See Delete a context.
What a context overrides
For work items in its scope, the resolved context replaces the property's values entirely: is_required, is_multi, default_value, settings, and the list of selectable options all come from the context, not from the property.
Working through the Severity example, with the seeded context left at its defaults:
| Field | On the seeded context | On the Bug severity context | Bug in Platform | Task in Platform |
|---|---|---|---|---|
| Tier | 4 (all / all) | 1 (listed / listed) | Tier 1 wins | Tier 4 wins |
is_required | false | true | Required | Optional |
is_multi | false | false | Single value | Single value |
| Options | Low, High | S1, S2, S3 | S1/S2/S3 | Low/High |
| Default | none | S2 — Major (is_default) | S2 — Major | none |
A Bug in Platform never sees Low or High. Option lists aren't combined across contexts, and the resolved context's list is the full set of permitted values.
Options belong to a context
Options created through the property options endpoints attach to the property's all-projects, all-types context. To give a narrower context its own choices, send the options array when you create or update the context. Each entry either references an existing option of the property by id or creates a new one by name.
On update, options replaces the whole list. An option you leave out is removed from the context, along with the values recorded through it.
Contexts are workspace mode only
The property a context belongs to is defined at the workspace level, so POST, PATCH, and DELETE require the workspace to manage work item types at the workspace level. If it manages them per project, the write returns 409 work_item_types_managed_at_project. Reads work in either mode.
See Work item type modes for how to check which mode a workspace is in.
Scopes
| Operation | Scope |
|---|---|
| List, Get | workspaces.work_item_properties:read |
| Create, Update, Delete | workspaces.work_item_properties:write |

