Templates
A template is a subject and a body with holes in it. You store it once, and each send fills the holes:
curl -X POST https://api.avelto.dev/v1/emails \
-H "Authorization: Bearer av_live_..." \
-H "Content-Type: application/json" \
-d '{
"from": "Acme <[email protected]>",
"to": "[email protected]",
"template_slug": "welcome",
"variables": {
"name": "Ada",
"plan": "Growth"
}
}'No subject, no html, no text — the template owns those. Passing one alongside a
template is an error rather than an override, because two places deciding what a message
says is a support question waiting to happen. The reverse holds too: variables without
a template is refused.
The template language, in full
There isn't one. The entire grammar is a name between braces:
| Form | What it does |
|---|---|
{{name}} | The value, HTML-escaped in the HTML part |
{{{name}}} | The value exactly as given |
A name is letters, digits and underscores, not starting with a digit; {{ name }} with
spaces is fine. Anything else between braces is left as written. String values may be up
to 10,000 characters.
No loops, no conditionals, no partials, no property access, no expressions, no filters. That is a deliberate ceiling rather than a roadmap: every one of those turns your template into a program that runs on our servers, and the history of template engines is a history of that program escaping.
If you need a list of order lines, build the HTML for it yourself and pass it as one
variable with {{{lines}}}. You keep the loop, in your own language, where you can test
it.
Escaping
{{name}} is escaped in the HTML part and left alone in the subject and the plain text
part, so the same variable is safe in both. A customer called Ada <[email protected]> renders as text, not
as a broken tag.
{{{name}}} skips the escaping. Use it when you are passing markup you built, and not
when you are passing something a user typed.
Missing variables are an error
A template that refers to {{name}} and a send that does not pass one is refused with
422, listing every variable that was missing:
{
"error": {
"code": "validation_error",
"message": "The template needs values for these variables: company, name. Pass them in variables.",
"details": { "missing_variables": ["company", "name"] }
}
}Not an empty string. "Hi ," sent to a hundred thousand people is worse in every way than a send that did not happen, and the error names all of them at once so it is one fix rather than a guessing game.
Values
Strings, numbers, booleans and null. null renders as nothing, which is what an absent
middle name should do. Objects and arrays are refused — see the ceiling above.
Managing templates
POST /v1/templates with a name, a subject, and html, text or both. The slug
is derived from the name unless you set one, and it is what you pass as template_slug.
Slugs are lower-case letters, digits and hyphens (welcome-email). A derived slug that is
already taken gets a numeric suffix; a slug you set yourself must be free or the request
is 409 conflict. On a send, name the template with template_slug or template_id,
not both. An unknown slug or id is 404 not_found.
import { Avelto } from "@avelto/sdk";
const avelto = new Avelto(process.env.AVELTO_API_KEY);
const template = await avelto.templates.create({
name: "Welcome",
subject: "Welcome, {{name}}",
html: "<p>Hello {{name}}</p>",
});
await avelto.emails.send({
from: "[email protected]",
to: "[email protected]",
template_slug: template.slug,
variables: { name: "Ada" },
});GET, PATCH and DELETE /v1/templates/{id} do what you expect. A key needs the
templates:manage scope for any of them.
Versions
Every save adds a version; version 1 is the template as you first created it, and
version on the template is the current one. GET /v1/templates/{id}/versions lists them, and
POST /v1/templates/{id}/restore with a version puts one back.
Restoring writes the old version forward as a new one rather than rewinding, so the history is append-only and a restore is itself something you can undo. The mistake you restored away from is still there.
What a send keeps
The rendered subject and body are copied onto the email when it is accepted. Editing a template afterwards does not change what was already sent, and deleting one does not orphan it — the email log still shows exactly what went out.
In the dashboard
Templates has an editor with the same preview the email log uses, a panel listing the variables it found in your body, and a button that sends the template to the account owner's address in test mode so you can look at it in a real mail client.