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.

Forte also sends built-in messages for you, such as verification codes and the welcome message. You can reword those too: see Built-in notification messages.

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.

Sandbox email sender

Sending email normally requires an approved compliance registration, which sets up your own sending domain. Sandbox projects can send before that: in your project's Settings → Authentication → Authentication Methods, set Email sender to Forte sandbox. This also lets you turn on email and password sign-in, and email one-time codes for multi-factor authentication, in that project.

Mail from the sandbox sender works differently from mail sent from your own domain:

  • It comes from fortesandbox.com, its subject starts with [Sandbox], and a banner at the top shows your project ID.
  • Each account can send up to 5 emails per UTC day this way, counting every email it sends: verification, sign-in, and MFA codes, invites, and template sends. Contact support if you need a higher limit.
  • Template emails and password resets go only to addresses the user verified themselves, with an emailed code or Google sign-in. Addresses you mark verified with a sandbox override or the admin verify operation don't count, so have the user verify the address with the code before sending to it.
  • Built-in messages (verification codes, invites, password resets) use Forte's default wording and refer to your project by its ID. Your notification customizations apply once you switch to your own domain.
  • Reserved test addresses such as jane@example.com are never delivered. The message, including any code, appears in the user's activity log instead. Codes sent to real addresses aren't shown in the activity log.
  • A new sending domain can land in spam at first, so check your spam folder.

Once your compliance registration is approved and your domain is verified, switch Email sender to Your domain. The limits above no longer apply.

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
400 EMAIL_CONFIGURATION_INVALIDYour account has no verified sending domain yet. Complete compliance registration, or use the sandbox email sender in a sandbox project
400 SANDBOX_EMAIL_RECIPIENT_UNVERIFIEDSandbox sender only: the user's email was marked verified with an override instead of a code or Google sign-in
402 SANDBOX_EMAIL_QUOTA_EXCEEDEDSandbox sender only: your account has reached its daily sandbox email limit (UTC)

Built-in notification messages

Forte sends these messages to your users automatically. Customize any of them under Settings → Notifications in your project, where each message has its own tab with a live preview. Leave a field blank to use Forte's built-in default.

TabMessageCustomizable fieldsVariables
VerificationContact-method verification codeEmail subject, email HTML body, SMS body{{code}} (required in both bodies), {{projectName}}, {{contactValue}}
WelcomeWelcome message on sign-up, plus per-channel on/off toggles (Google, Email, SMS; all off by default)Email subject, email HTML body, SMS body{{projectName}}, {{userFullName}}, {{contactValue}}
Login OTPOTP login codeEmail subject, email HTML body, SMS body{{code}} (required in both bodies), {{projectName}}, {{contactValue}}
InviteUser invite emailEmail subject, email HTML body{{projectName}}, {{contactValue}}, {{inviterName}}, plus any custom attributes sent with the invite
Password resetPassword reset notificationEmail subject, email HTML body, SMS body{{newPassword}} or {{resetUrl}} (by reset mode), {{projectName}}, {{contactValue}}

Built-in messages follow the same Mustache rules as your own templates, except they accept only the variables listed for that message. A save with any other variable, a Mustache partial or comment, or HTML with script tags or event handlers returns 400 NOTIFICATION_TEMPLATE_INVALID. Omitting a required variable returns 400 NOTIFICATION_TEMPLATE_MISSING_REQUIRED_VARIABLE.

To manage the same settings from code, use getNotificationTemplates (returns your current overrides and Forte's defaults) and updateNotificationTemplates. The update is a partial patch: omitted fields keep their current value, and an empty string resets a field to Forte's default.

typescript
await forte.projects.updateNotificationTemplates({
  projectId,
  updateNotificationTemplatesRequest: {
    welcomeOnEmailEnabled: true,
    welcomeOnGoogleEnabled: true,
    welcomeEmailSubject: "Welcome aboard, {{userFullName}}",
    welcomeEmailHtmlBody: "<p>Thanks for joining {{projectName}}.</p>",
  },
});
MessageRequest fields
VerificationemailVerificationSubject, emailVerificationHtmlBody, smsVerificationBody
WelcomewelcomeOnGoogleEnabled, welcomeOnEmailEnabled, welcomeOnSmsEnabled, welcomeEmailSubject, welcomeEmailHtmlBody, welcomeSmsBody
Login OTPloginOtpEmailSubject, loginOtpEmailHtmlBody, loginOtpSmsBody
InviteinviteEmailSubject, inviteEmailHtmlBody
Password resetpasswordResetEmailSubject, passwordResetEmailHtmlBody, passwordResetSmsBody

Next steps

Search

Search your resources, console pages, and documentation