Update a module
Update a module in place — move it to in-progress, hand it to a new lead, push out its target date.
The update is partial: fields you omit are untouched. Omitting a field is not the same as sending null, which clears a nullable field.
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 module belongs to.
pk:requiredstring (uuid)The module to update.
Body Parameters
name:optionalstringNew display name, unique within the project. Maximum 255 characters. Renaming onto an existing module's name returns 409 conflict.
description:optionalstringPlain-text summary of what the module covers.
status:optionalstringMove the module to a different lifecycle position.
backlog— Captured, not yet committed toplanned— Committed to but not startedin-progress— Actively being worked onpaused— Started, then put on holdcompleted— Deliveredcancelled— Dropped without delivering
Any value outside this list is a 400 validation_error. Transitions are unrestricted — a completed module can be sent back to in-progress.
start_date:optionalstring (date)Date the module is scheduled to begin, as YYYY-MM-DD. Send null to clear it.
target_date:optionalstring (date)Date the module is expected to land, as YYYY-MM-DD. Send null to clear it. Must not be earlier than the module's start_date — including the start_date already stored when you only send target_date.
lead_id:optionalstring (uuid)Reassign the module. Must be a member of this project — any other user id is rejected with a 400 naming lead_id. Send null to leave the module without a lead.
sort_order:optionalnumberOrdering weight used when modules are listed. Lower values sort first.
logo_props:optionalanyFree-form JSON object holding the icon Plane renders for the module. The value you send replaces the stored object.
external_id:optionalstringYour system's identifier for this module, for sync and import correlation. Maximum 255 characters. Nullable.
external_source:optionalstringThe system external_id came from, for example github or jira. Maximum 255 characters. Nullable.
No PUT
v2 has no PUT. Sending one returns 405 method_not_allowed — use PATCH with only the fields you want to change.
member_ids, archived_at, and the audit fields are read-only. Sending them has no effect.
Scopes
projects.modules:write
Errors
| Status | Code | Cause |
|---|---|---|
400 | validation_error | A status outside the enum, a lead_id who isn't a project member, or a target_date before start_date. |
401 | unauthorized | Missing or invalid credentials. |
403 | forbidden | Your role or token scope can't edit this module. |
404 | resource_not_found | No such module, workspace, or project, or it's outside your tenant. |
409 | conflict | Another module in the project already uses this name. |
429 | rate_limited | Throttled. Wait for the interval in Retry-After and retry. |
curl -X PATCH \
"https://api.plane.so/api/v2/workspaces/my-team/projects/4af68566-94a4-4eb3-94aa-50dc9427067b/modules/7c1f3d90-2a64-4e58-9b0d-3fa1c7e28b45/" \
-H "X-Api-Key: $PLANE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"status": "paused",
"target_date": "2026-03-13"
}'import requests
response = requests.patch(
"https://api.plane.so/api/v2/workspaces/my-team/projects/4af68566-94a4-4eb3-94aa-50dc9427067b"
"/modules/7c1f3d90-2a64-4e58-9b0d-3fa1c7e28b45/",
headers={"X-Api-Key": "your-api-key"},
json={"status": "paused", "target_date": "2026-03-13"},
)
print(response.json())const response = await fetch(
"https://api.plane.so/api/v2/workspaces/my-team/projects/4af68566-94a4-4eb3-94aa-50dc9427067b/modules/7c1f3d90-2a64-4e58-9b0d-3fa1c7e28b45/",
{
method: "PATCH",
headers: {
"X-Api-Key": "your-api-key",
"Content-Type": "application/json",
},
body: JSON.stringify({
status: "paused",
target_date: "2026-03-13",
}),
}
);
const data = await response.json();{
"id": "7c1f3d90-2a64-4e58-9b0d-3fa1c7e28b45",
"name": "Billing revamp",
"description": "Rework subscription billing end to end.",
"status": "paused",
"start_date": "2026-01-05",
"target_date": "2026-03-13",
"lead_id": "16c61a3a-512a-48ac-b0be-b6b46fe6f430",
"member_ids": ["16c61a3a-512a-48ac-b0be-b6b46fe6f430", "9d3e1f27-8b4c-4a06-95f1-2c7ea45b0d18"],
"sort_order": 65535.0,
"logo_props": {},
"external_id": null,
"external_source": null,
"archived_at": 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": "lead_id", "message": "Invalid pk \"b4d70c11-9e35-4a2f-8d6c-1f0ab3e97c52\" - object does not exist." }
]
}
