Parameters and types
Every template has a parameter schema. It documents what the template expects, powers the
params panel in the editor, generates TypeScript types and – most
importantly – validates every send. A request whose params don’t match fails with
422 invalid_template_params before any credit is used.
Defining params
Section titled “Defining params”Each param has:
| Field | Meaning |
|---|---|
name |
Identifier used in the template, e.g. customer_name. Letters, digits, _ and -; dotted names like customer.name are allowed and produce nested objects. frontmail, this and root are reserved. |
label, description |
Shown in the params panel and in generated snippets. |
type |
One of the types below. |
required |
Missing (or empty) value → error. |
default |
Used when the value is missing. A param with a default never fails as required. |
sampleValue |
Used by the preview and test sends. |
| Rules | minLength / maxLength, min / max, pattern (regex), enumValues, itemFields – depending on the type. |
In the editor, open Parameters and add params with Add parameter, or click Detect from
template: Frontmail scans the HTML, subject and
recipient fields for {{placeholders}} and proposes a param for each, including item fields used
inside {{#each}} blocks.
| Type | Accepts (JSON) | Coercion from strings (forms) | Rules | Output in template |
|---|---|---|---|---|
string |
string, number, boolean | converted to string | minLength, maxLength, pattern |
escaped text |
text |
same as string |
same | same | escaped text; use {{nl2br x}} to keep line breaks |
email |
string | trimmed | must be a valid address (max 254 chars); maxLength, pattern |
escaped text |
url |
string | trimmed | http, https, mailto or tel only |
escaped text |
number |
number | "1234.5", "1 234,5" (spaces and a decimal comma are accepted) |
min, max |
number (use formatNumber / formatMoney) |
boolean |
boolean, 1, 0 |
true/false, on/off, 1/0, yes/no, y/n, ano/ne (case-insensitive) |
– | true / false for {{#if}} |
date |
ISO string, epoch milliseconds | YYYY-MM-DD (kept as a calendar date) or YYYY-MM-DDTHH:mm… (normalized to ISO UTC) |
– | string (use formatDate) |
enum |
string or number | trimmed | value must be in enumValues |
escaped text |
html |
string | – | minLength, maxLength |
sanitized HTML, rendered as markup |
list |
array of objects | a JSON string is parsed | min, max items (default max 500); each item validated against itemFields |
array for {{#each}} |
Other rules:
- An empty string or
nullcounts as missing, sorequiredanddefaultapply. - String params without
maxLengthare capped at 50,000 characters. - All params together may be at most 256 kB of JSON; larger payloads fail with
payload_too_large. patternmust match the whole value (it is anchored automatically), e.g.[A-Z]{2}\d{4}.
Coercion from form data
Section titled “Coercion from form data”sendForm() and POST /v1/send-form submit multipart/form-data, where every value is a string.
Frontmail converts them using the declared types, so the same template works for JSON and forms:
<input name="guests" value="3"> <!-- number → 3 --><input name="price" value="1 299,50"> <!-- number → 1299.5 --><input type="checkbox" name="newsletter"> <!-- checked "on" → true; unchecked → missing → default --><input type="date" name="arrival"> <!-- "2026-10-01" stays "2026-10-01" --><input type="hidden" name="items" value='[{"title":"Room","qty":1}]'> <!-- list → parsed JSON -->File inputs become attachments, not params.
Unknown params and strict mode
Section titled “Unknown params and strict mode”By default, params that are not in the schema are passed through to the template (so you can
start sending before you finish the schema). Turn on Strict parameters in Security → Abuse protection to reject
them with an unknown_param issue instead – recommended for public-key templates.
The error response
Section titled “The error response”{ "error": { "code": "invalid_template_params", "message": "Invalid template parameters. email: Invalid email address. message: Must be at least 10 characters.", "docs_url": "https://docs.frontmail.dev/reference/errors/#invalid-template-params", "details": { "issues": [ { "param": "email", "code": "invalid_email", "message": "Invalid email address." }, { "param": "message", "code": "too_short", "message": "Must be at least 10 characters.", "meta": { "min": 10 } }, { "param": "items[2].qty", "code": "too_small", "message": "Must be at least 1.", "meta": { "min": 1 } } ] } }}Issue codes: required, invalid_type, too_short, too_long, too_small, too_big,
invalid_format, invalid_email, invalid_url, invalid_enum, invalid_date, unknown_param,
payload_too_large. Use param to put the message next to the right form field; meta carries
the limit so you can translate the message yourself.
Escaping and the html type
Section titled “Escaping and the html type”Every value is HTML-escaped when rendered – even inside {{{triple braces}}}, which Frontmail
treats like {{double braces}}. That way nobody can inject markup into your email through a
public key. If you need rich text, declare the param as html: it is run through a strict
sanitizer (formatting tags, links, tables and images only; no scripts, forms, iframes or event
handlers; only safe inline styles). Details in the Handlebars guide.