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

# Create a template

`POST /templates`

## Request

- Base URL: `https://sending.dev/api/v1`
- URL: `https://sending.dev/api/v1/templates`
- Auth: HTTP bearer

Email: `subject` is mandatory and `format` is one of markdown, html (default) and blocks; with `blocks` the `body` is the JSON of an EmailDoc, the same document as the visual editor. WhatsApp and Telegram: `format` is always text and there is no subject. `{{...}}` variables are derived from the content and are not declared. The name is unique in the workspace: on a duplicate the response is 409 `template_exists` with the existing `templateId`, to reuse or to fix with PATCH. Required scope: `templates:write`.

## Request body

- CreateTemplateInput
  - `name` string, required: Unique within the workspace.
  - `body` string, required: Base content. With format 'blocks' it is the JSON of an EmailDoc (the visual editor document).
  - `channels` string[]: Channels the template can be used on. Default: ['email'].
  - `format` 'markdown' | 'html' | 'text' | 'blocks': Email: markdown, html or blocks (default html). WhatsApp/Telegram: always text.
  - `subject` string: Required if the template includes the email channel.
  - `channelText` object: Alternative text for WhatsApp/Telegram: without an override the base body is degraded to plain text.
    - `whatsapp` string
    - `telegram` string

## Response `201`

Template created.

- object
  - `template` Template, required
    - `id` string, uuid, required
    - `name` string, required
    - `channel` 'email' | 'whatsapp' | 'telegram', required: Derived primary channel (email wins when enabled).
    - `channels` string[], required
    - `format` 'markdown' | 'html' | 'text' | 'blocks', required
    - `subject` string, nullable, required
    - `variables` string[], required: {{...}} variables found in the content. Derived, not declared.
    - `createdAt` string, date-time
    - `updatedAt` string, date-time
    - `body` string, required
    - `channelText` object, nullable, required: Text overrides for chat channels.
      - `whatsapp` string
      - `telegram` string
  - `warnings` string[]: Non-blocking warnings: present only when there is something to report, e.g. {{...}} variables that match no contact field.

## Other responses

- `401`: Missing or invalid token.
- `403`: Insufficient scope.
- `409`: State conflict (e.g. duplicate).
- `422`: Invalid input.

---

[API](https://skmtc.dev/sending/apis/sending-dev-api.md) · [All operations](https://skmtc.dev/sending/apis/sending-dev-api/llms.txt) · [OpenAPI document](https://skmtc.dev/sending/apis/sending-dev-api/revisions/9fe78d2918a1?raw)
