# Templates

## Register a template

**post** `/v1/templates`

Registers a template and submits it for review, synchronously.

The call returns once the channel has accepted the submission, so a name
or a body it refuses is a `422` you read immediately rather than a silence
you discover later. What comes back is almost always `status: "pending"`:
review is an unbounded queue and an hour or more is ordinary. **Nothing is
sendable until it is `approved`** — watch for it on `GET /v1/templates`.

Status is never ours to assert. An approved template can be paused later
for quality and approved again afterwards, and this API reports what the
channel currently says rather than what it said at submission.

A refusal decided before any submission attempt records nothing, and its
message says so: the name remains reusable. Once a submission is attempted,
its evidence remains visible as `status: "draft"` with the derived
parameter schema even if the attempt is refused or its answer is lost. A
definitive refusal leaves the name reusable after correction; an unknown
outcome permanently fences the name and must not be retried. This ordering prevents
an accepted template from becoming invisible here. A name that is already
registered beyond draft answers `409` — submitted names are permanent.
An account with no messaging channel answers retryable HTTP 503
`no_channel_account` with `error.type` `api_error`, not a validation
error. It carries no `Retry-After` because setup has no honest completion
time to publish.
An invalid channel credential likewise answers HTTP 503
`template_channel_unavailable` with `error.type` `api_error`, not 422
`template_refused`: rotating that credential is this service's repair,
not a change to the template. It carries no `Retry-After` because rotation
is an operator action rather than a clock boundary.

Media-header preparation is bounded and resumable. While the same request
is actively preparing, HTTP 503 `template_submission_in_progress` asks
you to retry the unchanged body. Exhausted preparation answers HTTP 503
`template_asset_unavailable`. Once the template-create call may have
reached the channel but its answer is unknown, HTTP 409
`template_outcome_indeterminate` is permanent: do not resubmit that name;
registry reconciliation must establish the outcome. HTTP 201 is returned
only after the channel accepted the template submission.

### Body Parameters

- `category: string`

  `utility`, `marketing` or `authentication`.

  The channel may RECATEGORISE on review — copy that reads as marketing is
  treated as marketing whatever was requested — and the assigned category is
  what the send is priced at. Read `category` back off the response and off
  `GET /v1/templates`.

- `language: string`

  The locale this variant is written in, such as `en_US`. One template name may have several language variants, each registered separately.

- `name: string`

  Lowercase letters, digits and underscores. Permanent once submitted: a name cannot be reused for different copy.

- `authentication: optional object { otp_type, add_security_recommendation, autofill_text, 6 more }`

  Selects the fixed-copy authentication specialization. Valid only when `category` is `authentication`; omit to retain ordinary body authoring.

  - `otp_type: "copy_code" or "one_tap" or "zero_tap"`

    `copy_code` works on every client. `one_tap` and `zero_tap` are Android app integrations and require both app identity fields.

    - `"copy_code"`

    - `"one_tap"`

    - `"zero_tap"`

  - `add_security_recommendation: optional boolean`

    Include the channel's localized security recommendation.

  - `autofill_text: optional string`

    Localized Android one-tap button label, maximum 25 characters.

  - `code_expiration_minutes: optional number`

    Show the localized code-expiry footer. Whole minutes from 1 through 90.

  - `copy_code_text: optional string`

    Localized fallback copy-button label, maximum 25 characters.

  - `message_send_ttl_seconds: optional number`

    Stop attempting delivery after this many seconds. Authentication templates accept 30 through 900.

  - `package_name: optional string`

    Android application package name. Required for `one_tap` and `zero_tap`; omit for `copy_code`.

  - `signature_hash: optional string`

    Android app signing-key hash. Required for `one_tap` and `zero_tap`; omit for `copy_code`.

  - `zero_tap_terms_accepted: optional boolean`

    Must be true for `zero_tap`; omit for the other subtypes.

- `body: optional object { text, examples }`

  The ordinary authoring body. Required unless `authentication` is supplied; specialized authentication templates omit it because their localized body is fixed.

  - `text: string`

    The message copy. Use `{{name}}` for each variable — lowercase letters,
    digits and underscores, the same names a `template` part supplies values
    for. Numbered placeholders such as `{{1}}` are refused: this API addresses
    template variables by name. At most 32 distinct placeholders may appear;
    a larger set is refused at this field.

  - `examples: optional unknown`

    One example value per variable, keyed by variable name. **Required for
    every variable the copy uses** — the channel refuses a template whose
    variables carry no examples, and reviewers read the examples to decide.
    Omit it entirely when the copy has no variables.

    Each value is 1–1024 characters, may not be whitespace-only, and may not
    contain a line break, a tab, or four consecutive spaces, because a
    parameter value carries the same published rules at send time.

- `buttons: optional array of object { text, url }`

  One or two fixed URL buttons for an ordinary template. Their non-blank labels and HTTPS destinations are baked into the reviewed template and take no send-time values.

  - `text: string`

    Visible label, maximum 25 characters.

  - `url: string`

    Fixed HTTPS destination baked into the approved template. Senders cannot replace it.

- `carousel: optional object { cards }`

  Optional media-card carousel definition. All 2–10 cards must use the same media kind, body presence, and ordered button-type sequence.

  - `cards: array of object { media, body, buttons }`

    - `media: object { asset_handle, kind }`

      - `asset_handle: string`

        The asset handle returned by the channel's template-authoring upload flow. This is neither this API's upload_ref nor an inbound media_id.

      - `kind: "image" or "video"`

        - `"image"`

        - `"video"`

    - `body: optional object { text, examples }`

      The body copy of a template, with `{{variable}}` placeholders for the parts
      that change per send.

      - `text: string`

        The message copy. Use `{{name}}` for each variable — lowercase letters,
        digits and underscores, the same names a `template` part supplies values
        for. Numbered placeholders such as `{{1}}` are refused: this API addresses
        template variables by name. At most 32 distinct placeholders may appear;
        a larger set is refused at this field.

      - `examples: optional unknown`

        One example value per variable, keyed by variable name. **Required for
        every variable the copy uses** — the channel refuses a template whose
        variables carry no examples, and reviewers read the examples to decide.
        Omit it entirely when the copy has no variables.

        Each value is 1–1024 characters, may not be whitespace-only, and may not
        contain a line break, a tab, or four consecutive spaces, because a
        parameter value carries the same published rules at send time.

    - `buttons: optional array of object { text, type, phone_number, url }`

      - `text: string`

      - `type: "quick_reply" or "phone_number" or "url"`

        - `"quick_reply"`

        - `"phone_number"`

        - `"url"`

      - `phone_number: optional string`

      - `url: optional string`

- `footer: optional string`

  An optional footer line. Takes no variables.

- `media_header: optional object { kind, upload_ref }`

  Optional image, video, or document header for an ordinary template. The referenced bytes are uploaded for template review as part of this submission. It cannot be combined with `authentication` or `carousel`.

  - `kind: "image" or "video" or "document"`

    The media shape reviewed with this template.

    - `"image"`

    - `"video"`

    - `"document"`

  - `upload_ref: string`

    A durable handle returned by `POST /v1/media` for this account and key mode. Private-beta template authoring accepts JPEG, PNG, MP4, and PDF up to 5 MiB for every kind. This is this API's conservative authoring limit. The `upload_ref` follows the media route's documented beta retention posture and is not permanent.

### Returns

- `Template object { category, created_at, language, 9 more }`

  One registered message template in any status, with the parameters it takes.

  A template is identified by its `name` and `language` together — that is the
  pair a `template` part names, and the pair this API addresses it by. There is
  no separate template id.

  - `category: string`

    `utility`, `marketing` or `authentication` — the category the channel ASSIGNED, which may not be the one that was requested: a template that reads as marketing is recategorised on review, and the category is what a send is priced at. Values grow additively.

  - `created_at: string`

  - `language: string`

    The locale this variant is written in, such as `en_US`.

  - `name: string`

    Lowercase letters, digits and underscores. Permanent once submitted.

  - `parameters: unknown`

    The variables this template takes, as a JSON Schema (2020-12) object —
    ready to hand to a model verbatim as a tool schema. Every property is a
    string and every one is required: the channel substitutes all of them.

    Each property publishes `minLength`, `maxLength` and `pattern` alongside
    its example, so a model sees the same value rules the send path enforces:
    values are 1–1024 characters, not whitespace-only, and contain no line
    break, tab or run of four spaces.

    An empty `properties` object means the template takes no variables.
    `null` means something different and specific: this template's variables
    cannot be addressed by name over this API (they are positional, or they
    live in a part of the template this API does not read yet). A `template`
    part naming such a template cannot supply its variables.

  - `quality: string`

    The channel's quality signal for this template, when it has one. `null` until it does. Free text; treat an unknown value as no signal.

  - `rejected_reason: string`

    Why the template was refused or held, when the channel said. Free text for a human; the wording is not stable and must not be branched on. `null` when there is nothing to say.

  - `send_schema: unknown`

    The complete schema for the `template` part that sends this exact template, including its fixed identity, named parameters, media header, and carousel values. `null` means this template cannot be addressed safely through this API.

  - `status: string`

    Where this template stands. Only `approved` may be sent.

    `draft` — a submission attempt has not produced a registered template.
    Consult `retry_allowed`; draft status alone never permits resubmission.
    `pending` — under review. Review is an unbounded queue; an hour or more is
    ordinary for a first submission.
    `approved` — sendable.
    `rejected` — refused; `rejected_reason` may say why.
    `paused` — was approved and is currently held, usually for quality. Not
    terminal: it can become `approved` again without you doing anything.
    `disabled` — no longer usable.

    Values grow additively, and anything you do not recognise is not sendable.

  - `updated_at: string`

  - `content: optional object { body, buttons, carousel, 2 more }`

    Human-readable copy and fixed actions in a registered template.

    - `body: optional string`

    - `buttons: optional array of object { type, phone_number, text, url }`

      - `type: string`

        The action kind; values grow additively.

      - `phone_number: optional string`

        A fixed telephone destination baked into the template, when present.

      - `text: optional string`

        The label shown to the recipient, when the channel supplies one.

      - `url: optional string`

        A fixed destination baked into the template, when present.

    - `carousel: optional array of object { body, buttons, header }`

      - `body: optional string`

      - `buttons: optional array of object { type, phone_number, text, url }`

        - `type: string`

          The action kind; values grow additively.

        - `phone_number: optional string`

          A fixed telephone destination baked into the template, when present.

        - `text: optional string`

          The label shown to the recipient, when the channel supplies one.

        - `url: optional string`

          A fixed destination baked into the template, when present.

      - `header: optional object { kind, text }`

        A media or text header as it will appear to the recipient.

        - `kind: string`

          `text`, `image`, `video`, or `document`; values grow additively.

        - `text: optional string`

          Fixed header copy. Omitted for media headers.

    - `footer: optional string`

    - `header: optional object { kind, text }`

      A media or text header as it will appear to the recipient.

      - `kind: string`

        `text`, `image`, `video`, or `document`; values grow additively.

      - `text: optional string`

        Fixed header copy. Omitted for media headers.

  - `retry_allowed: optional boolean`

    Whether another submission using this draft's name and language is currently allowed. A corrected definition may be required. Present on all responses from current servers. Clients must not offer retry unless this is explicitly `true`.

### Example

```http
curl https://whatsapp.messages.api.linqapp.com/v1/templates \
    -H 'Content-Type: application/json' \
    -H "Authorization: Bearer $LINQ_WHATSAPP_API_KEY" \
    -d '{
          "category": "category",
          "language": "language",
          "name": "name"
        }'
```

#### Response

```json
{
  "category": "category",
  "created_at": "2019-12-27T18:11:19.117Z",
  "language": "language",
  "name": "name",
  "parameters": {},
  "quality": "quality",
  "rejected_reason": "rejected_reason",
  "send_schema": {},
  "status": "status",
  "updated_at": "2019-12-27T18:11:19.117Z",
  "content": {
    "body": "body",
    "buttons": [
      {
        "type": "type",
        "phone_number": "phone_number",
        "text": "text",
        "url": "url"
      }
    ],
    "carousel": [
      {
        "body": "body",
        "buttons": [
          {
            "type": "type",
            "phone_number": "phone_number",
            "text": "text",
            "url": "url"
          }
        ],
        "header": {
          "kind": "kind",
          "text": "text"
        }
      }
    ],
    "footer": "footer",
    "header": {
      "kind": "kind",
      "text": "text"
    }
  },
  "retry_allowed": true
}
```

## List templates

**get** `/v1/templates`

Lists the templates registered for this key's account, newest first, with
the parameter schema each one takes.

This is the read a `422 outside_customer_window` points you at: outside a
customer's service window only an approved `template` part sends, and this
is where the sendable ones and their variables are. It is also the read to
hand an agent — `parameters` is a JSON Schema shaped to be used verbatim as
a tool definition.

Templates in every status are listed, including ones that are not sendable,
so a pause or a rejection is visible rather than looking like a template
that vanished. Filter on `status == "approved"` for the sendable set.

### Query Parameters

- `cursor: optional string`

  A `next_cursor` from a previous page. Omit for the first page.

- `limit: optional number`

  How many templates to return, 1–100. Defaults to 100. A value outside the range is refused rather than clamped.

### Returns

- `TemplatePage object { data, has_more, next_cursor }`

  One page of templates, newest first.

  - `data: array of Template`

    - `category: string`

      `utility`, `marketing` or `authentication` — the category the channel ASSIGNED, which may not be the one that was requested: a template that reads as marketing is recategorised on review, and the category is what a send is priced at. Values grow additively.

    - `created_at: string`

    - `language: string`

      The locale this variant is written in, such as `en_US`.

    - `name: string`

      Lowercase letters, digits and underscores. Permanent once submitted.

    - `parameters: unknown`

      The variables this template takes, as a JSON Schema (2020-12) object —
      ready to hand to a model verbatim as a tool schema. Every property is a
      string and every one is required: the channel substitutes all of them.

      Each property publishes `minLength`, `maxLength` and `pattern` alongside
      its example, so a model sees the same value rules the send path enforces:
      values are 1–1024 characters, not whitespace-only, and contain no line
      break, tab or run of four spaces.

      An empty `properties` object means the template takes no variables.
      `null` means something different and specific: this template's variables
      cannot be addressed by name over this API (they are positional, or they
      live in a part of the template this API does not read yet). A `template`
      part naming such a template cannot supply its variables.

    - `quality: string`

      The channel's quality signal for this template, when it has one. `null` until it does. Free text; treat an unknown value as no signal.

    - `rejected_reason: string`

      Why the template was refused or held, when the channel said. Free text for a human; the wording is not stable and must not be branched on. `null` when there is nothing to say.

    - `send_schema: unknown`

      The complete schema for the `template` part that sends this exact template, including its fixed identity, named parameters, media header, and carousel values. `null` means this template cannot be addressed safely through this API.

    - `status: string`

      Where this template stands. Only `approved` may be sent.

      `draft` — a submission attempt has not produced a registered template.
      Consult `retry_allowed`; draft status alone never permits resubmission.
      `pending` — under review. Review is an unbounded queue; an hour or more is
      ordinary for a first submission.
      `approved` — sendable.
      `rejected` — refused; `rejected_reason` may say why.
      `paused` — was approved and is currently held, usually for quality. Not
      terminal: it can become `approved` again without you doing anything.
      `disabled` — no longer usable.

      Values grow additively, and anything you do not recognise is not sendable.

    - `updated_at: string`

    - `content: optional object { body, buttons, carousel, 2 more }`

      Human-readable copy and fixed actions in a registered template.

      - `body: optional string`

      - `buttons: optional array of object { type, phone_number, text, url }`

        - `type: string`

          The action kind; values grow additively.

        - `phone_number: optional string`

          A fixed telephone destination baked into the template, when present.

        - `text: optional string`

          The label shown to the recipient, when the channel supplies one.

        - `url: optional string`

          A fixed destination baked into the template, when present.

      - `carousel: optional array of object { body, buttons, header }`

        - `body: optional string`

        - `buttons: optional array of object { type, phone_number, text, url }`

          - `type: string`

            The action kind; values grow additively.

          - `phone_number: optional string`

            A fixed telephone destination baked into the template, when present.

          - `text: optional string`

            The label shown to the recipient, when the channel supplies one.

          - `url: optional string`

            A fixed destination baked into the template, when present.

        - `header: optional object { kind, text }`

          A media or text header as it will appear to the recipient.

          - `kind: string`

            `text`, `image`, `video`, or `document`; values grow additively.

          - `text: optional string`

            Fixed header copy. Omitted for media headers.

      - `footer: optional string`

      - `header: optional object { kind, text }`

        A media or text header as it will appear to the recipient.

        - `kind: string`

          `text`, `image`, `video`, or `document`; values grow additively.

        - `text: optional string`

          Fixed header copy. Omitted for media headers.

    - `retry_allowed: optional boolean`

      Whether another submission using this draft's name and language is currently allowed. A corrected definition may be required. Present on all responses from current servers. Clients must not offer retry unless this is explicitly `true`.

  - `has_more: boolean`

    True when another page follows.

  - `next_cursor: optional string`

    Pass as `cursor` to read the next page. Present only when `has_more` is true.

### Example

```http
curl https://whatsapp.messages.api.linqapp.com/v1/templates \
    -H "Authorization: Bearer $LINQ_WHATSAPP_API_KEY"
```

#### Response

```json
{
  "data": [
    {
      "category": "category",
      "created_at": "2019-12-27T18:11:19.117Z",
      "language": "language",
      "name": "name",
      "parameters": {},
      "quality": "quality",
      "rejected_reason": "rejected_reason",
      "send_schema": {},
      "status": "status",
      "updated_at": "2019-12-27T18:11:19.117Z",
      "content": {
        "body": "body",
        "buttons": [
          {
            "type": "type",
            "phone_number": "phone_number",
            "text": "text",
            "url": "url"
          }
        ],
        "carousel": [
          {
            "body": "body",
            "buttons": [
              {
                "type": "type",
                "phone_number": "phone_number",
                "text": "text",
                "url": "url"
              }
            ],
            "header": {
              "kind": "kind",
              "text": "text"
            }
          }
        ],
        "footer": "footer",
        "header": {
          "kind": "kind",
          "text": "text"
        }
      },
      "retry_allowed": true
    }
  ],
  "has_more": true,
  "next_cursor": "next_cursor"
}
```

## Domain Types

### Template

- `Template object { category, created_at, language, 9 more }`

  One registered message template in any status, with the parameters it takes.

  A template is identified by its `name` and `language` together — that is the
  pair a `template` part names, and the pair this API addresses it by. There is
  no separate template id.

  - `category: string`

    `utility`, `marketing` or `authentication` — the category the channel ASSIGNED, which may not be the one that was requested: a template that reads as marketing is recategorised on review, and the category is what a send is priced at. Values grow additively.

  - `created_at: string`

  - `language: string`

    The locale this variant is written in, such as `en_US`.

  - `name: string`

    Lowercase letters, digits and underscores. Permanent once submitted.

  - `parameters: unknown`

    The variables this template takes, as a JSON Schema (2020-12) object —
    ready to hand to a model verbatim as a tool schema. Every property is a
    string and every one is required: the channel substitutes all of them.

    Each property publishes `minLength`, `maxLength` and `pattern` alongside
    its example, so a model sees the same value rules the send path enforces:
    values are 1–1024 characters, not whitespace-only, and contain no line
    break, tab or run of four spaces.

    An empty `properties` object means the template takes no variables.
    `null` means something different and specific: this template's variables
    cannot be addressed by name over this API (they are positional, or they
    live in a part of the template this API does not read yet). A `template`
    part naming such a template cannot supply its variables.

  - `quality: string`

    The channel's quality signal for this template, when it has one. `null` until it does. Free text; treat an unknown value as no signal.

  - `rejected_reason: string`

    Why the template was refused or held, when the channel said. Free text for a human; the wording is not stable and must not be branched on. `null` when there is nothing to say.

  - `send_schema: unknown`

    The complete schema for the `template` part that sends this exact template, including its fixed identity, named parameters, media header, and carousel values. `null` means this template cannot be addressed safely through this API.

  - `status: string`

    Where this template stands. Only `approved` may be sent.

    `draft` — a submission attempt has not produced a registered template.
    Consult `retry_allowed`; draft status alone never permits resubmission.
    `pending` — under review. Review is an unbounded queue; an hour or more is
    ordinary for a first submission.
    `approved` — sendable.
    `rejected` — refused; `rejected_reason` may say why.
    `paused` — was approved and is currently held, usually for quality. Not
    terminal: it can become `approved` again without you doing anything.
    `disabled` — no longer usable.

    Values grow additively, and anything you do not recognise is not sendable.

  - `updated_at: string`

  - `content: optional object { body, buttons, carousel, 2 more }`

    Human-readable copy and fixed actions in a registered template.

    - `body: optional string`

    - `buttons: optional array of object { type, phone_number, text, url }`

      - `type: string`

        The action kind; values grow additively.

      - `phone_number: optional string`

        A fixed telephone destination baked into the template, when present.

      - `text: optional string`

        The label shown to the recipient, when the channel supplies one.

      - `url: optional string`

        A fixed destination baked into the template, when present.

    - `carousel: optional array of object { body, buttons, header }`

      - `body: optional string`

      - `buttons: optional array of object { type, phone_number, text, url }`

        - `type: string`

          The action kind; values grow additively.

        - `phone_number: optional string`

          A fixed telephone destination baked into the template, when present.

        - `text: optional string`

          The label shown to the recipient, when the channel supplies one.

        - `url: optional string`

          A fixed destination baked into the template, when present.

      - `header: optional object { kind, text }`

        A media or text header as it will appear to the recipient.

        - `kind: string`

          `text`, `image`, `video`, or `document`; values grow additively.

        - `text: optional string`

          Fixed header copy. Omitted for media headers.

    - `footer: optional string`

    - `header: optional object { kind, text }`

      A media or text header as it will appear to the recipient.

      - `kind: string`

        `text`, `image`, `video`, or `document`; values grow additively.

      - `text: optional string`

        Fixed header copy. Omitted for media headers.

  - `retry_allowed: optional boolean`

    Whether another submission using this draft's name and language is currently allowed. A corrected definition may be required. Present on all responses from current servers. Clients must not offer retry unless this is explicitly `true`.

### Template Page

- `TemplatePage object { data, has_more, next_cursor }`

  One page of templates, newest first.

  - `data: array of Template`

    - `category: string`

      `utility`, `marketing` or `authentication` — the category the channel ASSIGNED, which may not be the one that was requested: a template that reads as marketing is recategorised on review, and the category is what a send is priced at. Values grow additively.

    - `created_at: string`

    - `language: string`

      The locale this variant is written in, such as `en_US`.

    - `name: string`

      Lowercase letters, digits and underscores. Permanent once submitted.

    - `parameters: unknown`

      The variables this template takes, as a JSON Schema (2020-12) object —
      ready to hand to a model verbatim as a tool schema. Every property is a
      string and every one is required: the channel substitutes all of them.

      Each property publishes `minLength`, `maxLength` and `pattern` alongside
      its example, so a model sees the same value rules the send path enforces:
      values are 1–1024 characters, not whitespace-only, and contain no line
      break, tab or run of four spaces.

      An empty `properties` object means the template takes no variables.
      `null` means something different and specific: this template's variables
      cannot be addressed by name over this API (they are positional, or they
      live in a part of the template this API does not read yet). A `template`
      part naming such a template cannot supply its variables.

    - `quality: string`

      The channel's quality signal for this template, when it has one. `null` until it does. Free text; treat an unknown value as no signal.

    - `rejected_reason: string`

      Why the template was refused or held, when the channel said. Free text for a human; the wording is not stable and must not be branched on. `null` when there is nothing to say.

    - `send_schema: unknown`

      The complete schema for the `template` part that sends this exact template, including its fixed identity, named parameters, media header, and carousel values. `null` means this template cannot be addressed safely through this API.

    - `status: string`

      Where this template stands. Only `approved` may be sent.

      `draft` — a submission attempt has not produced a registered template.
      Consult `retry_allowed`; draft status alone never permits resubmission.
      `pending` — under review. Review is an unbounded queue; an hour or more is
      ordinary for a first submission.
      `approved` — sendable.
      `rejected` — refused; `rejected_reason` may say why.
      `paused` — was approved and is currently held, usually for quality. Not
      terminal: it can become `approved` again without you doing anything.
      `disabled` — no longer usable.

      Values grow additively, and anything you do not recognise is not sendable.

    - `updated_at: string`

    - `content: optional object { body, buttons, carousel, 2 more }`

      Human-readable copy and fixed actions in a registered template.

      - `body: optional string`

      - `buttons: optional array of object { type, phone_number, text, url }`

        - `type: string`

          The action kind; values grow additively.

        - `phone_number: optional string`

          A fixed telephone destination baked into the template, when present.

        - `text: optional string`

          The label shown to the recipient, when the channel supplies one.

        - `url: optional string`

          A fixed destination baked into the template, when present.

      - `carousel: optional array of object { body, buttons, header }`

        - `body: optional string`

        - `buttons: optional array of object { type, phone_number, text, url }`

          - `type: string`

            The action kind; values grow additively.

          - `phone_number: optional string`

            A fixed telephone destination baked into the template, when present.

          - `text: optional string`

            The label shown to the recipient, when the channel supplies one.

          - `url: optional string`

            A fixed destination baked into the template, when present.

        - `header: optional object { kind, text }`

          A media or text header as it will appear to the recipient.

          - `kind: string`

            `text`, `image`, `video`, or `document`; values grow additively.

          - `text: optional string`

            Fixed header copy. Omitted for media headers.

      - `footer: optional string`

      - `header: optional object { kind, text }`

        A media or text header as it will appear to the recipient.

        - `kind: string`

          `text`, `image`, `video`, or `document`; values grow additively.

        - `text: optional string`

          Fixed header copy. Omitted for media headers.

    - `retry_allowed: optional boolean`

      Whether another submission using this draft's name and language is currently allowed. A corrected definition may be required. Present on all responses from current servers. Clients must not offer retry unless this is explicitly `true`.

  - `has_more: boolean`

    True when another page follows.

  - `next_cursor: optional string`

    Pass as `cursor` to read the next page. Present only when `has_more` is true.
