Templates
Create template versions, publish one per alias, and use them when sending.
Create a template
Creates a template version. Versions that share an alias belong to the same template, and only one version per alias is published at a time. When you send an email with template set to an alias, Emailit uses the published version. Requires an API key with full scope.
/templatesRequest body
namestringRequiredTemplate name shown in the dashboard. Up to 191 characters.
aliasstringRequiredIdentifier that groups the versions of a template. Up to 191 characters; lowercase letters, numbers, underscores and hyphens only (^[a-z0-9_-]+$).
If no template uses this alias yet, the new version is published immediately. If the alias already exists, the new version is created unpublished (published_at is null) and you publish it with Publish a template.
fromstringDefault sender, for example Acme <hello@acme.com>. Up to 191 characters.
subjectstringDefault subject line. Up to 191 characters. Can contain Temple variables such as {{ first_name }}.
reply_tostring | string[]Reply-to address, or an array of addresses. Every value must be a valid email address.
htmlstringHTML body.
textstringPlain-text body.
sourcestringEditor source document, for example the Dragit JSON of a template built in the drag-and-drop editor. Stored as-is. For editor: "mjml", the MJML: Emailit validates it, stores it as an MJML document and compiles html from it.
editorstringEditor the template belongs to: html (default), text, dragit or tiptap. mjml is in alpha and open to the Emailit team only; other requests get 403 with error: "mjml_alpha". See MJML editors and API.
Returns
Returns 201 Created with the template in data and a confirmation message. The template includes html, text and source. Emailit also sends a template.created webhook event.
MJML templates also return an mjml object with the document’s versions. Invalid MJML returns 422 with errors.source and diagnostics; see Validation.
If a field fails validation, the response is 400 with message: "Validation failed" and an errors object keyed by field, for example an alias with uppercase letters or an invalid reply_to address. A missing name or alias, or an editor value that isn’t allowed, returns the standard 400 validation error with a details array instead. See Errors.
{
"data": {
"id": "tem_2xKx7M2c9wQe3kHhJ8sVtY1pZ0a",
"name": "Welcome email",
"alias": "welcome-email",
"from": null,
"subject": "Welcome to Acme, {{ first_name }}",
"reply_to": null,
"html": "<h1>Welcome, {{ first_name }}</h1>",
"text": null,
"source": null,
"editor": "html",
"published_at": "2026-09-30T10:30:00.482119Z",
"preview_url": null,
"created_at": "2026-09-30T10:30:00.482119Z",
"updated_at": "2026-09-30T10:30:00.482119Z"
},
"message": "Template was successfully created."
}{
"message": "Validation failed",
"errors": {
"alias": ["Alias must contain only lowercase letters (a-z), numbers (0-9), underscores (_), and hyphens (-)"]
}
}Retrieve a template
Returns one template version, including its content, and lists the other versions of the same alias in versions. Templates are looked up by ID only, not by alias. Requires an API key with full scope.
/templates/:idPath parameters
idstringRequiredTemplate ID, for example tem_2xKx7M2c9wQe3kHhJ8sVtY1pZ0a.
Returns
Returns 200 OK with the template in data. Besides the template fields, the response has a versions array with the id, name, published_at, created_at and updated_at of every other version that shares the alias, newest first. The published version is the one with a non-null published_at.
Returns 404 with message: "Template not found" if the ID doesn’t exist in your workspace.
{
"data": {
"id": "tem_2xKx7M2c9wQe3kHhJ8sVtY1pZ0a",
"name": "Welcome email",
"alias": "welcome-email",
"from": "Acme <hello@acme.com>",
"subject": "Welcome to Acme, {{ first_name }}",
"reply_to": ["support@acme.com"],
"html": "<h1>Welcome, {{ first_name }}</h1>",
"text": "Welcome, {{ first_name }}",
"source": null,
"editor": "html",
"published_at": "2026-09-30T10:30:00.482119Z",
"preview_url": null,
"created_at": "2026-09-28T08:12:45.103882Z",
"updated_at": "2026-09-30T10:30:00.482119Z",
"versions": [
{
"id": "tem_2xKyB4qLm7RtV9sNd3HwEa6uC1f",
"name": "Welcome email (October)",
"published_at": null,
"created_at": "2026-09-30T14:02:11.550731Z",
"updated_at": "2026-09-30T14:02:11.550731Z"
}
]
}
}{
"message": "Template not found"
}Update a template
Updates one template version. Send only the fields you want to change. The version keeps its publish state: a published version stays published and a draft stays a draft. Requires an API key with full scope.
/templates/:idPath parameters
idstringRequiredTemplate ID, for example tem_2xKx7M2c9wQe3kHhJ8sVtY1pZ0a.
Request body
namestringTemplate name. Up to 191 characters.
aliasstringNew alias. Up to 191 characters; lowercase letters, numbers, underscores and hyphens only. It can’t be an alias that another template already uses.
fromstringDefault sender, for example Acme <hello@acme.com>. Up to 191 characters. Send an empty string to clear it.
subjectstringDefault subject line. Up to 191 characters. Send an empty string to clear it.
reply_tostring | string[]Reply-to address or array of addresses. Send an empty string to clear it.
htmlstringHTML body.
textstringPlain-text body.
sourcestringEditor source document, for example Dragit JSON. For an MJML template, the full MJML: Emailit validates it and recompiles html, and any html you send is ignored.
editorstringhtml, text, dragit or tiptap. mjml is in alpha and open to the Emailit team only; changing an MJML template’s content without MJML access returns 403 with error: "mjml_alpha". Renaming or publishing it works for everyone. See MJML editors and API.
Returns
Returns 200 OK with the updated template in data and a confirmation message. Emailit also sends a template.updated webhook event.
Returns 400 with message: "Validation failed" and an errors object when a value is invalid, for example "Alias already exists". Values longer than 191 characters or an unknown editor return the standard 400 validation error. Returns 404 if the template doesn’t exist.
To make this version the one used for sending, call Publish a template.
{
"data": {
"id": "tem_2xKx7M2c9wQe3kHhJ8sVtY1pZ0a",
"name": "Welcome email",
"alias": "welcome-email",
"from": "Acme <hello@acme.com>",
"subject": "Welcome aboard, {{ first_name }}",
"reply_to": ["support@acme.com"],
"html": "<h1>Welcome, {{ first_name }}</h1>",
"text": "Welcome, {{ first_name }}",
"source": null,
"editor": "html",
"published_at": "2026-09-30T10:30:00.482119Z",
"preview_url": null,
"created_at": "2026-09-28T08:12:45.103882Z",
"updated_at": "2026-10-01T09:15:27.640000Z"
},
"message": "Template was successfully updated."
}{
"message": "Validation failed",
"errors": {
"alias": ["Alias already exists"]
}
}{
"message": "Template not found"
}List templates
Returns the published version of each template, newest first. Unpublished versions aren’t listed; retrieve a template to see all versions of its alias. Requires an API key with full scope.
/templatesQuery parameters
pageintegerPage number, starting at 1. Default 1.
per_pageintegerTemplates per page, from 1 to 100. Default 25.
include_contentbooleanSet to true to include html, text and source on each template. Omitted by default to keep responses small.
filter[name]stringCase-insensitive partial match on the template name or alias.
filter[alias]stringExact alias.
filter[editor]stringEditor: html, text, dragit, tiptap or mjml (alpha).
matchstringall (default) requires every key.condition filter to match. or matches any of them. See Filtering.
sortstringSort key: name, alias, created_at (default), updated_at or published_at.
orderstringSort direction: asc or desc (default).
Filters
List filters are one layer of key.condition=value query parameters. See Filtering for match, order, direction and the condition list per type.
Filter keys
| Key | Type | Conditions | Notes |
|---|---|---|---|
name | string | exact, not_exact, contains, not_contains, starts_with, ends_with, empty, not_empty | |
alias | string | exact, not_exact, contains, not_contains, starts_with, ends_with, empty, not_empty | |
editor | string | exact, not_exact, contains, not_contains, starts_with, ends_with, empty, not_empty | |
subject | string | exact, not_exact, contains, not_contains, starts_with, ends_with, empty, not_empty | |
created_at | date | exact, before, after, empty, not_empty |
Sort keys
This endpoint sorts with sort set to one of these keys and order set to asc or desc (order=<key> returns 400 here): name, alias, editor, subject, created_at
On this endpoint, order only accepts asc or desc. Pass the sort key in sort, for example sort=name&order=asc.
Returns
Returns 200 OK with the templates in data and the pagination fields total_records, per_page, current_page and total_pages. Each template includes total_versions, the number of versions that share its alias.
{
"data": [
{
"id": "tem_2xKx7M2c9wQe3kHhJ8sVtY1pZ0a",
"name": "Welcome email",
"alias": "welcome-email",
"from": "Acme <hello@acme.com>",
"subject": "Welcome to Acme, {{ first_name }}",
"reply_to": ["support@acme.com"],
"editor": "html",
"published_at": "2026-09-30T10:30:00.482119Z",
"preview_url": null,
"total_versions": 3,
"created_at": "2026-09-28T08:12:45.103882Z",
"updated_at": "2026-09-30T10:30:00.482119Z"
}
],
"total_records": 1,
"per_page": 25,
"current_page": 1,
"total_pages": 1
}{
"statusCode": 401,
"error": "Unauthorized",
"message": "Invalid API key"
}Publish a template
Publishes a template version and unpublishes every other version with the same alias, in one transaction. Use it to roll out a new draft or to roll back to an earlier version. Requires an API key with full scope.
/templates/:id/publishPath parameters
idstringRequiredID of the version to publish, for example tem_2xKyB4qLm7RtV9sNd3HwEa6uC1f.
Request body
No body. Publishing an already published version sets a new published_at.
Returns
Returns 200 OK with the published template in data and a confirmation message. Returns 404 if the template doesn’t exist.
Emailit sends a template.updated webhook event for the version you published and one for each version that was unpublished.
{
"data": {
"id": "tem_2xKyB4qLm7RtV9sNd3HwEa6uC1f",
"name": "Welcome email (October)",
"alias": "welcome-email",
"from": "Acme <hello@acme.com>",
"subject": "Welcome to Acme, {{ first_name }}",
"reply_to": ["support@acme.com"],
"html": "<h1>Welcome, {{ first_name }}</h1><p>Here is your October guide.</p>",
"text": "Welcome, {{ first_name }}. Here is your October guide.",
"source": null,
"editor": "html",
"published_at": "2026-10-01T09:20:04.118502Z",
"preview_url": null,
"created_at": "2026-09-30T14:02:11.550731Z",
"updated_at": "2026-10-01T09:20:04.118000Z"
},
"message": "Template was successfully published."
}{
"message": "Template not found"
}Delete a template
Permanently deletes one template version. Other versions of the same alias are kept. Requires an API key with full scope.
/templates/:idPath parameters
idstringRequiredTemplate ID, for example tem_2xKx7M2c9wQe3kHhJ8sVtY1pZ0a.
Returns
Returns 200 OK with data: null and a confirmation message. Emailit sends a template.deleted webhook event with the deleted version. Returns 404 if the template doesn’t exist.
If you delete the published version, no version of that alias is published until you publish another one, and sending with that alias fails. Deleting a draft doesn’t affect the published version. You can’t undo a delete.
{
"data": null,
"message": "Template was successfully deleted."
}{
"message": "Template not found"
}