> For the complete documentation index, see [llms.txt](https://codemash.gitbook.io/codemash/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://codemash.gitbook.io/codemash/cloud/concepts/message-templates.md).

# Message templates

The reusable content of an email, SMS or push message — one template per message, one translation per project language, tokens filled per recipient.

> A **message template** is the reusable content of one message — per language — with tokens such as `@Model.FirstName` that are filled for each recipient when the message is sent.

## What it is

You should not paste the same text into every campaign and every trigger. A template keeps the content in one place: [campaigns](/codemash/cloud/concepts/campaigns.md), [triggers](/codemash/cloud/concepts/triggers.md), authentication flows and your own code point at it by id (`tmpl_…`), so a fix in the template reaches every future send. Message templates are one cross-cutting feature with three channels — **Email**, **SMS** and **Push**. The channels share the translations, the token rule, the type and the template actions; each channel has its own content.

## The parts

* **Name** and **Type** — **Transactional** or **Marketing**.
* **Translations** — one content per language. What a translation holds depends on the channel: an email has a subject and a body, an SMS has a text, a push has a title, a body and delivery options.
* **Tokens** — the blanks in the content, filled per recipient at send time. See the token rule below.
* **Actions** — every channel has the same actions: create, update, **Clone**, **Archive** / **Unarchive**, **Delete**, and a list of the tokens a template can use (`GET …/templates/{id}/tokens`).

## Rules that are the same everywhere

### The token rule

Every token in every part that Norbix renders must have a value before a message can go out.

* **A token is Razor only:** `@Model.FirstName`, `@Model.Person.FirstName`, or a `Model.X` argument inside a Razor call such as `@Model.Cmf.RenderSignature(Model.Email.SignatureId)`. `{{FirstName}}` is **not** a token — it is sent as plain text. Razor comments (`@* … *@`) and an escaped `@@` are not tokens either.
* **Every rendered part counts:** for example an email's subject and body, a push's title and body, and in a trigger also the pre-action code. A token found only in the subject still needs a value.
* **Who fills it:** reserved tokens (`Project.Name`, `Initiator.User.Email`, `Recipient.User.FirstName`, trigger tokens like `New.User.Email`) fill themselves. Your own tokens need a value from you on the campaign, task or test form.
* **Send waits for them.** The tokens panel under the template picker names every token still missing a value; the send buttons stay disabled until the list is empty.

Full syntax and every reserved token: [Tokens binding](/codemash/cloud/concepts/tokens-binding.md).

### Which language a message is sent in

The **project languages** decide everything: the default language plus the supported languages in [Project → Settings → Languages](/codemash/cloud/project/settings/languages.md).

* **A template needs every project language.** A campaign or a trigger that uses a template without a translation for each project language is refused (`CM-ERRORS-LANGUAGES-004`). Extra translations in a language the project does not have are allowed, but never sent.
* **The language of one message**, first match wins:
  1. the forced language picked on the campaign or trigger (it must be a project language, else `CM-ERRORS-LANGUAGES-003`);
  2. the recipient's language, when it is a project language;
  3. the project's default language.
* **Never "the template's first translation".** The order of the translations does not matter.
* **Changing the project languages is never blocked.** Before saving, Project settings lists the active templates that would miss a language and asks **Save anyway**. After that, campaigns and triggers using those templates are refused until you add the missing translations; each template list marks such a template with an amber **Missing …** badge.

### Other shared rules

* **What uses a template protects it.** Delete and Archive are refused while a trigger uses the template (`CM-ERRORS-TEMPLATES-010`) or an authentication flow uses it (`CM-ERRORS-TEMPLATES-011`). Change the trigger or the flow first. A campaign that already ran does not block either one.
* **Every send points at a template by id.** Editing a template changes every future send that uses it — including triggers and scheduler tasks.
* **Preview link.** Every sent message gets its own signed preview link that opens that one message, tokens filled in. See [Notification preview link](/codemash/cloud/concepts/message-templates/preview-link.md).

## Where it lives

| Channel | Portal page                                              | SDK methods                                    | API reference                                           |
| ------- | -------------------------------------------------------- | ---------------------------------------------- | ------------------------------------------------------- |
| Email   | [Email → Templates](/codemash/cloud/emails/templates.md) | [Email](/codemash/sdks/notifications/email.md) | [Email](/codemash/api-reference/notifications/email.md) |
| SMS     | [SMS → Templates](/codemash/cloud/sms/templates.md)      | [SMS](/codemash/sdks/notifications/sms.md)     | [SMS](/codemash/api-reference/notifications/sms.md)     |
| Push    | [Push → Templates](/codemash/cloud/push/templates.md)    | [Push](/codemash/sdks/notifications/push.md)   | [Push](/codemash/api-reference/notifications/push.md)   |

## What is different per module

| Channel | Content of one translation       | Own features                                                                                                                                                                                                                                                                                                                                                        |
| ------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Email   | subject and an MJML body         | System templates (read only), a [template marketplace](/codemash/cloud/emails/templates/marketplace.md), file attachments, [footers](/codemash/cloud/emails/footers.md) and [signatures](/codemash/cloud/emails/signatures.md). Tokens in the body are HTML-encoded; use `@Raw(...)` only for trusted HTML ([details](/codemash/cloud/concepts/tokens-binding.md)). |
| SMS     | text                             | One SMS part holds 160 characters; a longer text is split into parts. The sender belongs to the integration, not to the template. A render endpoint (`POST …/sms/templates/render`).                                                                                                                                                                                |
| Push    | title, body and delivery options | A render endpoint (`POST …/push/templates/render`).                                                                                                                                                                                                                                                                                                                 |

## Related

* [Campaigns](/codemash/cloud/concepts/campaigns.md) — send a template to an audience
* [Triggers](/codemash/cloud/concepts/triggers.md) — send a template when an event happens
* [Tokens binding](/codemash/cloud/concepts/tokens-binding.md) — every token and template function
