# SMS templates

A template is a pre-registered message body you send by reference instead of inlining the text on every call. It carries its own category and a set of typed variable slots, so a send only supplies the values that change (an OTP code, an order number) and Bird assembles the final message. The catalog is Bird's built-in **system** templates: a fixed set covering common authentication and transactional messages. Authoring your own **workspace** templates is not yet available.

Compared with a [free-text send](/docs/guides/sms/sending-sms), a template send settles two decisions up front: the message category comes from the template, so the classification that per-country compliance rules key on is decided by the template rather than by each caller, and Bird selects the sender for the destination, so you don't pass `from`.

## Browsing templates in the dashboard

The [**Templates**](https://bird.com/dashboard/w/sms/templates) page, under SMS, lists every template available to your workspace. Search by name and filter by status or category to find one.

![The SMS Templates tab: a search box with Status and Category filters above a table of templates, each row showing a name, an Active status, a category, an EN language chip, and a System scope, across Name, Status, Category, Language, Scope, and Updated columns.](/images/docs/dashboard-sms-templates.png)

Each row shows the fields you need to pick and send a template:

- **Name**: the human-readable title, with the template's stable reference (for example `bird_order_confirmation`) below it. The reference is what you pass when sending; it never changes.
- **Status**: the template's lifecycle state. Built-in system templates are always **Active**, live and sendable. The **Draft**, **Pending**, **Approved**, and **Rejected** states track a workspace-authored template through review, and apply once workspace templates are available.
- **Category**: the content classification (`transactional`, `marketing`, `authentication`, or `service`) applied to every message sent from the template.
- **Language**: the languages the template is stocked in, as BCP 47 tags. The first few are shown as chips with a `+N` overflow when a template is localized into many languages.
- **Scope**: **System** for Bird's built-in templates. Every template is System today; **Workspace** covers templates your own workspace authors, once that's available.
- **Updated**: when the template last changed. Built-in templates show no date.

## What's in a template

Alongside its name, category, and languages, each template defines the **variables** it fills in at send time. A variable is a typed slot with a `key` (the name you supply a value under), a `type`, a `required` flag, and a human-readable `constraint` describing the accepted values. When you send, you supply a value for every required variable and no undeclared keys.

A template is stocked in one or more **languages**. You pick one per send; if you request a language the template isn't stocked in, Bird falls back to the closest available language and then to English rather than failing.

## Listing templates from the API

`GET /v1/sms/templates` returns the catalog in full; it is small and not paginated. Filter by `scope`, `category`, or `language` to narrow it:

```bash
curl "https://eu1.platform.bird.com/v1/sms/templates?category=authentication" \
  -H "Authorization: Bearer bk_eu1_..."
```

Each template in the response carries its `name` (the reference you send by), `scope`, `category`, `status`, `available_languages`, the `variables` it expects, and a `body` preview of the default-language text with the variable placeholders inline. Fetch a single template by its reference with `GET /v1/sms/templates/{template_ref}` to read its variables before a send.

## Sending with a template

Set the send's `template` object instead of `text`. Because the template decides the message and its sender, `text`, `category`, `from`, and `media_urls` are not accepted alongside it:

```bash
curl -X POST https://eu1.platform.bird.com/v1/sms/messages \
  -H "Authorization: Bearer bk_eu1_..." \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+31612345678",
    "template": {
      "name": "bird_otp_verification_ttl",
      "language": "en",
      "parameters": { "code": "481920", "ttl": "10" }
    }
  }'
```

`name` is the template reference from the catalog (you can identify a template by its `id` instead). `language` selects the localized body; omit it for English. `parameters` supplies a value for each of the template's variables, keyed by variable name. A missing required variable, an undeclared key, a value that doesn't match its variable's constraint, or a `parameters` object over 16 KB serialized is rejected with a `422`.

The `202` response shows what the template resolved to: the rendered body in `text`, the template's `category`, and the sender Bird selected in `from`:

```json
{
  "id": "sms_01ky7qc2nmf1s8fe22xd4qdvre",
  "direction": "outbound",
  "status": "accepted",
  "to": "+31612345678",
  "from": "Authifly",
  "text": "481920 is your verification code. It expires in 10 minutes. Do not share it.",
  "category": "authentication",
  "segments": { "count": 1, "encoding": "GSM_7BIT", "characters": 76 },
  "cost": null,
  "carrier": null,
  "mcc_mnc": null,
  "sent_at": null,
  "delivered_at": null,
  "created_at": "2026-07-23T14:51:45.716Z"
}
```

Everything else about the send (the recipient, tags, metadata, the destination allowlist, and the async `202` model) works exactly as it does for a [free-text send](/docs/guides/sms/sending-sms).

## Next steps

- [Sending SMS](/docs/guides/sms/sending-sms): the full send payload that the `template` field slots into
- [SMS log](/docs/guides/sms/sms-log): find a sent message and follow its lifecycle
- [Events](/docs/guides/sms/events): the webhook events that report each message's delivery