Email templates and merge variables
Templates let you design an email once in the dashboard and send it through the transactional API with per-recipient variables. The same merge-tag syntax also powers campaign personalization.
Last updated
Creating templates
- Templates are created and edited in dashboard → Templates (rich editor or raw HTML mode). Each template belongs to one sending domain and stores a subject, an HTML body, and optionally a plain-text body.
- A template may have an alias — a short handle like
password-resetfor API sends. Aliases are lowercase and unique per root domain, sopassword-resetonyourdomain.comand onotherdomain.comare different templates. - When a template has no stored plain-text body, API sends derive one from the rendered HTML automatically, so every email ships with a text part.
Merge-tag syntax
Variables appear in the subject, HTML body, or text body as double-brace tags. Keys may contain letters, digits, underscores, and dots.
| Syntax | Behavior |
|---|---|
{{name}} | Replaced with the value of name. Required: if any occurrence has no fallback, the variable must be supplied or the send fails. |
{{name|there}} | Replaced with the value of name, or the literal there when name is not supplied. The fallback is everything after the first | (it may itself contain |, but not }), trimmed. |
{{name|}} | Explicit empty-string fallback — renders as nothing when name is missing, and counts as optional. |
{{user.plan}} | Dot-path key, filled by nested data: { "user": { "plan": "Pro" } }. |
{{email}} | Always available on API sends — defaults to the recipient (to) address unless data.email overrides it. |
A variable counts as optional only if every occurrence across subject, HTML, and text carries a fallback. One bare {{name}} anywhere makes name required for the whole template.
Required-variable enforcement
SendBunny refuses to send an email that would render with blank merge fields. If required variables are missing from data, the API returns a 400 naming them, and nothing is sent:
{
"error": "Missing required template variables: name, reset_url",
"missing": ["name", "reset_url"]
}Sending a template
Reference the template by templateAlias (resolved on the from address's root domain) or by templateId, never both. Raw html/text fields are forbidden in template mode; a non-empty subject overrides the template's stored subject.
curl -X POST 'https://YOUR-DISTRIBUTION.cloudfront.net/v1/emails' \
-H 'x-api-key: sbYOUR_KEY_HERE' \
-H 'Content-Type: application/json' \
-d '{
"from": "hello@yourdomain.com",
"to": ["priya@example.com"],
"templateAlias": "welcome",
"data": {
"name": "Priya",
"user": { "plan": "Pro" }
}
}'Value rules for data (full details in the API reference): JSON object; strings, numbers, booleans, and nested objects only; arrays and null are rejected with the offending paths listed.