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.
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.
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.comare 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:
<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 |
400 EMAIL_CONFIGURATION_INVALID | Your account has no verified sending domain yet. Complete compliance registration, or use the sandbox email sender in a sandbox project |
400 SANDBOX_EMAIL_RECIPIENT_UNVERIFIED | Sandbox sender only: the user's email was marked verified with an override instead of a code or Google sign-in |
402 SANDBOX_EMAIL_QUOTA_EXCEEDED | Sandbox 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.
| Tab | Message | Customizable fields | Variables |
|---|---|---|---|
| Verification | Contact-method verification code | Email subject, email HTML body, SMS body | {{code}} (required in both bodies), {{projectName}}, {{contactValue}} |
| Welcome | Welcome 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 OTP | OTP login code | Email subject, email HTML body, SMS body | {{code}} (required in both bodies), {{projectName}}, {{contactValue}} |
| Invite | User invite email | Email subject, email HTML body | {{projectName}}, {{contactValue}}, {{inviterName}}, plus any custom attributes sent with the invite |
| Password reset | Password reset notification | Email 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.
await forte.projects.updateNotificationTemplates({
projectId,
updateNotificationTemplatesRequest: {
welcomeOnEmailEnabled: true,
welcomeOnGoogleEnabled: true,
welcomeEmailSubject: "Welcome aboard, {{userFullName}}",
welcomeEmailHtmlBody: "<p>Thanks for joining {{projectName}}.</p>",
},
});| Message | Request fields |
|---|---|
| Verification | emailVerificationSubject, emailVerificationHtmlBody, smsVerificationBody |
| Welcome | welcomeOnGoogleEnabled, welcomeOnEmailEnabled, welcomeOnSmsEnabled, welcomeEmailSubject, welcomeEmailHtmlBody, welcomeSmsBody |
| Login OTP | loginOtpEmailSubject, loginOtpEmailHtmlBody, loginOtpSmsBody |
| Invite | inviteEmailSubject, inviteEmailHtmlBody |
| Password reset | passwordResetEmailSubject, passwordResetEmailHtmlBody, passwordResetSmsBody |
Next steps
- Turn on or send the built-in welcome message, including on demand with the reserved
forte-welcometemplate: see Authentication → Welcome message - Learn about Contact Methods and how verification works