MailcrateDocs

Send with a Template

Design an email once in Mailcrate, then send it from your code with each recipient's data filled in.

A template keeps the design of an email in Mailcrate and the data in your application. Your code sends a template id and a few values; Mailcrate fills them in, renders the email and sends it. Someone can change the wording or the design later without a deploy.

This page builds a password-reset email end to end.

Create the template

You can create it in the app or through the API.

In the app, open Emails and choose New Email. Give it a name and a type:

  • Visual editor: drag-and-drop blocks, no code.
  • Code (HTML): write the HTML yourself.
  • React Email: build it as a React component in your repository and push it with the CLI. See Templates as Code.

The Create new email dialog, with a name and the Code (HTML) template type selected

Email Templates in the Guides covers the editor in detail.

Through the API, post the template with a slug you will send it by (scope email-template:write):

POST/public/email-templatescope · email-template:write
Terminal
curl -X POST https://api.mailcrate.io/public/email-template \
  -H "Authorization: Api-Key $MAILCRATE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Password reset",
    "slug": "password-reset",
    "type": "html",
    "senderIdentityId": "<sender_identity_id>",
    "subject": "Reset your password, {{ contact.properties.firstName | default: \"there\" }}",
    "html": "<p>Someone asked to reset your password.</p><p><a href=\"{{ resetUrl }}\">Choose a new password</a></p><p>The link expires in {{ expiresInMinutes }} minutes.</p>",
    "variables": [
      { "key": "resetUrl", "sample": "https://app.example.com/reset/sample" },
      { "key": "expiresInMinutes", "sample": "30" }
    ]
  }'

GET /public/sender-identity lists the sender identity ids. The response is the new template, including its id.

Set the sender and subject

A template carries its own From, Subject, Preview text, Reply To and BCC. In the editor they sit behind Settings, above the email body:

The Email Settings panel: From, Subject, Preview text, Reply To, BCC and Send data variables

These values are used for every send of the template. A send request can override the From address with fromAddress, but not the subject, reply-to or BCC.

Add variables

Variables are the gaps your code fills at send time. Write them as {{ name }} in the body or the subject:

Template HTML
<h1>Reset your password</h1>
<p>Hi {{ contact.properties.firstName | default: "there" }},</p>
<p><a href="{{ resetUrl }}">Choose a new password</a>. The link expires in {{ expiresInMinutes }} minutes.</p>

Templates use the Liquid template language. These values are available:

VariableComes from
{{ resetUrl }}, {{ anyKey }}The data object of the send request. Each key becomes a variable of the same name.
{{ contact.email }}The recipient's address.
{{ contact.properties.firstName }}Any custom property of the contact.
{{ contact.externalIdentifier }}Your own id for the contact, if it has one.
{{ unsubscribe_url }}The recipient's unsubscribe link. Empty on transactional message sends.
{{ sender_address }}Your workspace's postal address, for the footer.

Under Send data variables in the template settings you can declare the keys you expect, with a sample value. Declaring them is optional: it lists them in the editor's merge-tag picker and fills them in the preview, and it does not change what is sent.

Preview it with real data

In the editor, switch to Preview and choose a contact to see the email as they would get it.

The editor in Preview mode, showing the rendered email

From code, render the template with the data you plan to send, without sending anything:

POST/public/email-template/:identifier/render-previewscope · email-template:write
Terminal
curl -X POST https://api.mailcrate.io/public/email-template/password-reset/render-preview \
  -H "Authorization: Api-Key $MAILCRATE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "contactId": "user_8231",
    "data": { "resetUrl": "https://app.example.com/reset/8f2c", "expiresInMinutes": 30 }
  }'

The response is { "html": "…" }. contactId is optional; without it the contact variables are empty.

To try out a piece of Liquid without saving a template, POST /public/render (scope rendering:write) renders any html with any data.

Send it

Send the template by its slug or id, with the values in data:

POST/public/sending/mailscope · sending:write
Terminal
curl -X POST https://api.mailcrate.io/public/sending/mail \
  -H "Authorization: Api-Key $MAILCRATE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "contactEmail": "ada@example.com",
    "templateId": "password-reset",
    "lane": "transactional",
    "data": {
      "resetUrl": "https://app.example.com/reset/8f2c",
      "expiresInMinutes": 30
    },
    "idempotencyKey": "password-reset-8f2c"
  }'

Don't forget the lane

A send by templateId defaults to the marketing lane, which skips recipients who unsubscribed from your marketing. Set "lane": "transactional" for password resets, receipts and anything else the recipient asked for. See Lanes.

How variables behave

  • A missing variable renders as nothing. If the template uses {{ couponCode }} and data has no couponCode, that spot is empty and the email still sends. Use default for a fallback: {{ couponCode | default: "WELCOME10" }}.

  • Values can be objects and lists. Send "data": { "order": { "items": [...] } } and loop over it:

    {% for item in order.items %}
      <tr><td>{{ item.name }}</td><td>{{ item.quantity }}</td></tr>
    {% endfor %}
  • Conditions work the usual Liquid way: {% if order.discount %}…{% endif %}.

  • Some names are reserved. contact, unsubscribe_url, unsubscribeUrl and sender_address in data are dropped, so your data cannot replace the real recipient or unsubscribe link.

  • Text is not HTML-escaped automatically. If a value comes from a user, escape it: {{ comment | escape }}.

  • The subject is a template too. Your order {{ orderNumber }} works in the subject field.

Editing a template that is in use

You can change a template at any time; the next send uses the new version. An email already queued keeps the version that was current when you sent it, so an edit never changes an email halfway. Every save is kept in the template's History, so you can see and restore earlier versions.

Before deleting a template, check Where it's used. Sends by a slug that no longer exists fail with 404 Email template "…" not found.

Next steps

On this page