Attach a property to a type
Expose one or more existing custom properties on a work item type. After this call, work items of that type collect those properties.
This does not create a property
The body is a list of ids of properties that already exist in the project. Sending a definition — display_name, property_type, and friends — is a 400. Create the property first with Create a work item property, then attach the id it returns.
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 the work item type belongs to.
type_id:requiredstring (uuid)The work item type to attach the properties to.
Body Parameters
properties:requiredarray of string (uuid)The ids of the properties to attach. Every id must belong to a property in this project — an id from another project or another workspace fails the whole request with 400 validation_error, and nothing is attached. Nothing is attached partially: either all the ids are valid or none are applied.
The array cannot be empty. Attaching an id the type already exposes is not an error and does not create a duplicate, so retrying a request that may have already landed is safe.
Scopes
projects.work_item_types:write
Errors
| Status | Code | Cause |
|---|---|---|
400 | validation_error | properties missing or empty, or an id that isn't a property in this project. |
401 | unauthorized | Missing or invalid credentials. |
403 | forbidden | Your role or token scope can't edit this project's work item types. |
404 | resource_not_found | No such workspace, project, or type — or it's outside your tenant. |
409 | work_item_types_managed_at_workspace | This workspace manages work item types at the workspace level. See below. |
429 | rate_limited | Throttled. Honor the Retry-After header before retrying. |
Wrong mode is a 409, not a 404
Attaching is a project-mode write. If the workspace manages work item types at the workspace level, this endpoint returns 409 work_item_types_managed_at_workspace — the capability exists, it just lives on the other surface. Attach there instead with Attach a property to a workspace type.
Branch on the code, not the status: a 409 here means "wrong surface", never "already attached". See Work item type modes.
curl -X POST \
"https://api.plane.so/api/v2/workspaces/my-team/projects/4af68566-94a4-4eb3-94aa-50dc9427067b/work-item-types/9d3c7f21-6b48-4e0a-8f52-2c1d7a904e66/properties/" \
-H "X-Api-Key: $PLANE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"properties": [
"c1f0a2d4-73b9-4e6c-8a15-9d0e4b3f7c28",
"5e8b3417-2a6d-4c91-b0f7-8d2e14a6c395"
]
}'import requests
response = requests.post(
"https://api.plane.so/api/v2/workspaces/my-team/projects/4af68566-94a4-4eb3-94aa-50dc9427067b/work-item-types/9d3c7f21-6b48-4e0a-8f52-2c1d7a904e66/properties/",
headers={"X-Api-Key": "your-api-key"},
json={
"properties": [
"c1f0a2d4-73b9-4e6c-8a15-9d0e4b3f7c28",
"5e8b3417-2a6d-4c91-b0f7-8d2e14a6c395",
]
},
)
print(response.json())const response = await fetch(
"https://api.plane.so/api/v2/workspaces/my-team/projects/4af68566-94a4-4eb3-94aa-50dc9427067b/work-item-types/9d3c7f21-6b48-4e0a-8f52-2c1d7a904e66/properties/",
{
method: "POST",
headers: {
"X-Api-Key": "your-api-key",
"Content-Type": "application/json",
},
body: JSON.stringify({
properties: ["c1f0a2d4-73b9-4e6c-8a15-9d0e4b3f7c28", "5e8b3417-2a6d-4c91-b0f7-8d2e14a6c395"],
}),
}
);
const data = await response.json();{
"properties": ["c1f0a2d4-73b9-4e6c-8a15-9d0e4b3f7c28", "5e8b3417-2a6d-4c91-b0f7-8d2e14a6c395"]
}{
"type": "https://api.plane.so/errors/validation_error",
"title": "Validation Error",
"status": 400,
"code": "validation_error",
"detail": "One or more fields failed validation.",
"errors": [
{
"field": "properties",
"message": "This list may not be empty."
}
]
}{
"type": "https://api.plane.so/errors/work_item_types_managed_at_workspace",
"title": "Work Item Types Managed At Workspace",
"status": 409,
"code": "work_item_types_managed_at_workspace",
"detail": "Work item types are managed at the workspace level for this workspace."
}The response is ids, not objects
201 returns a properties array — the ids that are now attached to the type. It does not echo the property definitions. Read them back with List type properties or Get a type property when you need display_name, property_type, or the option list.

