---
title: "Create a template"
method: POST
path: "/v1/templates"
tags: ["Templates"]
---

# Create a template

`POST /v1/templates`

## Request

- Base URL: `https://api-eu.dynamicdocumentapi.com`
- URL: `https://api-eu.dynamicdocumentapi.com/v1/templates`
- Auth: one of:
  - HTTP bearer
  - API key in header `X-API-Key`

Creates a `pdf_code`, `pdf_markdown` or `image_canvas` template. The content fields depend on `type` (any type may send one `content` object instead); they land in the draft — publish it to get a live version.

## Headers

- `Idempotency-Key` string

## Request body

- union: `POST /v1/templates`: the content fields depend on `type`; any type may instead send one `content` object.
  - PdfCodeTemplateCreate
    - `content` object: The whole content in one object, instead of the separate fields.
    - `datasets` object[]: Sample data sets `{name, data, is_default}` (rendered when publishing).
    - `description` string
    - `head` string: Extra `<head>` markup (styles, fonts).
    - `header_footer` object: `{header, footer}`: header/footer objects as in `PdfOptions`.
    - `html` string: Jinja HTML of the body.
    - `name` string, required
    - `options` object: Default output options (`RenderOptions`: `output_format`, `filename`, `pdf` as in `PdfOptions`, `image`, `strict_undefined`, and for PDF templates `einvoice: {profile, invoice_path}`, a default hybrid e-invoice that every render embeds unless the request sends `output.einvoice`).
    - `schema` object, nullable: JSON Schema.
    - `type` 'pdf_code', required
  - PdfMarkdownTemplateCreate
    - `content` object: The whole content in one object, instead of the separate fields.
    - `css` string
    - `datasets` object[]: Sample data sets `{name, data, is_default}` (rendered when publishing).
    - `description` string
    - `head` string
    - `header_footer` object: `{header, footer}`: header/footer objects as in `PdfOptions`.
    - `markdown` string: Jinja-enabled Markdown.
    - `name` string, required
    - `options` object: Default output options (`RenderOptions`: `output_format`, `filename`, `pdf` as in `PdfOptions`, `image`, `strict_undefined`, and for PDF templates `einvoice: {profile, invoice_path}`, a default hybrid e-invoice that every render embeds unless the request sends `output.einvoice`).
    - `schema` object, nullable: JSON Schema.
    - `theme` string: `default`, `github`, `academic`, `minimal` or `none`.
    - `type` 'pdf_markdown', required
  - ImageCanvasTemplateCreate
    - `content` object: The whole content in one object, instead of the separate fields.
    - `datasets` object[]: Sample data sets `{name, data, is_default}` (rendered when publishing).
    - `description` string
    - `name` string, required
    - `options` object: Default output options (`RenderOptions`: `output_format`, `filename`, `pdf` as in `PdfOptions`, `image`, `strict_undefined`, and for PDF templates `einvoice: {profile, invoice_path}`, a default hybrid e-invoice that every render embeds unless the request sends `output.einvoice`).
    - `scene` object: The canvas scene as defined by `@dynamic-document-api/scene-schema`.
    - `schema` object, nullable: JSON Schema.
    - `type` 'image_canvas', required

## Response `201`

- ManagedTemplate: `POST /v1/templates` and `POST /v1/templates/{id}/rollback`. The read endpoints (`GET /v1/templates*`) answer from the regional mirror and use the `Template` schema; this is the control-plane representation, which also carries the draft revision.
  - `created_at` string, date-time, required
  - `default_options` object, nullable, required: Output options of the live version.
  - `deleted_at` string, date-time, nullable, required
  - `description` string, required
  - `draft_revision` integer, required
  - `engine` string, required: Engine channel, e.g. `2026.4`.
  - `folder` TemplateFolder, required
    - `id` string, required
    - `name` string, required
  - `id` string, required: `tpl_…`
  - `live_version` TemplateWriteVersion, required
    - `id` string, required
    - `note` string, required
    - `number` integer, required
    - `published_at` string, date-time, nullable, required
  - `name` string, required
  - `object` string
  - `tags` string[], required
  - `thumbnail_url` string, uri, nullable, required
  - `type` 'pdf_code' | 'pdf_markdown' | 'image_canvas' | 'docx' | 'pdf_form', required: * `pdf_code` - pdf_code * `pdf_markdown` - pdf_markdown * `image_canvas` - image_canvas * `docx` - docx * `pdf_form` - pdf_form
  - `updated_at` string, date-time, required

## Other responses

- `400`: Invalid request body (`errors[]` with JSON pointers).
- `401`: Missing, invalid, expired or revoked credentials.
- `403`: Insufficient scope, IP not allowed, workspace suspended or scheduled for deletion, or email not verified; or `template_not_allowed_for_key`: the key is restricted to specific templates.
- `429`: Rate limited (`Retry-After`).
- `503`: The control plane is unreachable (`Retry-After`).

---

[API](https://skmtc.dev/dynamicdocumentapi/apis/dynamic-document-api.md) · [All operations](https://skmtc.dev/dynamicdocumentapi/apis/dynamic-document-api/llms.txt) · [OpenAPI document](https://skmtc.dev/dynamicdocumentapi/apis/dynamic-document-api/revisions/0f14bc0000f4?raw)
