> ## Documentation Index
> Fetch the complete documentation index at: https://docs.notifique.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Variables, custom fields, and CRUD

> {{…}} placeholders, contact merge, defaults, per-channel payloads, and template management via API.

## In short

* Write `{{key}}` in the copy. At send time Notifique **fills** values from defaults, the contact, and request `variables`.
* Contact keys: use **`name`**, **`email`**, **`phone`**. Prefer English for built-in keys.
* **Management** and **send** use different scopes. See [API Key scopes](/en/template-api/como-funciona/escopos-da-api-key).

***

## Channels on a template

Each template chooses **which channels are active** (1 to 7): `sms`, `whatsapp`, `telegram`, `email`, `rcs`, `push`, `voice`.

In the API, use one root block per channel:

```json theme={null}
"sms": { "enabled": true, "payload": { "content": "..." } },
"rcs": { "enabled": false, "payload": {} }
```

On **send**, `channels` must be a **subset** of `enabledChannels`. A requested but disabled channel returns **400** (`TEMPLATE_CHANNEL_NOT_ENABLED`).

***

## Per-channel payloads (create / update)

| Channel    | Main `payload` fields                                                                                                                                                   |
| ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `sms`      | `content` (final text 9 to 160 after variables)                                                                                                                         |
| `whatsapp` | `content`, optional `mediaUrl`, `buttons` (`label` + HTTPS `url`)                                                                                                       |
| `telegram` | `content`, optional `mediaUrl`, `buttons`                                                                                                                               |
| `email`    | `subject`, `html` and/or `text`, optional `buttons`                                                                                                                     |
| `rcs`      | `messageType` (`BASIC` \| `CARD` \| `CAROUSEL` \| `FILE`), `message`, plus type fields: `cardImage`, `cardTitle`, `cardMessage`, `buttons`, `cards`, `file`, `fileName` |
| `push`     | `title`, `body`, optional `url`, `icon`, `image`, `data` (string map)                                                                                                   |
| `voice`    | `speakText`, optional `speakVoice`, optional `gather` (`prompt`, `maxDigits`, `timeoutSecs`, `voice`)                                                                   |

`{{…}}` variables also apply inside nested RCS strings, push title/body, and voice `speakText`.

***

## Variables in copy (`{{…}}`)

Two sources merge on send:

1. **From the template**: placeholders you typed. They need a value in `variables` or **`variableDefaults`**.
2. **From the contact**: filled automatically when the recipient exists in the workspace (except **Telegram-only** recipients).

**Priority order:** template defaults → contact data → custom fields → request **`variables`** (wins).

### Built-in contact keys

| Key in template    | Meaning                                    |
| ------------------ | ------------------------------------------ |
| `name`             | Contact name                               |
| `email`            | Email                                      |
| `phone`            | Phone (E.164)                              |
| `telefone`         | Same as `phone`                            |
| `url`              | Contact URL when set                       |
| `preferences_link` | Preferences / unsubscribe link (marketing) |

<Note>
  Prefer **`{{name}}`**. In some internal flows `nome` may be filled alongside `name`, but the stable API and editor contract is `name`. Send `variables.nome` only if your copy intentionally uses that key.
</Note>

<Info>
  **Telegram-only** recipients (`chat_id` or `@username`): automatic name/email merge **does not** run. Fill via `variables` or defaults.
</Info>

### Accepted formats

* **Named:** `{{order}}` → `variables: { "order": "123" }`
* **Positional:** `{{1}}`, `{{2}}` → keys `"1"`, `"2"`
* **Custom fields:** same CRM technical key, e.g. `{{current_plan}}`

***

## Custom fields

Each field has a **technical key** (`snake_case`, e.g. `current_plan`). In the template: `{{current_plan}}` with the same key.

Define them in the dashboard (**Contacts → Custom fields**) or via the Contacts API. After merge, values also apply to RCS, Push, and Voice.

***

## Defaults (`variableDefaults`)

If the send **does not** provide a key, the template default is used before failing on a missing variable. Contact data and request `variables` can still override it.

***

## Marketing and preferences

For templates with category **`MARKETING`**:

* `marketingTopicId`: ties the send to a communication topic
* `appendPreferencesLink` (default `true`): the platform fills `{{preferences_link}}` per recipient

Outside marketing, `preferences_link` may be empty: do not rely on it as the only CTA.

***

## Translations (`localeTranslations`)

You can store per-locale translations for fields of enabled channels. On send, the API picks copy based on the contact language preference when available. Placeholders `{{…}}` in translations must match the primary template.

***

## Management via API

| Operation       | Scope              |
| --------------- | ------------------ |
| List templates  | `templates:read`   |
| Get template    | `templates:read`   |
| Create template | `templates:create` |
| Update template | `templates:update` |
| Delete template | `templates:delete` |

**List query:** `page`, `limit`, `search` (name).

Minimal SMS-only example:

```json theme={null}
{
  "name": "reminder",
  "sms": {
    "enabled": true,
    "payload": { "content": "Hi {{name}}, reminder about your appointment." }
  },
  "whatsapp": { "enabled": false, "payload": {} },
  "telegram": { "enabled": false, "payload": {} },
  "email": { "enabled": false, "payload": {} },
  "rcs": { "enabled": false, "payload": {} },
  "push": { "enabled": false, "payload": {} },
  "voice": { "enabled": false, "payload": {} },
  "variableDefaults": { "name": "Customer" }
}
```

<Warning>
  **`templates:*`** scopes are for **management**. On **send**, each channel needs its send scope (including `voice:call` for voice).
</Warning>

## Official Meta templates (`WHATSAPP_OFFICIAL`)

`POST /v1/templates` and `PATCH /v1/templates/:id` use the **same validations** as the dashboard:

* required media on header/carousel (`META_TEMPLATE_MEDIA_REQUIRED`)
* carousel cards with the same structure (`META_TEMPLATE_CAROUSEL_INCONSISTENT`)
* rich structure only on official templates (`TEMPLATE_META_STRUCTURE_REQUIRES_OFFICIAL`)

On **send** (`POST /v1/templates/send` or `type: "template"` on each channel route) with `sk_live_`, the API also validates Meta token, **`metaName`**, media and carousel **before** queueing when the channel is official WhatsApp. With `sk_test_`, those Meta gates **do not** run (see [Sandbox](/en/guides/sandbox/index)).

Each channel route (`POST /v1/sms/messages`, `/v1/email/messages`, `/v1/whatsapp/messages`, etc.) accepts `type: "template"` + `payload.templateId` and fires **only** that channel, handy when you already use the native channel contract.

The internal **`name`** may differ from **`metaName`** (Graph name). Without a resolvable `metaName` → `META_TEMPLATE_NOT_FOUND`.

Full codes: [Error responses](/en/guides/conceitos/resposta-de-erros) (**Meta Cloud / official templates** accordion) and [Official Meta templates](/en/template-api/como-funciona/templates-oficiais-meta).

Full schemas: **API reference** on the Templates tab.

***

## See also

* [Introduction](/en/template-api/como-funciona/introducao)
* [Quick Start](/en/template-api/como-funciona/quick-start)
* [Error responses](/en/guides/conceitos/resposta-de-erros)
* [Official Meta templates](/en/template-api/como-funciona/templates-oficiais-meta)
