Skip to content

Project templates overview ​

A project template describes a project before it exists: its feature toggles, work item states, labels, work item types, estimates, intake settings, and a list of starter work items. Use a project template to create a real project from it.

Project templates belong to the workspace. There is no project-level variant, because a project template describes a project rather than living in one.

Learn more about project templates

The project template object ​

Attributes ​

  • id string (uuid)

    Unique identifier for the template. This is the id that use and copy take.

  • name string

    Display name of the template, shown in the template picker. Maximum 255 characters.

  • short_description string

    One-line summary of what the template is for. Nullable.

  • description_html string

    Longer description of the template itself, as HTML. The description of the project it creates is template_data.description.

  • template_type string

    Always project for project templates.

  • is_published boolean

    Whether the template is published. Defaults to false. Only published templates can be pulled into a workspace with Copy a project template.

  • is_verified boolean

    Whether Plane has verified the template. Plane sets it, so you can filter on it but not write it.

  • short_id string

    Short unique id that Plane generates when the template is created, for example p7m2qa. Filter on it with ?short_id=.

  • slug string

    URL-safe form of name. Plane regenerates it whenever the name changes.

  • category_ids array of string (uuid)

    The template categories the template is tagged with. Read-only here. Filter on them with ?category_id= or ?category_id__in=.

  • template_data object

    The project seed and its bundled work items. See The template_data object. null only if the seed row is missing.

  • created_at string (date-time)

    When the template was created.

  • updated_at string (date-time)

    When the template was last updated.

  • created_by_id string (uuid)

    The user who created the template.

  • updated_by_id string (uuid)

    The user who last updated the template.

The template_data object ​

template_data is the project the template creates. Every key comes back on read, with the model default when you never set it. Ids inside it, such as a state's id, are your own identifiers for the template. use maps them onto the rows it creates, so point a work item seed's state.id at an entry in states.

  • id string (uuid)

    Id of the seed row. Read-only, and different from the template's id.

  • name string

    Name of the project the template describes. Required whenever you send template_data. Maximum 255 characters, and unique among the workspace's project templates.

  • description string

    Description of the project.

  • network integer

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

  • default_assignee, project_lead object

    Stored as sent. Defaults to {}.

  • logo_props object

    Editor-owned descriptor for the project icon. Defaults to {}.

  • cover_asset string

    Cover image, as an external URL or a Plane asset path. An empty string means no cover.

  • module_view, cycle_view, issue_views_view, page_view boolean

    Feature toggles for modules, cycles, views, and pages. Each defaults to true.

  • intake_view, is_time_tracking_enabled, is_issue_type_enabled, is_project_updates_enabled, is_epic_enabled, is_workflow_enabled, is_milestone_enabled, guest_view_all_features boolean

    Feature toggles for intake, time tracking, work item types, project updates, epics, workflows, milestones, and guest access to all features. Each defaults to false.

  • timezone string

    IANA time zone, for example America/New_York. Defaults to UTC.

  • archive_in, close_in integer

    Months before completed work items are auto-archived and before stale work items are auto-closed. From 0 to 12, where 0 turns the automation off. Defaults to 0.

  • states array of object

    The project's work item states. Each entry needs id (a UUID you choose), name, color, sequence (a number), and group (one of backlog, unstarted, started, completed, cancelled, or triage). description and default are optional.

  • priority string

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

  • project_state object

    The project's lifecycle state, as {"id", "name", "group"}. Defaults to {}.

  • start_date, target_date string (date-time)

    Planned dates. Nullable.

  • labels array of object

    Work item labels, each with id, name, and color (at most 7 characters, for example #3f76ff).

  • estimates object

    An estimate as {"id", "name", "type", "points"}, where each point has id, key (0 to 12), and value.

  • workitem_types array of object

    Work item type definitions, each with id, name, logo_props, is_epic, and properties. description, is_default, and is_active are optional.

  • epics object

    The epic type, with id, name, and properties.

  • members array of object

    Members as {"id"} entries. Defaults to [].

  • intake_settings object

    is_in_app_enabled, is_email_enabled, and is_form_enabled booleans.

  • workflows, milestones, modules, recurring_work_items, automations object or array

    Stored as sent. Each defaults to {}.

  • workitems array of object

    The starter work items, in creation order. Each has name (required), description_html, priority, state ({"id", "name", "group"}), assignees, labels, type, modules, and properties. See Bundled work items.

Response200
json
{
  "id": "5b7e3c1a-9d24-4f68-b5a0-2e8c6d4f1b97",
  "name": "Service launch",
  "short_description": "States, labels, and starter work items for a new service",
  "description_html": "<p>Use this for every new backend service.</p>",
  "template_type": "project",
  "is_published": false,
  "is_verified": false,
  "short_id": "p7m2qa",
  "slug": "service-launch",
  "category_ids": [],
  "template_data": {
    "id": "e4a9c2f7-1b38-4d5e-9f60-7a2c8b3d1e45",
    "name": "Service project",
    "description": "Bootstraps a new backend service",
    "network": 2,
    "default_assignee": {},
    "project_lead": {},
    "logo_props": {},
    "cover_asset": "",
    "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,
    "is_project_updates_enabled": false,
    "is_epic_enabled": false,
    "is_workflow_enabled": false,
    "is_milestone_enabled": false,
    "guest_view_all_features": false,
    "timezone": "UTC",
    "archive_in": 0,
    "close_in": 0,
    "states": [
      {
        "id": "a1f4c7e2-5b8d-4e19-9c63-2f7a0d4b8e15",
        "name": "Backlog",
        "color": "#a3a3a3",
        "group": "backlog",
        "default": true,
        "sequence": 15000
      },
      {
        "id": "c8e3f1b5-7a24-4d96-b0e1-4a6d8c2f9b37",
        "name": "Done",
        "color": "#16a34a",
        "group": "completed",
        "default": false,
        "sequence": 25000
      }
    ],
    "priority": "high",
    "project_state": {},
    "start_date": null,
    "target_date": null,
    "labels": [
      {
        "id": "d4b7a2e9-1f63-4c85-9e02-6b3d8f1a7c54",
        "name": "infra",
        "color": "#3f76ff"
      }
    ],
    "workflows": {},
    "estimates": {},
    "workitem_types": {},
    "epics": {},
    "members": [],
    "intake_settings": {},
    "milestones": {},
    "modules": {},
    "recurring_work_items": {},
    "automations": {},
    "workitems": [
      {
        "name": "Set up CI",
        "description_html": "<p>Build, test, and deploy on every merge.</p>",
        "priority": "high",
        "state": {
          "id": "a1f4c7e2-5b8d-4e19-9c63-2f7a0d4b8e15",
          "name": "Backlog",
          "group": "backlog"
        },
        "assignees": [],
        "labels": [
          {
            "id": "d4b7a2e9-1f63-4c85-9e02-6b3d8f1a7c54",
            "name": "infra",
            "color": "#3f76ff"
          }
        ],
        "type": {},
        "modules": [],
        "properties": []
      }
    ]
  },
  "created_at": "2026-01-14T09:22:41.478363Z",
  "updated_at": "2026-01-14T09:22:41.478363Z",
  "created_by_id": "16c61a3a-512a-48ac-b0be-b6b46fe6f430",
  "updated_by_id": null
}

Endpoints ​

MethodPathDescription
GET/api/v2/workspaces/{slug}/project-templates/List project templates
GET/api/v2/workspaces/{slug}/project-templates/{pk}/Get a project template
POST/api/v2/workspaces/{slug}/project-templates/Create a project template
PATCH/api/v2/workspaces/{slug}/project-templates/{pk}/Update a project template
DELETE/api/v2/workspaces/{slug}/project-templates/{pk}/Delete a project template
POST/api/v2/workspaces/{slug}/project-templates/copy/Copy a published project template
POST/api/v2/workspaces/{slug}/project-templates/{pk}/use/Create a project from a template

Shape checks ​

The JSON keys inside template_data are free-form in storage, so create and update check their shape before saving. states, project_state, labels, estimates, workitem_types, epics, intake_settings, and members are checked against the shapes listed above, and so are the state, type, assignees, labels, modules, and properties of every work item seed. A failure returns 400 invalid_request and saves nothing. The detail is Invalid template data. for the project keys, or Invalid work item template at index N. for the seed at position N in workitems.

The checks cover shape only. They don't confirm that a referenced user, label, or state exists anywhere in Plane.

Bundled work items ​

template_data.workitems is a list that you always write as a whole:

  • On create, the list you send becomes the template's work items. Omit it for none.
  • On update, sending template_data replaces the stored list with the one you send. The old seeds are deleted, never merged. If your template_data has no workitems key, the template ends up with no work items.
  • An update without template_data leaves the work items alone.

To add one work item, read the template, append to the workitems you got back, and send the full template_data.

Updating template_data ​

The other keys in template_data merge on update. A key you send overwrites the stored value, and a key you omit keeps it, with three exceptions:

  • workitems is replaced as described above.
  • members resets to [] when you omit it.
  • cover_asset resets to an empty string when you omit it or send null.

template_data.name is required whenever you send template_data, even when you aren't changing it.

Copy and use ​

  • Copy a project template pulls a published template, from this workspace or another one, into this workspace as a new unpublished template. It returns the new template.
  • Create a project from a template creates a real project in this workspace from one of this workspace's templates. It returns the new project.

Feature gating ​

Project templates are a paid feature. When the workspace's plan doesn't include them, or the feature is switched off, every endpoint here returns 402 payment_required. See Errors.

Workspace governance doesn't block these routes. While a governance migration runs, every write in the workspace, including these, returns 409 governance_migration_in_progress.

Response shaping ​

Every read accepts ?fields= for sparse responses. See Sparse fields.

List rows leave out description_html and template_data by default. template_data carries the whole project seed and every bundled work item, so it is the expensive part of a row. Name either field in ?fields=, or pass ?fields=all, to get it on list rows. A single-template response always includes both. Errors follow the shared problem+json contract.

Changed from v1 ​

  • The routes move from /api/v1/workspaces/{slug}/projects/templates/ to /api/v2/workspaces/{slug}/project-templates/.
  • use takes the template id in the path, at /project-templates/{pk}/use/. v1 took template_id in the body of /projects/templates/use/.
  • copy returns the full new template with 201. v1 returned only {"template_id": ...}.
  • The list is paginated, filterable, and searchable. v1 returned every template in one array.
  • template_data doesn't carry a workspace key.

See Migrating from v1 for the full list.