Templates as parameters
A MostlyRender template is a canvas (width × height, background) plus a stack of named layers. The key idea:
The layer name is the API parameter. To change what a layer shows at render time, send
modificationskeyed by the layer’s name.
# Modifications
Given a template with a text layer named title, an image layer named photo, and a
QR layer named link:
{
"template": "tpl_abc",
"modifications": {
"title": "Renders that never go dark",
"photo": "https://example.com/hero.jpg",
"link": "https://mostlyrender.com"
}
}
- A string on a text layer sets its text.
- A string on an image layer sets its
src. - A string on a QR layer sets the encoded value.
- An object is merged into the layer, so you can override styling too:
{ "modifications": { "title": { "text": "On sale", "color": "#e11d48" } } }
Layers you don’t mention keep their designed defaults. Unknown layer names are ignored.
# Declared params: types, required fields and defaults
Layer names work with no setup, but every value is plain text and nothing is required — a missing name just renders the designed placeholder. To get a real contract, open Params in the editor and choose Declare params to customise. The template then carries a typed list of params:
{
"params": [
{ "key": "name", "type": "text", "label": "Guest name", "required": true, "maxLength": 60 },
{ "key": "photo", "type": "image" },
{ "key": "tier", "type": "enum", "values": ["guest", "speaker", "vip"], "default": "guest" },
{ "key": "date", "type": "date" }
]
}
| Type | Accepts | Renders as |
|---|---|---|
text, longtext |
strings and numbers (maxLength optional) |
the text |
number |
numbers or numeric strings (min / max optional) |
the number |
date |
YYYY-MM-DD, an ISO timestamp or epoch milliseconds |
YYYY-MM-DD |
bool |
true/false, 1/0, yes/no, on/off |
drives show/hide conditions |
enum |
one of values, exactly |
the value |
colour |
#rrggbb, rgb(), hsl() or a colour name |
the colour |
url, image |
http(s) URLs only |
the link / the image |
qr |
the text or link to encode | a QR code |
html |
an HTML fragment | sanitised HTML (bold, lists, line breaks…) |
What changes once params are declared:
- A required param that is missing or empty fails the render with HTTP
400and a stable code in the error (param-required), instead of rendering an empty field. A wrong value fails the same way (param-not-in-enum,param-invalid-url,param-out-of-range, …). - A param with a default uses it when you don’t send a value.
- Values are converted to their type, so
"seats": "2"arrives as the number2. - A layer can bind to a param with a different name than the layer itself — set the layer’s param binding. Two layers can share one param.
- Unknown keys still pass through on single renders (as before), so existing integrations keep working.
The editor’s Params panel also has a sample-values form: type a row of values and it shows exactly which ones would be rejected, with the same rules the API applies, plus a preview of the filled template.
# HTML templates and {{{raw}}}
In an HTML template, {{name}} is always escaped. Once a template declares params,
{{{name}}} (raw HTML) is only allowed for a param of type html, and its value is
sanitised on our side — formatting tags stay, scripts, event handlers, links and external
URLs are removed. Saving a declared template that uses {{{name}}} for any other param is
refused. Templates that don’t declare params behave exactly as before.
# The canvas background is a parameter too
The canvas background isn’t a layer, so it has a reserved parameter name: background
(lowercase). Send it in modifications to swap the background at render time — the same
solid / gradient / image forms the editor produces:
{
"template": "tpl_abc",
"modifications": {
"title": "Q3 results",
"background": "#0b1020"
}
}
// a gradient
{ "modifications": { "background": { "type": "gradient", "value": "linear-gradient(135deg,#23204a,#5b5bd6)" } } }
// an image (URL must be a public http(s) URL — data-URIs are rejected by the SSRF guard)
{ "modifications": { "background": { "type": "image", "src": "https://cdn.example.com/hero.png", "fit": "cover" } } }
# {{placeholders}} inside a background
Instead of replacing the whole background, a template can bake placeholders into it and you
fill them per render. In the editor’s Background panel, set a value containing
{{param}}; then pass that param in modifications:
// template background (set in the editor): {{brandColor}}
// or an image: url("{{heroUrl}}") center/cover
{ "modifications": { "brandColor": "#ff5a00", "heroUrl": "https://cdn.example.com/u/42.png" } }
Defaults for placeholders can live in the template’s vars; a modification of the same name
overrides the default. Background placeholders are substituted raw (they land in CSS, not
HTML), so a URL’s query string (?w=1&h=2) is preserved verbatim.
# Reading a template’s params
GET /v1/templates/:id/params returns the typed params a render (or a
generator) validates against: the ones the template declares, or, for a
template that declares none, the implicit ones (its layer names and {{vars}}):
{ "template_id": "tpl_abc", "version": 3, "declared": true, "engine": "layers",
"params": [{ "key": "title", "type": "text", "required": true }, { "key": "photo", "type": "image" }] }
?version= picks a published version (n, latest or draft). Publishing a template
snapshots an immutable version; a generator pins one, so later edits never change files it
already rendered. To render a template for many rows at once (a name badge per guest, a
card per product), see Generators.
# Listing templates
curl https://api.mostlyrender.com/v1/templates \
-H "Authorization: Bearer mr_live_…"
{
"templates": [
{ "id": "tpl_abc", "name": "Launch card", "width": 1200, "height": 630, "engine": "layers" }
]
}
Use the id as the template in a render call. Manage templates (create, edit,
delete) in the app editor.