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.

Server-side API

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:

typescript
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.

Built-in template IDs are reserved

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:

typescript
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:

html
<ul>
  {{#highlights}}<li>{{.}}</li>{{/highlights}}
</ul>
json
{ "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:

html
<table>
  {{#items}}
  <tr><td>{{name}}</td><td>{{quantity}}</td><td>{{price}}</td></tr>
  {{/items}}
</table>
json
{
  "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:

html
{{^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

LimitValue
templateParams entries per send100
Items per list50
Fields per list object20
Characters per list string or field value1,000

Errors

ErrorMeaning
404 CUSTOM_EMAIL_TEMPLATE_NOT_FOUNDNo template with that name exists in the project
400 CUSTOM_EMAIL_TEMPLATE_PARAMS_INVALIDA templateParams value isn't one of the allowed shapes, or exceeds a list limit
400 CUSTOM_EMAIL_TEMPLATE_INVALIDThe template body uses disallowed HTML (script tags, event handlers) or Mustache partials/comments
400 CUSTOM_EMAIL_TEMPLATE_NAME_RESERVEDThe template name uses the reserved forte- prefix
400 USER_NO_VERIFIED_CONTACT_METHODSThe user has no verified email address to deliver to

Next steps

Search

Search your resources, console pages, and documentation