Skip to content

Templates

A template is a reusable email — a subject line and a designed body you build once in the dashboard and then send from the API with per-recipient variables. Templates keep your markup out of your application code: your send call carries only the data, and SendGrail renders the message.

Building a template

Open Templates in the dashboard and create one. The editor is a drag-and-drop canvas for the body, with a header for the From, Reply-To, Subject and Preview text.

Your work is saved automatically as you type — there's no Save button. A new template becomes a draft the moment it has real content, and every later edit is saved in the background (you'll see a Saved indicator in the header).

Nothing is required to save a draft. Missing pieces surface later as non-blocking warnings when you publish, not as errors that stop you working.

Viewing the rendered HTML

The </> button in the top-left of the editor opens the send-ready HTML, with a live preview and a copy button — useful for inspecting exactly what a recipient's mail client will receive.

Variables

Anywhere in the subject or body, write a variable in triple braces:

Hi {{{first_name}}}, your order {{{order_id}}} has shipped.

Every unique {{{name}}} you use appears in the editor's Variables panel. There you can give each one a fallback — the value rendered when a send call omits it. Without a fallback, a missing variable renders as empty.

At send time you supply the values as a variables object (see Sending with a template below).

Draft vs. published

A template is either a draft or published:

  • Draft — a work in progress. It cannot be sent from the API; a send call that references it returns 422.
  • Published — live and callable from the send API.

Publishing is deliberate. The Publish New Version control shows any warnings first — a missing From address, preview text or subject, empty content, or a variable with no fallback — then a slide-to-publish confirm. None of the warnings block you; they're there so you don't ship an empty subject by accident. Use Move to draft from the editor menu to pull a template back offline.

Testing a template

From the editor menu, Test email sends a one-off copy through the real sending pipeline so you can see it in an inbox. Enter one or more recipients (separate them with commas or line breaks, up to 25), fill in sample variable values, and send.

A test needs a From address set on the template — you'll be prompted for one before the test panel opens. If the From domain isn't verified, the test falls back to a test@ address on one of your verified domains.

Sending with a template

Reference a published template from POST /v1/emails with template_id (the template's UUID) or template_slug (its human-friendly, team-scoped handle), plus a variables object:

bash
curl https://api.sendgrail.com/v1/emails \
  -H "Authorization: Bearer $SENDGRAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "Acme <hello@example.com>",
    "to": "recipient@example.org",
    "template_slug": "order-shipped",
    "variables": {
      "first_name": "Ada",
      "order_id": "A-1024"
    }
  }'
js
await fetch('https://api.sendgrail.com/v1/emails', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.SENDGRAIL_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    from: 'Acme <hello@example.com>',
    to: 'recipient@example.org',
    template_slug: 'order-shipped',
    variables: { first_name: 'Ada', order_id: 'A-1024' },
  }),
});
python
import os, requests

requests.post(
    "https://api.sendgrail.com/v1/emails",
    headers={"Authorization": f"Bearer {os.environ['SENDGRAIL_API_KEY']}"},
    json={
        "from": "Acme <hello@example.com>",
        "to": "recipient@example.org",
        "template_slug": "order-shipped",
        "variables": {"first_name": "Ada", "order_id": "A-1024"},
    },
)
php
$http->post('https://api.sendgrail.com/v1/emails', [
    'headers' => ['Authorization' => 'Bearer '.getenv('SENDGRAIL_API_KEY')],
    'json' => [
        'from' => 'Acme <hello@example.com>',
        'to' => 'recipient@example.org',
        'template_slug' => 'order-shipped',
        'variables' => ['first_name' => 'Ada', 'order_id' => 'A-1024'],
    ],
]);

Notes:

  • Give either template_id or template_slug — you don't need both. template_id never changes; template_slug is friendlier but can be renamed.
  • The template supplies the subject, HTML and text — you don't send a body. You may still pass your own subject to override the template's; it's rendered with the same variables.
  • Passing variables, template_id or template_slug that don't resolve to a published template of yours returns a 422 — see Errors.

Next steps

Transactional email on your own domain.