Project page templates overview
A project page template is a page template that belongs to one project. It has the same shape as a workspace page template, with project_id set to its project. It stores a title, an HTML body, and display settings that Plane copies into a new page.
The project and workspace sets never overlap. A template stays in the scope it was created through, and no write moves it. A project template's id returns 404 on the workspace routes and on another project's routes.
Learn more about page templates
The project page template object
Attributes
idstring (uuid)Unique identifier for the template.
namestringDisplay name of the template, shown in the template picker. Maximum 255 characters.
short_descriptionstringOne-line summary of what the template is for. Nullable.
description_htmlstringLonger description of the template itself, as HTML. The body of the page that the template creates is
template_data.description_html, not this field.template_typestringAlways
pagefor page templates.is_publishedbooleanWhether the template is published. Defaults to
false.short_idstringShort unique id that Plane generates when the template is created, for example
m5v8c1. Filter on it with?short_id=.slugstringURL-safe form of
name. Plane regenerates it whenever the name changes.project_idstring (uuid)The project the template belongs to. Read-only, because the route you create a template through fixes its scope.
template_dataobjectThe page seed, with the keys
name,description_html,color,parent,view_props, andlogo_props. The keys, their defaults, and theparentrules are the same as for workspace page templates. See The template_data object.created_atstring (date-time)When the template was created.
updated_atstring (date-time)When the template was last updated.
created_by_idstring (uuid)The user who created the template.
updated_by_idstring (uuid) or nullThe user who last updated the template.
nulluntil someone updates it.
{
"id": "9e1c7a52-3b4d-4f86-a0d2-5c8e7b1f3a94",
"name": "Incident postmortem",
"short_description": "Timeline, impact, root cause, and follow-ups",
"description_html": "<p>Fill this in within 48 hours of an incident.</p>",
"template_type": "page",
"is_published": false,
"short_id": "m5v8c1",
"slug": "incident-postmortem",
"project_id": "4af68566-94a4-4eb3-94aa-50dc9427067b",
"template_data": {
"name": "Postmortem",
"description_html": "<h2>Timeline</h2><p></p><h2>Impact</h2><p></p><h2>Root cause</h2><p></p><h2>Follow-ups</h2><p></p>",
"color": "#e5484d",
"parent": {
"id": "c2f5a8d1-7e3b-4c96-8a14-0b9d6e2f5c71",
"project_id": "4af68566-94a4-4eb3-94aa-50dc9427067b",
"project_identifier": "ENG"
},
"view_props": {
"full_width": true
},
"logo_props": {}
},
"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
| Method | Path | Description |
|---|---|---|
GET | /api/v2/workspaces/{slug}/projects/{project_id}/page-templates/ | List project page templates |
GET | /api/v2/workspaces/{slug}/projects/{project_id}/page-templates/{pk}/ | Get a project page template |
POST | /api/v2/workspaces/{slug}/projects/{project_id}/page-templates/ | Create a project page template |
PATCH | /api/v2/workspaces/{slug}/projects/{project_id}/page-templates/{pk}/ | Update a project page template |
DELETE | /api/v2/workspaces/{slug}/projects/{project_id}/page-templates/{pk}/ | Delete a project page template |
Workspace governance
Workspace governance is the Enterprise Grid feature where the workspace owns states, workflows, and templates instead of each project. Turning governance on doesn't move existing project page templates. They stay on these routes, where you can still read them, but update and delete return 409 templates_managed_at_workspace, and the workspace page template routes return 404 for them.
In a workspace with governance turned on, the project routes stop accepting writes:
- Create, update, and delete return
409 templates_managed_at_workspace. Create new templates through the workspace page template routes instead. - List and get keep working.
In an ungoverned workspace, every route here works normally. While the governance migration runs, every write in the workspace returns 409 governance_migration_in_progress instead, and reads keep working.
{
"type": "conflict",
"code": "templates_managed_at_workspace",
"detail": "Templates are managed at the workspace level."
}The governance check runs after the existence and permission checks on update and delete, so an unknown id still returns 404 and a missing permission still returns 403. On create it runs before body validation, so a governed workspace returns 409 even when the body is invalid.
Updating template_data
template_data on a PATCH replaces the whole seed. Each omitted key goes back to its default: description_html to <p></p>, color to an empty string, and parent, view_props, and logo_props to {}. template_data.name is required whenever you send template_data. A PATCH without template_data leaves the seed alone.
Feature gating
Page templates are a paid feature. When the workspace's plan doesn't include them, or the feature is switched off, every endpoint except the single-template GET returns 402 payment_required. See Errors.
Response shaping
Every read accepts ?fields= for sparse responses. See Sparse fields.
List rows leave out description_html and template_data by default, because both carry HTML. Name them in ?fields=, or pass ?fields=all, to get them on list rows. A single-template response always includes them. Errors follow the shared problem+json contract.
Changed from v1
- The routes move from
/api/v1/workspaces/{slug}/projects/{project_id}/pages/templates/to/api/v2/workspaces/{slug}/projects/{project_id}/page-templates/. - In a governed workspace, project writes return
409 templates_managed_at_workspace. v1 returned a400with its own error body. - The list is paginated, filterable, and searchable. v1 returned every template in one array.
project_idin the path accepts the project identifier, for exampleENG, as well as the UUID.
See Migrating from v1 for the full list.

