Add or remove project release work items
Change a project release's scope by adding and removing work items in one request. Adding a work item links it to the release without moving or changing it. Removing it only removes the link.
The API runs remove first, then add, and answers with what changed:
removedlists the ids fromremovethat were on the release. Ids that weren't on it are ignored.addedlists every id fromaddthat matched a work item in the workspace that you can see, including work items already on the release. Other ids are skipped without an error.
Compare added with what you sent to find ids that were skipped. To read the scope afterward, use List a project release's work items, or filter the work items list with ?release_id={pk}.
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:requiredstringThe project the release belongs to. Accepts the project UUID or its bare identifier, for example ENG.
pk:requiredstring (uuid)The id of the release to change.
Body Parameters
add:optionalarray of string (uuid)Ids of work items to add to the release. Defaults to an empty array.
remove:optionalarray of string (uuid)Ids of work items to take out of the release. Defaults to an empty array.
Scopes
releases:write
Errors
| Status | Code | Cause |
|---|---|---|
400 | invalid_request | add or remove isn't an array, or an entry isn't a UUID. |
401 | unauthorized | Missing or invalid credentials. |
402 | payment_required | Project releases aren't enabled on your plan. |
403 | forbidden | Your role in the project can't edit this release, or your token scope doesn't allow this. |
404 | not_found | No release with this id in this project, or no such workspace or project. |
406 | not_acceptable | The Accept header asks for a representation the API can't produce. |
409 | conflict | Not raised by this endpoint. The spec lists it for every v2 write. |
413 | payload_too_large | The request body is over the size limit. |
415 | unsupported_media_type | The Content-Type isn't one this endpoint accepts. |
429 | rate_limited | Throttled. Honor the Retry-After header before retrying. |
curl -X POST \
"https://api.plane.so/api/v2/workspaces/my-team/projects/4af68566-94a4-4eb3-94aa-50dc9427067b/releases/3e8a1f52-7c4b-4d9e-a6f1-0b2c5d8e9f14/work-items/" \
-H "X-Api-Key: $PLANE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"add": [
"8f4c2b1e-0d3a-4f7b-9c21-6e5a8b7d4f13",
"3b7d9e40-1c62-4a85-b0f3-9d5c2e6a8471"
],
"remove": ["a7e51d24-3b98-4c6d-9f10-7d2c8e4b5a61"]
}'import requests
response = requests.post(
"https://api.plane.so/api/v2/workspaces/my-team/projects/4af68566-94a4-4eb3-94aa-50dc9427067b/releases/3e8a1f52-7c4b-4d9e-a6f1-0b2c5d8e9f14/work-items/",
headers={"X-Api-Key": "your-api-key"},
json={
"add": [
"8f4c2b1e-0d3a-4f7b-9c21-6e5a8b7d4f13",
"3b7d9e40-1c62-4a85-b0f3-9d5c2e6a8471",
],
"remove": ["a7e51d24-3b98-4c6d-9f10-7d2c8e4b5a61"],
},
)
print(response.json())const response = await fetch(
"https://api.plane.so/api/v2/workspaces/my-team/projects/4af68566-94a4-4eb3-94aa-50dc9427067b/releases/3e8a1f52-7c4b-4d9e-a6f1-0b2c5d8e9f14/work-items/",
{
method: "POST",
headers: {
"X-Api-Key": "your-api-key",
"Content-Type": "application/json",
},
body: JSON.stringify({
add: ["8f4c2b1e-0d3a-4f7b-9c21-6e5a8b7d4f13", "3b7d9e40-1c62-4a85-b0f3-9d5c2e6a8471"],
remove: ["a7e51d24-3b98-4c6d-9f10-7d2c8e4b5a61"],
}),
},
);
const data = await response.json();{
"added": ["8f4c2b1e-0d3a-4f7b-9c21-6e5a8b7d4f13", "3b7d9e40-1c62-4a85-b0f3-9d5c2e6a8471"],
"removed": ["a7e51d24-3b98-4c6d-9f10-7d2c8e4b5a61"]
}
