> For the complete documentation index, see [llms.txt](https://docs.channel360.co.za/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.channel360.co.za/api-usage/send-a-template-notification/filling-template-placeholders.md).

# Filling template placeholders

Learn how to provide text, media, and button values for a template.

This page explains how to fill a template's placeholders in the `components` list of a [template notification](/api-usage/send-a-template-notification.md) request.

A placeholder is a numbered blank in an approved template, such as `{{1}}`.

## The rule

For every template part with placeholders, add one object to `components`.

List its `parameters` in order. The first value fills `{{1}}`. The second fills `{{2}}`.

Do not include the `{{ }}` braces in a value.

## From template to request

A template and the request that sends it describe the same parts, but in different shapes. This section puts them next to each other.

### The template

This is the approved template `order_shipped` (language `en`), as [Get one template by name](/api-usage/manage-templates-through-the-api.md#get-one-template-by-name) returns it. You can also see the same parts in **Templates** in the web app.

```json
{
  "name": "order_shipped",
  "language": "en",
  "status": "APPROVED",
  "components": [
    { "type": "HEADER", "format": "IMAGE" },
    { "type": "BODY", "text": "Hi {{1}}, your order {{2}} has shipped and will arrive on {{3}}." },
    { "type": "FOOTER", "text": "Thank you for shopping with us" },
    {
      "type": "BUTTONS",
      "buttons": [
        { "type": "URL", "text": "Track order", "url": "https://shop.example.com/track/{{1}}" }
      ]
    }
  ]
}
```

### How each part maps

| In the template                                 | Placeholders | In your request (`components`)                                                                     |
| ----------------------------------------------- | ------------ | -------------------------------------------------------------------------------------------------- |
| `name`: `order_shipped`                         | —            | `message.template.name`: `"order_shipped"`                                                         |
| `language`: `en`                                | —            | `message.template.language.code`: `"en"`                                                           |
| `HEADER` with `format`: `IMAGE`                 | the image    | `{ "type": "header", "parameters": [ { "type": "image", "image": { "link": "…" } } ] }`            |
| `BODY` with `{{1}}`, `{{2}}`, `{{3}}`           | 3            | `{ "type": "body", "parameters": [ … ] }` with three `text` values, in order                       |
| `FOOTER` with no placeholders                   | 0            | Leave it out                                                                                       |
| First entry in `BUTTONS`, URL ending in `{{1}}` | 1            | `{ "type": "button", "sub_type": "url", "index": "0", "parameters": [ … ] }` with one `text` value |

Four rules make the translation:

1. **Lowercase the type.** `HEADER` becomes `header`, `BODY` becomes `body`.
2. **One request entry per button, not one for all buttons.** `BUTTONS` becomes a separate `button` entry for each button that has a placeholder, with `index` set to its position, counting from `"0"`.
3. **One parameter per placeholder.** Count the `{{n}}` in that part; send exactly that many values, in order.
4. **Leave out parts with nothing to fill.** The footer here has no placeholders, so it does not appear in the request. A media header always needs its file, even though it shows no `{{n}}`.

## Worked example

This is the full request for the `order_shipped` template above:

```json
{
  "destination": "27821234567",
  "msg_id": "ORDER-10045",
  "message": {
    "type": "template",
    "template": {
      "name": "order_shipped",
      "language": { "code": "en" },
      "components": [
        {
          "type": "header",
          "parameters": [
            {
              "type": "image",
              "image": { "link": "https://shop.example.com/img/parcel.jpg" }
            }
          ]
        },
        {
          "type": "body",
          "parameters": [
            { "type": "text", "text": "Thandi" },
            { "type": "text", "text": "10045" },
            { "type": "text", "text": "Friday 9 October" }
          ]
        },
        {
          "type": "button",
          "sub_type": "url",
          "index": "0",
          "parameters": [
            { "type": "text", "text": "10045" }
          ]
        }
      ]
    }
  }
}
```

The customer receives the parcel image, "Hi Thandi, your order 10045 has shipped and will arrive on Friday 9 October.", the footer, and a tracking button. The button opens `https://shop.example.com/track/10045`.

{% hint style="warning" %}
The number of parameters must match the placeholders in that template part. WhatsApp rejects messages with too many or too few values.
{% endhint %}

## Fragments: drop these into `components`

The examples below are single entries for the `components` list, not complete requests. Put them inside `message.template.components` in a request like the worked example above.

### Use media in a header

An image, video, or document header needs a public `https://` link. WhatsApp downloads the file from that link.

```json
{
  "type": "header",
  "parameters": [
    { "type": "video", "video": { "link": "https://example.com/video.mp4" } }
  ]
}
```

Use this shape for a document header:

```json
{
  "type": "header",
  "parameters": [
    {
      "type": "document",
      "document": {
        "link": "https://example.com/invoice.pdf",
        "filename": "invoice.pdf"
      }
    }
  ]
}
```

### Fill a URL button

Set `index` to the button position, starting at `"0"`.

```json
{
  "type": "button",
  "sub_type": "url",
  "index": "0",
  "parameters": [
    { "type": "text", "text": "10045" }
  ]
}
```

Leave template parts without placeholders out of `components`.

For a template with no placeholders, send an empty list:

```json
{ "components": [] }
```

## Next

{% content-ref url="/pages/RJMlaxNFSbVbTDbJ9pC3" %}
[Tags vs. the API](/api-usage/concepts/tags-vs-the-api.md)
{% endcontent-ref %}

{% content-ref url="/pages/UAUsKmCKXoQDu5gIwW8Q" %}
[Templates, placeholders and components](/api-usage/concepts/templates-placeholders-and-components.md)
{% endcontent-ref %}
