Templates
A template is the email an event type sends. Each event type has at most one, your platform’s default, and every workspace sends it when you emit that type. Your team builds it in the console’s block editor, or your code saves it through the API; both write the same format. Every save is a new version and goes live in every workspace at once, so preview before you save.
What a template holds
Section titled “What a template holds”subject, which can carry merge tags.from_local_part, the part of the from address before the@. The part after is the sending workspace’s own subdomain of your domain, sobookingssends asbookings@pine-valley.yourplatform.com. It is plain text, with no merge tags.display_name, the sender’s name the recipient sees. It can carry merge tags, and{{ workspace_name }}is the usual choice, so your customer’s guests see your customer’s name rather than yours.reply_to, an address or exactly one merge tag, such as{{ event.host_email }}, for when only your data knows your customer’s own address.locale, the language the template is written in. The first save must name it.composition, the email’s blocks in order: headings, text, buttons, images, columns, line items and more.translations, optional, for every other language you send in.
The composition format is easiest to learn by building an email in the console’s editor and reading it back with Get an event type’s default template.
Merge tags
Section titled “Merge tags”A merge tag is {{ token }}, or {{ token | fallback text }} with a fallback of its own. The tokens a template can use:
| Tag | What it is |
|---|---|
{{ event.<field> }} |
a field of the event’s payload, by its name in the schema |
{{ item.<field> }} |
a field of one record, inside a line-items block |
{{ email }} |
the recipient’s address |
{{ attributes.<key> }} |
one of the contact’s attributes |
{{ workspace_name }} |
the sending workspace’s name |
A tag that names nothing (a field the schema doesn’t have, an attribute with no definition) is refused when you save, naming the tag, so a typo never reaches a recipient.
When a tag has no value at send time, it renders its own fallback, else the field’s fallback from the schema, else nothing. The email goes out either way, and the emit’s answer lists the tags that fell back in message.fell_back.
Values are escaped, so a guest named <b>Ana</b> shows up as exactly that text. A tag that is a whole link renders only an http or https URL, and shows its fallback for anything else. A tag inside a longer link must come after the host, so data can add to a link’s path or query but never change where it goes.
Template email is transactional, so it carries no unsubscribe link and {{ unsubscribe_url }} is refused.
Saving through the API
Section titled “Saving through the API”Save an event type’s default template with a PUT:
curl -X PUT https://api.sendtruss.com/v1/event-types/booking.created/template \ -H "Authorization: Bearer $SENDTRUSS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "subject": "Your booking at {{ workspace_name }} is confirmed", "from_local_part": "bookings", "display_name": "{{ workspace_name }}", "locale": "en", "composition": { "editorVersion": 3, "target": "email", "document": { "blocks": [ {"id": "title", "type": "heading", "attrs": {"text": "See you soon, {{ event.guest_name }}"}}, {"id": "intro", "type": "text", "attrs": {"html": "Your booking starts on {{ event.arrival }}."}} ] } } }'- The first save answers 201 with version 1. Each save that changes something writes the next version and answers 200.
- A save identical to the current version writes nothing and answers with the current one, so your deploy can push its templates every time it runs.
- Send
base_version, the version you started from, to have the save refused withversion_conflictif someone saved a newer one since. The console always does, so your team and your code can’t silently overwrite each other.
If you’re porting an email you already send, you can paste its HTML into a single HTML block and have a working template on day one. Text inside an HTML block can’t be translated, though, so moving the text into text blocks is worth doing.
Versions
Section titled “Versions”Every version stays. List the versions, read one, and restore one, which saves its content as the next version. Restoring is a save like any other: live in every workspace at once.
Preview before you save
Section titled “Preview before you save”Preview a template renders the email a send would, without sending it. Render an unsaved draft, a saved version, or the current version when you send neither, with a payload, a contact, a locale and a timezone of your choosing:
curl -X POST https://api.sendtruss.com/v1/event-types/booking.created/template/preview \ -H "Authorization: Bearer $SENDTRUSS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "locale": "en", "payload": {"guest_name": "Ana", "arrival": "2026-10-12"} }'Leave out payload or contact and the preview uses sample values built from the schema and your attribute definitions. With a payload, an optional field it leaves out renders its fallback, as it would in a real send. The workspace name always shows a sample name, since the preview isn’t for one workspace. The answer carries the subject, the HTML, a plain-text version, the from fields and the tags that fell back.
Translations
Section titled “Translations”Translations are field by field: each text in the composition can carry a translation per locale. Send them in translations, by locale, then by the text’s field id, each with its translated text and the source text it was translated from. The console keeps them on every save; in this version they are written through the API.
At send time we pick the contact’s locale, else the workspace’s. A field takes the translation for that locale, else for its language alone (de-AT falls back to de), else the template’s own text.
When a save changes a text that has translations, those translations are now out of date. The save is refused with translations_outdated, naming each locale and field, unless you send fresh translations or accept_outdated: true to keep the old ones.
Which variables a workspace’s template uses
Section titled “Which variables a workspace’s template uses”Get the variables a workspace’s template uses lists the event fields, contact attributes and system tags in the template a workspace sends for an event type, so you know which payload fields and attributes matter:
curl https://api.sendtruss.com/v1/workspaces/ref:cust_4821/event-types/booking.created/variables \ -H "Authorization: Bearer $SENDTRUSS_API_KEY"Today every workspace sends your default, so the answer is the same for all of them. version and variables are null when the type has no template yet.