Skip to Content

Email Templates API

The Email Templates API lets administrators customize the transactional emails sent by Auris. Each of the thirteen template types corresponds to a specific event (verification, password reset, magic link, security alerts, …) and can be customized with HTML and dynamic variables, independently per locale.

Auris ships with default templates for all types in five locales (en, it, fr, de, es). When a custom template exists for a type and locale, it is used for all future emails of that type; otherwise the branded default is used. Resolution order at send time: custom (requested locale) -> custom (en) -> default (requested locale) -> default (en).

All endpoints require a Bearer token with the manage:security permission and select the tenant via the x-tenant header (the tenant’s realm identifier).

These endpoints return plain JSON objects — they do not use the { ok, data } envelope found in other parts of the Auris API.

List Templates

GET/api/email-templatesRequires: manage:security

List all thirteen template types with their customization status for the tenant. Full HTML bodies are not included — fetch a single template for that.

Success response (200)

{ "templates": [ { "type": "verification", "label": "Email Verification", "description": "Sent when a new user registers to verify their email address.", "variables": ["email", "link", "expiresIn", "year", "month", "day", "date"], "hasCustomTemplate": true, "active": true, "updatedAt": "2026-07-20T10:00:00.000Z", "customLocales": ["en", "it"] } ], "availableLocales": ["en", "it", "fr", "de", "es"], "wellKnownLocales": { "en": "English", "it": "Italiano", "pt-BR": "Português (Brasil)" } }
FieldTypeDescription
typestringTemplate type identifier (see Template Types below)
labelstringHuman-readable template name
descriptionstringWhen the email is sent
variablesstring[]Variables available for this type, including the auto-injected global date variables (year, month, day, date)
hasCustomTemplatebooleantrue if at least one custom version exists (any locale)
activebooleanWhether a custom version is active (true when no custom template exists — the default is always active)
updatedAtstring | nullISO 8601 timestamp of the most recent customization, or null
customLocalesstring[]Locales for which a custom version exists
availableLocalesstring[]Locales with built-in default templates
wellKnownLocalesobjectLocale code -> display label map used by the Console

Get Template

GET/api/email-templates/{type}?locale={locale}Requires: manage:security

Get a template for one locale: the custom content (if any) plus the branded default baseline. The locale query parameter defaults to en.

Success response (200)

{ "type": "verification", "locale": "it", "label": "Email Verification", "description": "Sent when a new user registers to verify their email address.", "variables": ["email", "link", "expiresIn", "year", "month", "day", "date"], "hasCustomTemplate": false, "subject": null, "htmlBody": null, "metadata": null, "active": true, "updatedAt": null, "defaultSubject": "Verifica il tuo indirizzo email", "defaultHtmlBody": "<!DOCTYPE html>...", "availableLocales": ["en", "it", "fr", "de", "es"], "customLocales": ["en"], "hasDefaultTemplate": true, "wellKnownLocales": { "en": "English", "it": "Italiano" } }

subject, htmlBody, and metadata are null when no custom template exists for the requested locale. defaultSubject and defaultHtmlBody always contain the built-in template, rendered with the tenant’s branding (logo, color, white-label footer) exactly as a live send would use it. hasDefaultTemplate indicates whether the requested locale has a built-in default (en, it, fr, de, es); other locales fall back to English.

Error responses

HTTPDescription
400Invalid template type or invalid locale code
401 / 403Missing or insufficient permissions
404Tenant not found

Update Template

PUT/api/email-templates/{type}Requires: manage:security

Create or update the custom template for one locale. The locale can be passed in the body or as a query parameter; it defaults to en. The saved template is active immediately.

Request body

{ "subject": "Verify your email — {{email}}", "htmlBody": "<!DOCTYPE html><html><body><h1>Verify your email</h1><p>Hello {{email}},</p><p><a href=\"{{link}}\">Confirm your address</a></p><p>The link expires in {{expiresIn}}.</p></body></html>", "locale": "en", "metadata": { "source": "code" } }
FieldTypeRequiredDescription
subjectstringYesEmail subject line. May include {{variable}} placeholders
htmlBodystringYesFull HTML email body. Maximum size 500 KB
localestringNoLocale code (BCP-47-like, e.g. en, pt-BR). Defaults to en
metadataobjectNoEditor state used by the Console (theme, builder layout, source mode). Validated against a closed schema — unrecognized fields are rejected, not silently dropped. Maximum size 256,000 characters

The HTML body is sanitized on the server before storage: <script> tags, event handler attributes (onclick, …), javascript:/data: URIs, <iframe>/<embed>/<object>/<form>/<base> tags, and dangerous CSS constructs are stripped.

Success response (200) — the saved template record:

{ "id": "cltpl123", "tenantId": "tnt_ScUtrVKUKGxtu7WY", "type": "verification", "locale": "en", "subject": "Verify your email — {{email}}", "htmlBody": "<!DOCTYPE html>...", "metadata": { "source": "code" }, "active": true, "createdAt": "2026-07-23T09:00:00.000Z", "updatedAt": "2026-07-23T09:00:00.000Z" }

Error responses

HTTPDescription
400Invalid template type, invalid locale, or missing subject/htmlBody
413htmlBody exceeds the 500 KB limit, or metadata exceeds 256,000 characters
422metadata does not match the expected schema (unrecognized shape or field)

Changes take effect immediately for all future emails of this type and locale. There is no staging or draft mechanism — preview and test the template before saving.

Delete Template

DELETE/api/email-templates/{type}?locale={locale}Requires: manage:security

Delete the custom template and revert to the built-in default. With the locale query parameter, only that locale’s custom version is deleted; without it, ALL locales for the type are deleted.

Success response (200)

{ "success": true }

Preview Template

POST/api/email-templates/{type}/previewRequires: manage:security

Render a subject and HTML body with realistic sample variables for the template type. Nothing is sent and nothing is stored.

Request body

{ "subject": "Verify your email — {{email}}", "htmlBody": "<!DOCTYPE html>..." }

Success response (200)

{ "subject": "Verify your email — [email protected]", "html": "<!DOCTYPE html>...", "variables": { "email": "[email protected]", "link": "https://console.auris.dev/verify-email?token=abc123", "expiresIn": "24 hours", "year": "2026", "month": "07", "day": "23", "date": "2026-07-23" } }

The variables field echoes the sample values that were substituted. The HTML body is sanitized before rendering; the subject is rendered as plain text (no HTML escaping of values).

Test Email

POST/api/email-templates/{type}/testRequires: manage:security

Render the given subject and HTML body with sample data and send them as a real email. By default the email goes to the authenticated administrator’s own address.

Request body

{ "subject": "Verify your email — {{email}}", "htmlBody": "<!DOCTYPE html>...", "recipientEmail": "[email protected]" }
FieldTypeRequiredDescription
subjectstringYesSubject line (with placeholders)
htmlBodystringYesHTML body (with placeholders)
recipientEmailstringNoOptional override recipient. When omitted (or empty), the test is sent to the authenticated admin’s own inbox. Must be a valid email address

Success response (200)

{ "success": true, "sentTo": "[email protected]" }

Error responses

HTTPDescription
400Invalid template type, missing subject/htmlBody, invalid recipientEmail, or the caller’s email address could not be determined
500Email delivery failed

The rendered subject is prefixed with [TEST] so test emails are easy to distinguish from real transactional mail. Delivery uses the tenant’s SMTP configuration when present and active, otherwise the platform default sender.

Template Types

Auris supports thirteen transactional email template types:

TypeWhen SentVariables
verificationA new user registers and must verify their emailemail, link, expiresIn
password_resetA user requests a password resetemail, link, expiresIn
invitationA user is invited to join a tenantemail, orgName, role, inviterEmail, link, expiresIn
mfa_codeEmail-based two-factor authenticationemail, code, expiresIn
magic_linkPasswordless login via magic linkemail, link, approveLink, expiresIn, tenantName
login_alertA new login is detected on the accountemail, device, ipAddress, location, time
welcomeA user successfully verifies their emailemail, name, orgName, dashboardLink
password_changedA password change is confirmedemail, name, time, ipAddress
account_lockedAn account is locked after failed login attemptsemail, name, lockDuration, attempts, ipAddress, time
suspicious_loginAn unusual login is detectedemail, name, device, ipAddress, location, time, reason
email_changedThe primary email changes (sent to the old address)email, name, newEmail, time
license_issuedA license key is issuedkey, jwtToken, product, expiresAt, features
cibaSign-in approval requested via CIBA backchannel flowemail, appName, bindingMessage, approveUrl, denyUrl

The global date variables year, month, day, and date (format YYYY-MM-DD) are auto-injected into every render, in addition to the per-type variables above.

Template Syntax

  • {{variable}} — replaced with the value. In the HTML body, values are HTML-escaped automatically to prevent injection; in the subject line values are inserted as plain text.
  • {{{variable}}} — raw interpolation without escaping. Only for trusted, server-built HTML fragments.
  • {{#if variable}}...{{/if}} — the block is kept only when the variable resolves to a non-empty string; otherwise it is removed entirely (markup included). Example: the magic_link default template renders the secondary approve button only when approveLink is provided.

Unknown placeholders are left as-is in the output. Dot notation and loops are not supported.

<h1>Sign in to {{tenantName}}</h1> <p><a href="{{link}}">Sign in on this device</a></p> {{#if approveLink}} <p><a href="{{approveLink}}">Approve on the original device</a></p> {{/if}} <p>The link expires in {{expiresIn}}.</p>

Permissions Reference

PermissionDescription
manage:securityList, view, update, delete, preview, and test all email templates for the tenant