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

# WhatsApp templates

> Approval status, placeholders, buttons, and importing from Meta's library.

Outside the 24-hour customer service window — which is almost always, for anything your
system initiates — WhatsApp only accepts **approved templates**. This page covers what you
need to know to build one that sends correctly.

List the templates a channel can send with
[`GET /v1/templates`](/api-reference/templates/list-approved-templates-for-a-channel).

## Status

```json theme={null}
{ "name": "ticket_resolved", "language": "ar", "status": "APPROVED", "category": "UTILITY" }
```

| Status             | Can you send it?                                           |
| ------------------ | ---------------------------------------------------------- |
| `APPROVED`         | Yes                                                        |
| `PENDING`          | No — in Meta review, usually under 24 hours                |
| `REJECTED`         | No — fix the content and resubmit, or appeal               |
| `IN_APPEAL`        | No — a rejection is being re-reviewed                      |
| `PAUSED`           | No — Meta halted delivery, usually after negative feedback |
| `DISABLED`         | No — permanently disabled by Meta                          |
| `PENDING_DELETION` | No — removed after a 24-hour grace period                  |

Status changes are not pushed to API consumers. If you create templates programmatically,
poll [`GET /v1/templates`](/api-reference/templates/list-approved-templates-for-a-channel)
rather than assuming a submission cleared review.

<Warning>
  A template is approved **per language**. `ticket_resolved` in `ar` and `ticket_resolved` in
  `en` are reviewed separately — one being live says nothing about the other. `templateLanguage`
  must match the approved language exactly.
</Warning>

## Placeholders

Placeholders in the body are numbered `{{1}}`, `{{2}}`, and so on. You fill them with
`templateParams`, **in order**:

```json theme={null}
{
  "templateName": "ticket_resolved",
  "templateLanguage": "ar",
  "templateParams": ["Ahmed", "4821"]
}
```

For a body of `مرحباً {{1}}، تم حل تذكرتك رقم {{2}}.` that sends *"مرحباً Ahmed، تم حل تذكرتك رقم 4821."*

The count must match exactly. Two placeholders and one parameter fails the send — it does
not fall back to an empty string.

<Warning>
  Write `{{1}}`, never `{{ 1 }}`. Meta approves a spaced placeholder as **literal text**, so
  the template passes review and then rejects every parameterized send with error `#132000`.
  We normalize spacing on templates created through this API, but a template created
  elsewhere can still carry the problem.
</Warning>

Only the **body** takes parameters here. A template whose header or buttons contain
variables cannot be sent through this API — rebuild it with a static header.

## Buttons

Templates can carry buttons, and the type decides whether the template stays sendable:

| Button type       | Notes                                                                       |
| ----------------- | --------------------------------------------------------------------------- |
| Quick reply       | The customer's tap arrives as a normal inbound message on the conversation. |
| URL (static)      | Fine.                                                                       |
| URL (dynamic)     | Contains a variable — **not sendable through this API**.                    |
| Call phone number | Fine.                                                                       |

Quick-reply taps come back as ordinary inbound messages, so anything already reading
[`GET /v1/conversations/{id}/messages`](/api-reference/conversations/list-messages-in-a-conversation)
picks them up with no extra work.

## Meta template library

Meta publishes pre-written, pre-approved templates for common cases — order updates,
appointment reminders, delivery notifications. Importing one is much faster than writing
your own and waiting on review.

In Linkiasoft, open the template builder and choose **Import from library**. Pick the library
template, supply the sample values it asks for, and submit. Because the copy is already
Meta-approved, these skip review entirely rather than sitting in `PENDING`.

<Warning>
  If the library template carries **URL or phone buttons**, you must supply one input per
  button, in the same order. Miss one and Meta rejects the creation with a message about
  matching the number of button inputs to the library buttons.
</Warning>

## Category

| Category         | Use for                                                                                     |
| ---------------- | ------------------------------------------------------------------------------------------- |
| `UTILITY`        | Transactional messages about something the customer did — order confirmed, ticket resolved. |
| `MARKETING`      | Promotions and re-engagement. Priced higher, and customers can opt out.                     |
| `AUTHENTICATION` | One-time passcodes.                                                                         |

Categorize honestly. Meta re-categorizes templates it judges miscategorized, and
marketing content sent as `UTILITY` risks the template being paused.

## When a send fails

Check `error_reason` on the message:

| Symptom                                        | Cause                                                                                            |
| ---------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| `#132000`                                      | Parameter count mismatch, or a `{{ 1 }}` spaced placeholder approved as literal text.            |
| Rejected on creation, mentioning button inputs | A library template with URL or phone buttons was created without one input per button, in order. |
| Template not found                             | The template exists, but not in the `templateLanguage` you asked for.                            |
| Accepted, then `failed`                        | Check `error_reason` on the message.                                                             |
| Accepted but never arrives                     | Almost always the recipient number — see [the quickstart](/quickstart).                          |
