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.
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.
{
"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.subject, which takes precedence.html or text in the request is ignored when templateId is set.templateId that does not exist on your account fails the send with 400 validation_error and a details entry for the templateId field.| Field | Type | Description |
|---|---|---|
id | string | Opaque template id. Treat it as a string; do not parse it. |
name | string | Unique name on the account, for your reference. |
subject | string | Subject line, may contain variables. |
html | string | HTML body, may contain variables. Empty string for text-only templates. |
text | string | Plain-text body, may contain variables. Absent if not set. |
variables | string[] | Declared variable names. |
isActive | boolean | Always true for templates returned by the API. |
createdAt | number | Unix time in milliseconds. |
updatedAt | number | Unix time in milliseconds. |
/v1/send/templatesList templates, newest first.
limitinteger50offsetinteger0searchstring{
"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 }
}/v1/send/templatesCreate a template. Every variable referenced in subject, html, or text must be listed in variables.
namestringrequiredsubjectstringrequiredhtmlstringtextstringvariablesstring[]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"]
}'{
"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
}/v1/send/templates/{id}Return one template.
/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.
namestringsubjectstringhtmlstringtextstringvariablesstring[]Updates take effect for sends queued after the update; emails already queued use the content they were queued with.
/v1/send/templates/{id}Delete a template. Fails if any email using it is still queued or processing.
Returns 204 No Content on success.