Update a cycle
Change a cycle in place — rename it, reschedule it, or attach correlation ids after an import.
The update is partial. Fields you omit are left untouched, and omitting a field is not the same as sending null: send "end_date": null to clear a date, omit end_date to keep it.
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 cycle belongs to.
pk:requiredstring (uuid)The cycle to update.
Body Parameters
name:optionalstringNew display name, unique within the project. Maximum 255 characters. Renaming onto a name another cycle already holds returns 409 conflict.
description:optionalstringFree-form description of what the cycle covers.
start_date:optionalstring (date-time)New opening date-time, in ISO 8601. Send null to unschedule the start.
end_date:optionalstring (date-time)New closing date-time, in ISO 8601. Send null to unschedule the end.
timezone:optionalstringThe IANA time zone the cycle's dates are interpreted in, for example America/New_York or UTC. Changing it re-anchors where the existing boundaries fall locally, so send it together with the dates when you are moving a cycle between regions. Any value outside the IANA list is rejected with 400 validation_error.
sort_order:optionalnumberOrdering weight for the cycle within the project. Lower values sort first when you list with ?order_by=sort_order.
logo_props:optionalanyJSON blob holding the cycle's icon configuration. Replaces the stored value outright — it is not merged key by key.
external_id:optionalstringYour system's identifier for this cycle. Maximum 255 characters, nullable.
external_source:optionalstringThe system external_id came from, for example jira. Maximum 255 characters, nullable.
There is no PUT
v2 updates are PATCH only. A PUT to this path returns 405 method_not_allowed. Audit fields such as created_at, created_by_id, and owned_by_id are read-only — including them has no effect.
Scopes
projects.cycles:write
Errors
| Status | Code | Cause |
|---|---|---|
400 | validation_error | A name over 255 characters, an unparseable date, or a timezone outside the IANA list. |
401 | unauthorized | Missing or invalid credentials. |
403 | forbidden | Your role or token scope can't update cycles in this project. |
404 | resource_not_found | No such cycle, wrong project, or the record is outside your tenant. |
409 | conflict | Another cycle in the project already uses this name. |
429 | rate_limited | Throttled. Honor the Retry-After header before retrying. |
curl -X PATCH \
"https://api.plane.so/api/v2/workspaces/my-team/projects/4af68566-94a4-4eb3-94aa-50dc9427067b/cycles/7c1f9a4e-3b6d-4a52-8f0c-2d9e6b18c3a7/" \
-H "X-Api-Key: $PLANE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Sprint 24 (extended)",
"end_date": "2026-01-26T00:00:00Z"
}'import requests
response = requests.patch(
"https://api.plane.so/api/v2/workspaces/my-team/projects/4af68566-94a4-4eb3-94aa-50dc9427067b/cycles/7c1f9a4e-3b6d-4a52-8f0c-2d9e6b18c3a7/",
headers={"X-Api-Key": "your-api-key"},
json={
"name": "Sprint 24 (extended)",
"end_date": "2026-01-26T00:00:00Z",
},
)
print(response.json())const response = await fetch(
"https://api.plane.so/api/v2/workspaces/my-team/projects/4af68566-94a4-4eb3-94aa-50dc9427067b/cycles/7c1f9a4e-3b6d-4a52-8f0c-2d9e6b18c3a7/",
{
method: "PATCH",
headers: {
"X-Api-Key": "your-api-key",
"Content-Type": "application/json",
},
body: JSON.stringify({
name: "Sprint 24 (extended)",
end_date: "2026-01-26T00:00:00Z",
}),
}
);
const data = await response.json();{
"id": "7c1f9a4e-3b6d-4a52-8f0c-2d9e6b18c3a7",
"name": "Sprint 24 (extended)",
"description": "Checkout rewrite and billing cleanup",
"start_date": "2026-01-05T00:00:00Z",
"end_date": "2026-01-26T00:00:00Z",
"timezone": "America/New_York",
"owned_by_id": "16c61a3a-512a-48ac-b0be-b6b46fe6f430",
"sort_order": 65535,
"logo_props": {},
"external_id": null,
"external_source": null,
"created_at": "2026-01-14T09:22:41.478363Z",
"created_by_id": "16c61a3a-512a-48ac-b0be-b6b46fe6f430"
}{
"type": "https://api.plane.so/errors/validation_error",
"title": "Validation Error",
"status": 400,
"code": "validation_error",
"detail": "The request body failed validation.",
"errors": [
{
"field": "timezone",
"message": "\"America/Atlantis\" is not a valid choice."
}
]
}
