Guide

Send Email with Hosted Templates (CLI)

You keep your transactional email copy in a Nylas-hosted template and want to render and send it from a script without rebuilding the HTML. This guide fills variables server-side with one command, loads data from a JSON file, and previews the merge with --render-only before anything leaves the outbox.

Written by Prem Keshari Senior SRE

Reviewed by Qasim Muhammad

VerifiedCLI 3.1.17 · Gmail, Outlook, IMAP · last tested June 9, 2026

What is a Nylas-hosted email template?

A Nylas-hosted email template is a subject-and-body document stored on Nylas with named placeholders that get filled at send time from JSON you supply. The merge happens server-side, so your script ships only an ID and a small data object — not the HTML. One template can back thousands of personalized sends without ever pasting markup into a command.

This differs from the local templates that nylas email templates manages: those live in ~/.config/nylas/templates.json on your machine and substitute {{variable}} values on the client. Hosted templates render on Nylas and are scoped to your app or a single grant, which keeps copy versioning out of every machine that runs the send. The two systems share the merge idea but never the storage location.

How do I send an email with a template ID?

Send a hosted template by passing its ID to nylas email send along with --template-data, an inline JSON object holding the variable values. Nylas renders the subject and body, then delivers over your connected provider's API. There is no SMTP host to configure and no HTML in the command itself.

The example below renders template tpl_welcome_01 with a nested user object and sends it. The --yes flag skips the confirmation prompt so the command runs unattended in a cron job or CI step. A single send replaces the 40-plus lines of templating and SMTP setup a hand-rolled mailer would need.

nylas email send \
  --to ada@example.com \
  --template-id tpl_welcome_01 \
  --template-data '{"user":{"name":"Ada"},"plan":"Pro"}' \
  --yes

The data object uses standard JSON, so nested fields like user.name map to whatever placeholder syntax the template author used. Most hosted template engines follow the Mustache convention documented at mustache.github.io, so a missing key renders as an empty string unless strict mode is on.

How do I load template data from a JSON file?

Load variables from disk with --template-data-file instead of inlining JSON on the command line. This keeps a 2,000-character data payload out of your shell history and out of process listings, and it lets a separate build step generate the file. The flag accepts any path to a valid JSON object.

Generating the file as a real artifact also means you can validate it with jq before the send, catching a malformed object in milliseconds rather than discovering it in a failed API call. The two commands below write the data, then render and send it.

cat > data.json <<'JSON'
{
  "user": { "name": "Ada", "email": "ada@example.com" },
  "invoice": { "number": "INV-2048", "amount": "$129.00" }
}
JSON

nylas email send \
  --to ada@example.com \
  --template-id tpl_invoice_03 \
  --template-data-file data.json \
  --yes

The inline --template-data flag and the file flag are mutually exclusive in practice: pick the file when the payload exceeds a line or holds anything you don't want echoed. A typical invoice or receipt object runs 200 to 600 bytes, well within either path.

How do I preview a template before sending?

Preview the rendered template by adding --render-only, which fills the variables on Nylas and returns the resulting subject and body without delivering anything. This is the proofing step that stops a broken merge from reaching a real inbox — you see the exact output a recipient would, with zero sends counted against your account.

Run the preview against the same data file you intend to send with, then pipe the output through --json when you want to assert on specific fields in a test. The render takes under a second and consumes no send quota, so it's cheap to run on every CI build that touches template copy.

# Preview the merge — nothing is sent
nylas email send \
  --template-id tpl_invoice_03 \
  --template-data-file data.json \
  --render-only

# Machine-readable preview for a CI assertion
nylas email send \
  --template-id tpl_invoice_03 \
  --template-data-file data.json \
  --render-only --json | jq '.subject'

Pair the preview with --template-strict, which defaults to true and fails the render when the data is missing a variable the template references. That turns a silent empty-string bug into a loud error before any production send.

How do I scope templates and track sends?

Hosted templates resolve at one of two scopes, controlled by --template-scope: the default app scope shares one template across every grant in your application, while grant scope ties a template to a single connected account. Grant-scoped sends also accept --template-grant-id to name the owning account explicitly.

Template sends accept the same delivery flags as any other message. Add --track-opens to record opens, --track-links for click tracking, and --metadata to tag the send with a correlation key. The scopes are described in the Nylas v3 admin API reference, and Message-IDs follow RFC 5322 so downstream systems can thread the reply.

nylas email send \
  --to ada@example.com \
  --template-id tpl_welcome_01 \
  --template-data '{"user":{"name":"Ada"}}' \
  --template-scope grant \
  --track-opens --metadata campaign=q3_onboard \
  --yes

Next steps