Skip to main content
Your transactional copy usually lives in the codebase — a React Email component, an MJML file, a string literal in a route handler. Every wording change is a pull request and a redeploy, with a developer in the loop for a comma. A template moves that copy out of the repo and into the SenderKit dashboard. Your code references the template by name; the subject, layout, and copy live in the dashboard, where anyone on the team can edit them without touching code.

What a template is

A template is a named, channel-bound definition of a message. It carries:
  • A slug — the stable identifier your code sends to ("welcome", "password-reset"). Unique within your workspace.
  • A channelemail, sms, push, or web-push. Fixed when the template is created; a template targets exactly one channel.
  • A stack of versions — the actual subject, layout, and copy live in versions, not on the template itself. The template just points at whichever version is currently published.
  • A statusdraft until you publish a version, then active. Templates can also be archived. Archiving is a hard stop: any API or SDK send to an archived template’s slug returns 422 template_archived.
The template is identity and routing; the content lives in its versions. That separation is what makes copy edits safe — every change is a new version you can publish or roll back independently.

Referencing a template from a send

Your code names the template by slug and supplies the recipient and variables. It never names a version or a channel — the channel comes from the template, and SenderKit picks the version for you (see Versioning and Environments).
await senderkit.send({
  template: "welcome",
  to: "user@example.com",
  vars: { name: "Ada" },
});
If the slug doesn’t exist you get a 404; in live mode, a template with no published version is also a 404 until you publish one.

Why this decouples copy from deploys

You wire up send({ template: "welcome" }) once. After that, changing the welcome email’s wording is a dashboard edit and a publish — not a code change, not a redeploy, not your time. The send call is a stable contract; everything that can change without engineering (the words, the layout, the subject line) lives on the other side of that contract.

Managing a template

The template editor’s Settings tab exposes lifecycle actions beyond the content editor:
  • Description — a free-text label visible in the dashboard.
  • Provider override — pin this template to a specific provider connection instead of the workspace default for the channel.
  • Slug — rename the template’s identifier. Slugs are always stored in lowercase ("Welcome-Email" saves as "welcome-email"), so your code must reference them in lowercase. Changing the slug breaks any code or integrations that reference the old name, so a warning is shown.
  • Duplicate — clones the latest version’s content and variables as a new draft template (the duplicate button also appears in the editor toolbar). The plan’s template cap applies.
  • Archive / Unarchive (Danger zone) — archiving marks the template archived and immediately stops all new sends to it (422 template_archived). The action is reversible — unarchiving restores the template to draft — but consequential: any integration still calling the slug will start getting errors. Scheduled messages already queued before archiving are not retroactively cancelled.
Archiving is the delete-equivalent for templates. Hard deletion is not available by design — archived templates remain visible in the dashboard when you switch the status filter to include Archived.

Previewing and testing (email only)

The template editor’s Preview tab renders the current editor content — including unsaved edits — through the same engine used at send time. Variable placeholders are filled with sample values derived from the template’s declared variables, so you can verify layout and substitution before publishing. A Send test button in the preview panel dispatches the rendered email to your own account address immediately, through the normal delivery path. The test send appears in the message log like any other send.

Synced blocks

A synced block is a named HTML fragment you define once in the dashboard (Blocks in the sidebar) and insert into any email template via the editor’s slash menu (Synced blocks group). Typical uses: a branded header, a shared footer, a legal disclaimer. When you insert a synced block into a template the editor records a reference, not a copy. At send time SenderKit resolves each reference to the block’s current content, so editing a synced block propagates to every email that uses it automatically — including already-published templates — without republishing. Synced blocks share the host template’s variable namespace, so {{vars}} inside a block resolve against the send’s variables just like the rest of the template.
// Synced blocks are transparent to your code — the send call is unchanged.
await senderkit.send({
  template: "receipt",
  to: "user@example.com",
  vars: { amount: "$42.00", companyName: "Acme" },
});
Per-block variable declarations are not yet supported. Declare all variables used inside a synced block on the parent template.

Variables

Fill the dynamic holes in a template at send time.

Versioning

How edits become versions and how a send picks one.

Channels & Providers

What a template’s channel means and who delivers it.

Sending

How a template reference turns into a delivered message.