Skip to main content

Template Guide

Optail templates use MJML for responsive email markup and Handlebars for variable interpolation. Templates are versioned -- you can preview with sample data, publish new versions, and roll back to any previous version.

Creating a Template

1. Create the template container

curl -X POST https://api.optail.io/v1/templates \
-H "Authorization: Bearer ms_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Welcome Email",
"description": "Sent when a new user signs up",
"tags": ["onboarding"]
}'

This creates a template with no versions yet. Note the id from the response.

2. Create the first version with MJML

curl -X POST https://api.optail.io/v1/templates/TPL_ID/versions \
-H "Authorization: Bearer ms_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"mjmlSource": "<mjml><mj-body><mj-section><mj-column><mj-text>Hello {{name}}!</mj-text><mj-button href=\"{{activationUrl}}\">Activate Account</mj-button></mj-column></mj-section></mj-body></mjml>",
"htmlContent": "<html><body><h1>Hello {{name}}!</h1><a href=\"{{activationUrl}}\">Activate Account</a></body></html>",
"textContent": "Hello {{name}}! Activate your account: {{activationUrl}}",
"variablesSchema": {
"name": "string",
"activationUrl": "string"
}
}'

If you provide mjmlSource, Optail compiles it to HTML server-side. The htmlContent field serves as a fallback if MJML compilation has issues.

3. Preview with sample data

curl -X POST https://api.optail.io/v1/templates/TPL_ID/preview \
-H "Authorization: Bearer ms_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"variables": {
"name": "Jane",
"activationUrl": "https://app.example.com/activate?token=abc"
}
}'

The response contains the rendered HTML with variables replaced.

MJML Basics

MJML is a markup language that compiles to responsive HTML email. It handles the complex table-based layouts and inline styles that email clients require.

<mjml>
<mj-body>
<mj-section>
<mj-column>
<mj-image src="https://yourdomain.com/logo.png" width="150px" />
<mj-text font-size="20px" font-weight="bold">
Welcome, {{name}}!
</mj-text>
<mj-text>
Thanks for signing up. Click below to activate your account.
</mj-text>
<mj-button href="{{activationUrl}}" background-color="#4F46E5">
Activate Account
</mj-button>
</mj-column>
</mj-section>
</mj-body>
</mjml>

Key MJML components:

ComponentDescription
<mj-body>Root email body.
<mj-section>A horizontal row (like a table row).
<mj-column>A column within a section.
<mj-text>Text block with styling.
<mj-image>Responsive image.
<mj-button>Call-to-action button.
<mj-divider>Horizontal line separator.
<mj-spacer>Vertical spacing.

Handlebars Variables

Use {{ variableName }} syntax in your templates. Variables are replaced at send time with the values passed in the variables field.

<mj-text>Hello {{firstName}} {{lastName}}!</mj-text>
<mj-text>Your order #{{orderNumber}} has shipped.</mj-text>
<mj-button href="{{trackingUrl}}">Track Package</mj-button>

When sending:

await optail.send({
to: 'user@example.com',
from: 'orders@yourdomain.com',
subject: 'Your order #{{orderNumber}} has shipped',
templateId: 'tpl-uuid',
variables: {
firstName: 'Jane',
lastName: 'Doe',
orderNumber: '12345',
trackingUrl: 'https://tracking.example.com/12345',
},
});

Variables in the subject field are also replaced.

Versioning and Rollback

Every time you create a new version, it becomes the current (active) version. Previous versions are preserved.

List versions

curl https://api.optail.io/v1/templates/TPL_ID/versions \
-H "Authorization: Bearer ms_live_your_api_key"

Roll back to a previous version

curl -X POST https://api.optail.io/v1/templates/TPL_ID/rollback/VERSION_ID \
-H "Authorization: Bearer ms_live_your_api_key"

This sets the specified version as the current version without deleting newer versions. You can roll forward again at any time.

Preview a specific version

curl -X POST https://api.optail.io/v1/templates/TPL_ID/preview \
-H "Authorization: Bearer ms_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"versionId": "VERSION_ID",
"variables": { "name": "Jane" }
}'