Modules overview
A module groups work items into a single deliverable inside one project — a launch, a migration, a redesign. Modules belong to exactly one project and are never shared across projects.
Where a cycle answers "what are we doing this sprint", a module answers "what does this piece of work consist of". A work item can sit in a module and a cycle at the same time.
The module object
Attributes
idstring (uuid)Unique identifier for the module.
namestringDisplay name, unique within the project. Maximum 255 characters.
descriptionstringPlain-text summary of what the module covers.
statusstringWhere the module sits in its lifecycle. One of
backlog,planned,in-progress,paused,completed, orcancelled.start_datestring (date)Date the module is scheduled to begin, as
YYYY-MM-DD, ornull.target_datestring (date)Date the module is expected to land, as
YYYY-MM-DD, ornull.lead_idstring (uuid)The project member accountable for the module, or
null.member_idsarray of stringProject members assigned to the module. Read-only in v2 — module membership is not yet writable through the v2 API.
sort_ordernumberOrdering weight used when modules are listed. Lower values sort first.
logo_propsanyFree-form JSON object holding the icon Plane renders for the module.
{}when no icon is set.external_id,external_sourcestringCorrelation fields for sync and import. Together they let you map a module to a record in another system and find it again later.
archived_atstring (date-time)When the module was archived, or
nullfor an active module.created_atstring (date-time)When the module was created.
created_by_idstring (uuid)The user who created the module.
Relations are always ids
Modules do not support ?expand=. lead_id and member_ids come back as ids — resolve them against project members.
{
"id": "7c1f3d90-2a64-4e58-9b0d-3fa1c7e28b45",
"name": "Billing revamp",
"description": "Rework subscription billing end to end.",
"status": "in-progress",
"start_date": "2026-01-05",
"target_date": "2026-02-27",
"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"
}Endpoints
| Method | Path | Description |
|---|---|---|
GET | /api/v2/workspaces/{slug}/projects/{project_id}/modules/ | List modules |
POST | /api/v2/workspaces/{slug}/projects/{project_id}/modules/ | Create a module |
GET | /api/v2/workspaces/{slug}/projects/{project_id}/modules/{pk}/ | Get a module |
PATCH | /api/v2/workspaces/{slug}/projects/{project_id}/modules/{pk}/ | Update a module |
DELETE | /api/v2/workspaces/{slug}/projects/{project_id}/modules/{pk}/ | Delete a module |
Status
status is the module's lifecycle position and is validated on both writes and the status filter — a value outside the enum is a 400 validation_error, never a silently ignored write or an empty list.
| Value | Meaning |
|---|---|
backlog | Captured, not yet committed to |
planned | Committed to but not started |
in-progress | Actively being worked on |
paused | Started, then put on hold |
completed | Delivered |
cancelled | Dropped without delivering |
A module created without a status starts as planned.
Lead and members
lead_id must be a member of the module's project. Passing a user who isn't a project member is rejected with 400 validation_error naming lead_id — the link is never made silently.
member_ids is read-only. Reads return the module's current members, but there is no v2 write path for adding or removing them yet.
Dates
start_date and target_date are plain dates (YYYY-MM-DD), and either can be null. A target_date earlier than start_date is rejected with 400 validation_error.
Names are unique per project
Two modules in the same project cannot share a name. A duplicate on create — or on a rename via PATCH — returns 409 conflict.
Not yet in v2
Module work-item management (listing the work items in a module, adding them, removing them) and archive/unarchive are still only available in v1. See the v1 module reference for those routes; the v2 endpoints above cover module CRUD only.
Changed from v1
leadis nowlead_id,membersis nowmember_ids, andcreated_byis nowcreated_by_id.member_idsis read-only.- Reads no longer return
updated_at,updated_by,project,workspace,view_props,description_text, ordescription_html. PUTis gone — updates arePATCHand partial.
See Migrating from v1 for the full list.

