Skip to content

Workspace page templates overview ​

A page template is a reusable starting point for a page. It stores a title, an HTML body, and display settings that Plane copies into a new page. Workspace page templates belong to the whole workspace. Project page templates belong to one project and have their own routes.

The two sets never overlap. A template stays in the scope it was created through, and no write moves it. A workspace template's id returns 404 on the project routes, and a project template's id returns 404 here.

Learn more about page templates

The page template object ​

Attributes ​

  • id string (uuid)

    Unique identifier for the template.

  • 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 body of the page that the template creates is template_data.description_html, not this field.

  • template_type string

    Always page for page templates.

  • is_published boolean

    Whether the template is published. Defaults to false.

  • short_id string

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

  • slug string

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

  • project_id string (uuid)

    null on a workspace page template. A project page template carries its project's id. Read-only, because the route you create a template through fixes its scope.

  • template_data object

    The page seed. 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 holds what a new page starts with. Every key comes back on read, with its default when you never set it.

  • name string

    Title of the page created from the template. Required whenever you send template_data. Maximum 255 characters.

  • description_html string

    Body of the page, as HTML. Defaults to <p></p>.

  • color string

    Page color, for example #3f76ff. Defaults to an empty string.

  • parent object

    The page that new pages nest under, as {"id", "project_id", "project_identifier"}. Defaults to {}, which means no parent. See Parent validation.

  • view_props object

    Page display settings, for example {"full_width": false}. Defaults to {}.

  • logo_props object

    Editor-owned descriptor for the page icon or emoji. Pass back what you read rather than composing it by hand. Defaults to {}.

Response200
json
{
  "id": "3d8b2f4e-6a1c-4e57-9b02-7c5d1e8f4a36",
  "name": "Weekly sync",
  "short_description": "Agenda and notes for the weekly team sync",
  "description_html": "<p>Use this for the Monday team sync.</p>",
  "template_type": "page",
  "is_published": false,
  "short_id": "k3x9p2",
  "slug": "weekly-sync",
  "project_id": null,
  "template_data": {
    "name": "Weekly sync notes",
    "description_html": "<h2>Agenda</h2><ul><li><p>Updates</p></li><li><p>Blockers</p></li></ul>",
    "color": "#3f76ff",
    "parent": {},
    "view_props": {
      "full_width": false
    },
    "logo_props": {
      "emoji": {
        "value": "128221"
      },
      "in_use": "emoji"
    }
  },
  "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}/page-templates/List workspace page templates
GET/api/v2/workspaces/{slug}/page-templates/{pk}/Get a workspace page template
POST/api/v2/workspaces/{slug}/page-templates/Create a workspace page template
PATCH/api/v2/workspaces/{slug}/page-templates/{pk}/Update a workspace page template
DELETE/api/v2/workspaces/{slug}/page-templates/{pk}/Delete a workspace page template

Parent validation ​

The API checks the shape of template_data.parent and nothing else. A non-empty parent must carry all three keys:

  • id, a UUID
  • project_id, a UUID
  • project_identifier, a string such as ENG

A partial object, for example one with only id, returns 400 invalid_request with errors entries under template_data.parent. The API does not look up the page or the project, so it accepts a well-formed reference to a page that doesn't exist. Send {} or omit parent for no parent.

Updating template_data ​

template_data on a PATCH replaces the whole seed. Send every key you want to keep, because 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 changes only the top-level fields you send and 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 here returns 402 payment_required. See Errors.

Workspace governance ​

Workspace governance doesn't block the workspace routes. In a workspace with governance turned on, these are the routes for creating and changing page templates, because project page template writes return 409 templates_managed_at_workspace. Turning governance on moves existing project page templates to the workspace, so they show up in this list.

While the governance migration runs, every write in the workspace, including these, returns 409 governance_migration_in_progress. Reads keep working.

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}/pages/templates/ to /api/v2/workspaces/{slug}/page-templates/.
  • The list is paginated, filterable, and searchable. v1 returned every template in one array.
  • 402 uses the problem+json body with code: "payment_required".

See Migrating from v1 for the full list.