Templates

Store reusable email content with variables and send it by id

A template is a stored subject, HTML body, and optional text body with {{variable}} placeholders. You create it once, then send it with templateId and templateData instead of inlining the content on every request. Templates are per account.

Variables

Placeholders use double curly braces around a name made of letters, digits, and underscores: {{firstName}}, {{order_id}}. Whitespace inside the braces is allowed ({{ firstName }}). Substitution is plain text replacement; there are no conditionals, loops, or filters.

Every variable that appears in the subject, HTML, or text must be declared in the template's variables array, and creating or updating a template that references an undeclared variable fails with 400. This catches typos at authoring time instead of at send time.

When you send, templateData supplies a value for each variable. Values are inserted as-is. Because there is no HTML escaping, do not put untrusted user input into a variable that lands in HTML without escaping it yourself first.

Sending with a template

{
  "from": { "email": "hello@mail.example.com", "name": "Example App" },
  "to": ["ada@example.net"],
  "templateId": "tpl_m8x9q4wzk17c2",
  "templateData": { "firstName": "Ada", "loginUrl": "https://app.example.com/login" }
}
  • templateData is required whenever templateId is set. Send {} if the template has no variables.
  • The template's subject is used unless the request includes its own subject, which takes precedence.
  • Any html or text in the request is ignored when templateId is set.
  • A templateId that does not exist on your account fails the send with 400 validation_error and a details entry for the templateId field.

Template object

FieldTypeDescription
idstringOpaque template id. Treat it as a string; do not parse it.
namestringUnique name on the account, for your reference.
subjectstringSubject line, may contain variables.
htmlstringHTML body, may contain variables. Empty string for text-only templates.
textstringPlain-text body, may contain variables. Absent if not set.
variablesstring[]Declared variable names.
isActivebooleanAlways true for templates returned by the API.
createdAtnumberUnix time in milliseconds.
updatedAtnumberUnix time in milliseconds.

Endpoints

List templates

GET/v1/send/templates

List templates, newest first.

Requires:send:read

Query parameters

limitinteger
Page size, 1 to 100.Defaults to 50
offsetinteger
Number of results to skip.Defaults to 0
searchstring
Only templates whose name contains this string.
{
"templates": [
  {
    "id": "tpl_m8x9q4wzk17c2",
    "name": "welcome",
    "subject": "Welcome, {{firstName}}",
    "html": "<p>Hi {{firstName}}, <a href=\"{{loginUrl}}\">sign in</a> to get started.</p>",
    "text": "Hi {{firstName}}, sign in at {{loginUrl}} to get started.",
    "variables": ["firstName", "loginUrl"],
    "isActive": true,
    "createdAt": 1756900000000,
    "updatedAt": 1756900000000
  }
],
"pagination": { "limit": 50, "offset": 0, "total": 1 }
}

Create a template

POST/v1/send/templates

Create a template. Every variable referenced in subject, html, or text must be listed in variables.

Requires:send:write

Body parameters

namestringrequired
Unique name on the account.
subjectstringrequired
Subject line. May contain variables.
htmlstring
HTML body. Provide html, text, or both.
textstring
Plain-text body.
variablesstring[]
Names of every variable used in subject, html, and text. Required if any are used.
Create a template
curl -X POST https://api.do.dev/v1/send/templates \
-H "Authorization: Bearer $SEND_API_KEY" \
-H "Content-Type: application/json" \
-d '{
  "name": "welcome",
  "subject": "Welcome, {{firstName}}",
  "html": "<p>Hi {{firstName}}, <a href=\"{{loginUrl}}\">sign in</a> to get started.</p>",
  "text": "Hi {{firstName}}, sign in at {{loginUrl}} to get started.",
  "variables": ["firstName", "loginUrl"]
}'
Response201
{
"id": "tpl_m8x9q4wzk17c2",
"name": "welcome",
"subject": "Welcome, {{firstName}}",
"html": "<p>Hi {{firstName}}, <a href=\"{{loginUrl}}\">sign in</a> to get started.</p>",
"text": "Hi {{firstName}}, sign in at {{loginUrl}} to get started.",
"variables": ["firstName", "loginUrl"],
"isActive": true,
"createdAt": 1756900000000,
"updatedAt": 1756900000000
}

Get a template

GET/v1/send/templates/{id}

Return one template.

Requires:send:read

Update a template

PUT/v1/send/templates/{id}

Update any of name, subject, html, text, or variables. Fields you omit keep their current value. The variable check runs against the merged result.

Requires:send:write

Body parameters

namestring
New unique name.
subjectstring
New subject.
htmlstring
New HTML body.
textstring
New text body.
variablesstring[]
Replaces the declared variable list.

Updates take effect for sends queued after the update; emails already queued use the content they were queued with.

Delete a template

DELETE/v1/send/templates/{id}

Delete a template. Fails if any email using it is still queued or processing.

Requires:send:write

Returns 204 No Content on success.