.md

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-reset for API sends. Aliases are lowercase and unique per root domain, so password-reset on yourdomain.com and on otherdomain.com are 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.

SyntaxBehavior
{{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:

400 response
{
  "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
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.