Email Templates
Create reusable, named email templates for your project and send them to users by name. Templates use Mustache syntax: you author the subject and body once with {{variables}}, then supply the values with each send.
Sending emails from templates is part of Forte's server-side API. These operations require FORTE_API_TOKEN and must run in your backend. The email goes to the user's verified email address.
Create a template
Manage templates from your project's Settings → Email Templates tab, where a live preview renders your template with sample values as you type, or through the API:
await forte.projects.createCustomEmailTemplate({
projectId,
createCustomEmailTemplateRequest: {
name: "order-receipt",
subject: "Your receipt for order {{orderId}}",
htmlBody: "<p>Hi {{customerName}}, thanks for your order.</p>",
textBody: "Hi {{customerName}}, thanks for your order.",
},
});A template has a unique name within the project (1-64 characters: letters, numbers, underscores, hyphens), a subject, and at least one of htmlBody or textBody. When both bodies are present, the email is sent with both an HTML and a plain-text part. Names beginning with forte-, such as forte-welcome, belong to Forte-provided templates.
Forte reserves its built-in template namespace. Creating a custom email template in that namespace returns 400 CUSTOM_EMAIL_TEMPLATE_NAME_RESERVED.
Send a template
Send a saved template to a user with the send email template operation, supplying a value for each variable the template references:
await forte.projects.sendUserEmailFromTemplate({
projectId,
userId,
sendUserEmailFromTemplateRequest: {
templateName: "order-receipt",
templateParams: {
orderId: "1042",
customerName: "Alex",
},
},
});Variables the template references but the send omits render as empty strings. Values are HTML-escaped when rendered, so parameter content can't inject markup into your email.
Lists and repeating sections
A template parameter can also be a list, rendered with a Mustache section. The block between {{#items}} and {{/items}} repeats once per list item.
For a list of strings, {{.}} renders the current item:
<ul>
{{#highlights}}<li>{{.}}</li>{{/highlights}}
</ul>{ "templateParams": { "highlights": ["Free shipping", "Arrives Friday"] } }For rows with several fields — order lines, invoice items — use a list of objects and reference each field by name inside the section:
<table>
{{#items}}
<tr><td>{{name}}</td><td>{{quantity}}</td><td>{{price}}</td></tr>
{{/items}}
</table>{
"templateParams": {
"items": [
{ "name": "Widget", "quantity": "2", "price": "$18.00" },
{ "name": "Gadget", "quantity": "1", "price": "$9.00" }
]
}
}An inverted section {{^items}}...{{/items}} renders only when the list is empty or omitted:
{{^items}}<p>Your order has no items.</p>{{/items}}List items are strings all the way down: format numbers, currency, and dates in your backend before sending. Each templateParams value must be a string, a list of strings, or a list of flat objects whose values are all strings — anything else (numbers, true/false values, nested lists or objects) returns 400 CUSTOM_EMAIL_TEMPLATE_PARAMS_INVALID.
Limits
| Limit | Value |
|---|---|
templateParams entries per send | 100 |
| Items per list | 50 |
| Fields per list object | 20 |
| Characters per list string or field value | 1,000 |
Errors
| Error | Meaning |
|---|---|
404 CUSTOM_EMAIL_TEMPLATE_NOT_FOUND | No template with that name exists in the project |
400 CUSTOM_EMAIL_TEMPLATE_PARAMS_INVALID | A templateParams value isn't one of the allowed shapes, or exceeds a list limit |
400 CUSTOM_EMAIL_TEMPLATE_INVALID | The template body uses disallowed HTML (script tags, event handlers) or Mustache partials/comments |
400 CUSTOM_EMAIL_TEMPLATE_NAME_RESERVED | The template name uses the reserved forte- prefix |
400 USER_NO_VERIFIED_CONTACT_METHODS | The user has no verified email address to deliver to |
Next steps
- Send the built-in welcome email with the reserved
forte-welcometemplate: see Authentication → Welcome email - Learn about Contact Methods and how verification works