> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lettr.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Create Template

> Create a new email template with HTML or Topol editor JSON content. Automatically creates and publishes a template version with extracted merge tags.

Creates a new email template with either HTML or JSON content. Provide `html` for raw HTML templates or `json` for visual editor (Topol) templates — these fields are mutually exclusive.

The template is automatically assigned a URL-friendly slug based on its name. You can optionally assign it to a specific project and folder using `project_id` and `folder_id`. If omitted, the template is added to your team's default project.


## OpenAPI

````yaml POST /templates
openapi: 3.1.0
info:
  title: Lettr API
  version: 1.0.0
  description: >-
    Lettr Email API - Send transactional emails with tracking, attachments, and
    personalization.
  contact:
    name: Lettr Support
    url: https://lettr.com
  license:
    name: Proprietary
    url: https://lettr.com/terms
servers:
  - url: https://app.lettr.com/api
    description: Production
security: []
tags:
  - name: Emails
    description: Email sending operations
  - name: Templates
    description: Email template management operations
  - name: Domains
    description: Domain management operations
  - name: Webhooks
    description: Webhook management operations
  - name: Audience
    description: 'Audience management: lists, contacts, topics, properties, and segments'
  - name: Campaigns
    description: >-
      Campaign operations: listing, stats, engagement events, and
      dispatch/scheduling
paths:
  /templates:
    post:
      tags:
        - Templates
      summary: Create Template
      description: >-
        Create a new email template with HTML or Topol editor JSON content.
        Automatically creates and publishes a template version with extracted
        merge tags.
      operationId: createTemplate
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateTemplateRequest'
            examples:
              with_json:
                summary: Create with Topol JSON
                value:
                  name: Welcome Email
                  json: >-
                    {"tagName":"mj-container","children":[{"tagName":"mj-text","content":"Hello
                    {{FIRST_NAME}}!"}]}
              with_html:
                summary: Create with custom HTML
                value:
                  name: Newsletter
                  html: >-
                    <html><body><p>Hello {{NAME}}, your order {{ORDER_ID}} is
                    ready!</p></body></html>
              with_project_and_folder:
                summary: Create in specific project and folder
                value:
                  name: Invoice Email
                  project_id: 5
                  folder_id: 10
                  html: >-
                    <html><body><p>Invoice for
                    {{CUSTOMER_NAME}}</p></body></html>
      responses:
        '201':
          description: Template created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateTemplateResponse'
              example:
                message: Template created successfully.
                data:
                  id: 123
                  name: Welcome Email
                  slug: welcome-email
                  project_id: 5
                  folder_id: 10
                  active_version: 1
                  merge_tags:
                    - key: FIRST_NAME
                      required: true
                  created_at: '2026-01-28T12:00:00+00:00'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          description: Project or folder not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                project_not_found:
                  summary: Project not found
                  value:
                    message: >-
                      Project with ID '123' was not found or you don't have
                      access to it.
                    error_code: not_found
                no_default_project:
                  summary: No default project configured
                  value:
                    message: No default project is configured for this team.
                    error_code: not_found
                folder_not_found:
                  summary: Folder not found
                  value:
                    message: >-
                      Folder with ID '456' was not found in the specified
                      project.
                    error_code: not_found
                no_folders:
                  summary: No folders in project
                  value:
                    message: >-
                      Project with ID '123' has no folders. Please create a
                      folder first.
                    error_code: not_found
        '422':
          description: Validation error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidationErrorResponse'
              examples:
                name_required:
                  summary: Name is required
                  value:
                    message: Validation failed.
                    error_code: validation_error
                    errors:
                      name:
                        - The name field is required.
                no_content:
                  summary: No content provided
                  value:
                    message: Validation failed.
                    error_code: validation_error
                    errors:
                      html:
                        - Either html or json content is required.
                both_content:
                  summary: Both html and json provided
                  value:
                    message: Validation failed.
                    error_code: validation_error
                    errors:
                      json:
                        - >-
                          The json and html fields are mutually exclusive.
                          Provide only one.
                invalid_json:
                  summary: Invalid JSON syntax
                  value:
                    message: Validation failed.
                    error_code: validation_error
                    errors:
                      json:
                        - The provided JSON is not valid.
        '500':
          description: Server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                message: Failed to create template. Please try again later.
                error_code: send_error
      security:
        - bearerAuth: []
components:
  schemas:
    CreateTemplateRequest:
      type: object
      description: >-
        Request to create a new email template. Provide either `html` for custom
        HTML templates or `json` for Topol visual editor templates.
      required:
        - name
      properties:
        name:
          type: string
          maxLength: 255
          description: Name of the template
          example: Welcome Email
        project_id:
          type: integer
          minimum: 1
          description: >-
            Project ID to create the template in. If not provided, uses the
            team's default project.
          example: 5
        folder_id:
          type: integer
          minimum: 1
          description: >-
            Folder ID to create the template in. If not provided, uses the first
            folder in the project.
          example: 10
        html:
          type: string
          description: >-
            HTML content for custom HTML templates. Required if `json` is not
            provided. Mutually exclusive with `json`.
          example: <html><body><p>Hello {{NAME}}!</p></body></html>
        json:
          type: string
          description: >-
            JSON content for Topol visual editor templates. Required if `html`
            is not provided. Mutually exclusive with `html`.
          example: >-
            {"tagName":"mj-container","children":[{"tagName":"mj-text","content":"Hello
            {{FIRST_NAME}}!"}]}
    CreateTemplateResponse:
      type: object
      description: Response after successfully creating a template
      required:
        - message
        - data
      properties:
        message:
          type: string
          description: Human-readable response message
          example: Template created successfully.
        data:
          $ref: '#/components/schemas/CreatedTemplateView'
    ErrorResponse:
      type: object
      required:
        - message
        - error_code
      description: Error response for non-validation errors (400, 409, 500, 502).
      properties:
        message:
          type: string
          description: Human-readable error message
          example: The sender domain could not be determined from the email address.
        error_code:
          $ref: '#/components/schemas/ErrorCode'
    ValidationErrorResponse:
      type: object
      required:
        - message
        - error_code
        - errors
      properties:
        message:
          type: string
          description: Human-readable error message
          example: Validation failed.
        error_code:
          type: string
          description: Error code (always `validation_error` for 422 responses)
          const: validation_error
          example: validation_error
        errors:
          type: object
          description: Field-specific validation errors
          additionalProperties:
            type: array
            items:
              type: string
          example:
            from:
              - The sender email address is required.
            to:
              - At least one recipient email address is required.
    CreatedTemplateView:
      type: object
      description: View of a newly created template
      required:
        - id
        - name
        - slug
        - project_id
        - folder_id
        - active_version
        - merge_tags
        - created_at
      properties:
        id:
          type: integer
          description: Unique identifier for the template
          example: 123
        name:
          type: string
          description: Name of the template
          example: Welcome Email
        slug:
          type: string
          description: URL-friendly identifier for the template
          example: welcome-email
        project_id:
          type: integer
          description: ID of the project containing this template
          example: 5
        folder_id:
          type: integer
          description: ID of the folder containing this template
          example: 10
        active_version:
          type: integer
          description: Version number of the active template version
          example: 1
        merge_tags:
          type: array
          description: List of merge tags extracted from the template content
          items:
            $ref: '#/components/schemas/MergeTagView'
        created_at:
          type: string
          format: date-time
          description: When the template was created
          example: '2026-01-28T12:00:00+00:00'
    UnauthorizedResponse:
      type: object
      required:
        - message
      description: Error response for authentication failures (401).
      properties:
        message:
          type: string
          description: Human-readable error message
          example: API key is required.
    ErrorCode:
      type: string
      description: >-
        Error codes returned by the API.


        | Code | HTTP Status | Description |

        |------|-------------|-------------|

        | `validation_error` | 422 | Request validation failed. Check the
        `errors` object for field-specific messages. |

        | `invalid_domain` | 400 | The sender domain could not be determined
        from the email address. |

        | `unconfigured_domain` | 400 | The sender domain is not configured or
        approved for sending. |

        | `send_error` | 400, 500 | General error during email send preparation
        or domain registration. |

        | `retrieval_error` | 400, 500 | Failed to retrieve resources (e.g.,
        sandbox key without associated user, upstream error). |

        | `transmission_failed` | 502 | Email transmission to the upstream
        provider failed. |

        | `resource_already_exists` | 409 | The resource (e.g., domain) already
        exists. |

        | `not_found` | 404 | The specified resource was not found. |

        | `template_not_found` | 404 | The specified template, project, or
        template version was not found. |

        | `insufficient_scope` | 403 | The API key does not have the required
        scope for this endpoint. |

        | `schedule_cancellation_failed` | 409, 500 | Could not cancel the
        scheduled transmission (already sent or upstream error). |

        | `quota_exceeded` | 429 | Monthly sending quota exceeded. Upgrade your
        plan to continue sending. |

        | `daily_quota_exceeded` | 429 | Daily sending quota exceeded. Try again
        tomorrow. |

        | `campaign_not_sendable` | 422 | The campaign cannot be sent in its
        current state (not a draft, or missing subject/sender/content). |

        | `campaign_not_scheduled` | 422 | The campaign is not scheduled, so it
        cannot be unscheduled. |
      enum:
        - validation_error
        - invalid_domain
        - unconfigured_domain
        - send_error
        - retrieval_error
        - transmission_failed
        - resource_already_exists
        - not_found
        - template_not_found
        - insufficient_scope
        - schedule_cancellation_failed
        - quota_exceeded
        - daily_quota_exceeded
        - campaign_not_sendable
        - campaign_not_scheduled
      example: invalid_domain
    MergeTagView:
      type: object
      description: >-
        A single merge tag. Loop merge tags (for iterating over arrays) include
        a 'children' property with nested field definitions.
      required:
        - key
        - required
      properties:
        key:
          type: string
          description: The merge tag key/name used in templates
          example: first_name
        required:
          type: boolean
          description: Whether this merge tag is required when sending emails
          example: true
        type:
          type: string
          description: The data type of the merge tag (only present for loop children)
          enum:
            - text
            - number
            - image
            - button
          example: text
        children:
          type: array
          description: >-
            Child merge tags for loop blocks. Each child represents a field
            available within the loop iteration.
          items:
            $ref: '#/components/schemas/MergeTagChild'
    MergeTagChild:
      type: object
      description: A child merge tag within a loop block
      required:
        - key
      properties:
        key:
          type: string
          description: The child merge tag key/name
          example: item_name
        type:
          type: string
          description: The data type of the child merge tag
          enum:
            - text
            - number
            - image
            - button
          example: text
  responses:
    UnauthorizedError:
      description: Unauthorized - Missing or invalid API key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/UnauthorizedResponse'
          examples:
            missing_key:
              summary: Missing API key
              value:
                message: API key is required.
            invalid_key:
              summary: Invalid API key
              value:
                message: Invalid API key.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: API key for authentication

````