Skip to content

Create a project from a template ​

POST/api/v2/workspaces/{slug}/project-templates/{pk}/use/

Create a new project in this workspace from one of the workspace's project templates. The body takes project create fields. You name the project and give it an identifier, and the template supplies its states, feature toggles, and starter content.

The response is the new project, with 201. Plane creates the project, its members, and its work item states before it responds. Labels, estimates, work item types, modules, and the starter work items come from a background job that runs after the response, so they can take a moment to appear. See What the template applies.

The template doesn't need to be published, but it must belong to this workspace. To use a template published by another workspace, copy it in first.

Path Parameters ​

slug:requiredstring

The workspace slug. It appears in your Plane URLs, so in https://app.plane.so/my-team/projects/ the slug is my-team.

pk:requiredstring (uuid)

The id of the project template to use. A template_id in the body is ignored, and this path id always wins.

Body Parameters ​

name:requiredstring

Name of the new project, unique within the workspace. Maximum 255 characters. It can't contain <, >, ", {, }, [, ], *, ^, !, #, %, or \.

identifier:requiredstring

Short project key used to prefix work item numbers, for example PAY in PAY-12. Unique within the workspace, and stored in upper case. Punctuation such as -, ., @, and # isn't allowed.

description:optionalstring

Plain-text description of the project. When you send only description, Plane builds description_html from it.

description_html:optionalstring

Description as HTML. Plane sanitizes it and fills description from it when you don't send one.

network:optionalinteger

Project visibility. 0 is private to members, 2 is visible to the whole workspace. Defaults to 2.

project_lead:optionalstring (uuid)

User id of the project lead, who must be a workspace member. The lead joins the project as an admin. This endpoint takes project_lead, not the project_lead_id that Create a project takes.

default_assignee:optionalstring (uuid)

User id of the default assignee, who must be a workspace member. Named default_assignee here, not default_assignee_id.

state_id:optionalstring (uuid)

The project's lifecycle state. It must belong to this workspace. When the workspace uses project grouping and the template sets project_state, the template's state replaces this one.

priority:optionalstring

Project priority. One of none, low, medium, high, or urgent.

start_date:optionalstring

Planned start date, as YYYY-MM-DD or a full ISO 8601 date-time. Nullable.

target_date:optionalstring

Planned due date, as YYYY-MM-DD or a full ISO 8601 date-time. Nullable.

timezone:optionalstring

IANA time zone, for example Europe/Berlin. Defaults to UTC.

archive_in:optionalinteger

Months before completed work items are auto-archived, from 0 to 12. 0 turns it off.

close_in:optionalinteger

Months before stale work items are auto-closed, from 0 to 12. 0 turns it off.

logo_props:optionalobject

Editor-owned descriptor for the project icon. When you omit it, Plane picks a random icon and color.

cover_image:optionalstring

URL of a cover image. When you send one, the template's cover isn't copied.

emoji:optionalstring

Emoji shown with the project name. Maximum 255 characters. Nullable.

icon_prop:optionalobject

Legacy icon descriptor. Nullable.

external_id:optionalstring

Your system's identifier for this project, for sync and import correlation. Maximum 255 characters.

external_source:optionalstring

The system external_id came from, for example jira. Maximum 255 characters.

The body also accepts module_view, cycle_view, issue_views_view, page_view, intake_view, is_issue_type_enabled, and is_time_tracking_enabled, but the template's values replace them. These toggles always come from template_data.

Response shaping ​

fields:optionalstring

Comma-separated list of fields to return. Unrequested keys are omitted from the response, not returned as null, so absent means "not requested" and null means "actually null". id always comes back whether or not you name it.

Pass all for every requestable field. An unknown name is a 400 that lists the valid set and suggests the closest match, so a typo can't silently cost you the saving.

Requestable here: archive_in, archived_at, close_in, cover_image, cover_image_url, created_at, created_by_id, cycle_view, default_assignee_id, default_state_id, description, description_html, emoji, estimate_id, external_id, external_source, guest_view_all_features, icon_prop, id, identifier, intake_view, is_issue_type_enabled, is_time_tracking_enabled, issue_views_view, logo_props, module_view, name, network, page_view, priority, project_lead_id, start_date, state_id, target_date, timezone, updated_at, updated_by_id.

See Sparse fields.

expand:optionalstring

Comma-separated relations to embed alongside the ids: default_assignee (the default assignee's user) and project_lead (the lead's user).

Expansion is separate-key: ?expand=project_lead keeps project_lead_id and adds a project_lead object next to it. An unknown value is a 400. See Expanding relations.

Scopes ​

templates.projects:write

Errors ​

StatusCodeCause
400invalid_requestname or identifier is missing or has a forbidden character, the identifier is taken or too long, the lead or default assignee isn't a workspace member, or state_id belongs to another workspace.
401unauthorizedMissing or invalid credentials.
402payment_requiredProject templates aren't in your plan, or the feature is switched off for this workspace.
403forbiddenYour role or token scope can't use project templates, or you can't create projects in this workspace. You need both.
404not_foundNo project template with this id in this workspace.
406not_acceptableThe Accept header asks for a representation the API can't produce.
409governance_migration_in_progressThe workspace is migrating to workspace governance. Writes are blocked until it finishes, so retry later.
413payload_too_largeThe request body is over the size limit.
415unsupported_media_typeThe Content-Type isn't one this endpoint accepts.
429rate_limitedThrottled. Honor the Retry-After header before retrying.
Create a project from a template
bash
curl -X POST \
  "https://api.plane.so/api/v2/workspaces/my-team/project-templates/5b7e3c1a-9d24-4f68-b5a0-2e8c6d4f1b97/use/" \
  -H "X-Api-Key: $PLANE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Payments",
  "identifier": "PAY",
  "description": "Card and bank payment flows",
  "project_lead": "16c61a3a-512a-48ac-b0be-b6b46fe6f430"
}'
Response201
json
{
  "id": "6d2a8f4c-0b7e-4a19-93c5-e8f1b6d4a207",
  "name": "Payments",
  "description": "Card and bank payment flows",
  "description_html": "<p>Card and bank payment flows</p>",
  "identifier": "PAY",
  "network": 2,
  "project_lead_id": "16c61a3a-512a-48ac-b0be-b6b46fe6f430",
  "default_assignee_id": null,
  "default_state_id": null,
  "estimate_id": null,
  "state_id": "0e5b9c3a-7d21-4f86-b4a8-2c6f1e9d7b30",
  "priority": "none",
  "start_date": null,
  "target_date": null,
  "emoji": null,
  "icon_prop": null,
  "logo_props": {
    "in_use": "icon",
    "icon": {
      "name": "rocket",
      "color": "#5e6ad2"
    }
  },
  "cover_image": null,
  "cover_image_url": null,
  "module_view": true,
  "cycle_view": true,
  "issue_views_view": true,
  "page_view": true,
  "intake_view": false,
  "is_time_tracking_enabled": false,
  "is_issue_type_enabled": false,
  "guest_view_all_features": false,
  "archive_in": 0,
  "close_in": 0,
  "timezone": "UTC",
  "archived_at": null,
  "external_id": null,
  "external_source": null,
  "created_at": "2026-02-03T16:45:12.904117Z",
  "updated_at": "2026-02-03T16:45:13.118402Z",
  "created_by_id": "16c61a3a-512a-48ac-b0be-b6b46fe6f430",
  "updated_by_id": null
}
Response400
json
{
  "type": "invalid_request",
  "code": "invalid_request",
  "detail": "One or more fields failed validation.",
  "errors": [
    {
      "field": "non_field_errors",
      "code": "identifier_already_taken",
      "message": "Project Identifier is taken"
    }
  ]
}

What the template applies ​

Before the response, Plane:

  • creates the project from your body and adds you to it as an admin, along with the project lead when the lead is someone else;
  • creates the template's states as the project's work item states;
  • copies the feature toggles module_view, cycle_view, issue_views_view, page_view, intake_view, is_time_tracking_enabled, and is_issue_type_enabled from the template and replaces any you sent;
  • switches project updates, epics, and workflows on or off to match is_project_updates_enabled, is_epic_enabled, and is_workflow_enabled;
  • sets up intake from intake_settings when intake_view is on;
  • copies the template's cover image when it is stored in Plane, unless you sent cover_image;
  • sets the project's lifecycle state from project_state, when the workspace uses project grouping and that state still exists.

After the response, a background job:

  • creates the template's labels and estimates;
  • creates the template's workitem_types and epics, or links the workspace's default work item type when the workspace manages work item types at the workspace level;
  • creates the template's modules when module_view is on;
  • creates one work item per entry in workitems, mapped onto the new states, labels, types, and modules by their template ids.

The project's other settings, such as network, timezone, priority, and its dates, come from your request body, not from the template.

Poll for the starter work items

The background job runs after you get the 201, so an immediate List work items on the new project can return an incomplete list. If your integration needs the seeded work items, poll the list until the count matches the template's workitems.