# Templates with the API

> Create message templates and send them to WhatsApp for review, follow their status, edit and delete them with an Avox API key.

Source: https://docs.theavoxai.com/avox-api/templates

Write [message templates](https://docs.theavoxai.com/templates) from your own code or an AI assistant and send them to
WhatsApp for review, exactly as the dashboard does: the same checks, the same name and language
rules, the same plan limit. Needs `templates:read` / `templates:write` (deleting also needs
**Delete templates** for the person who set the key's permissions). Basics:
[Builder API quick start](https://docs.theavoxai.com/avox-api/builder). To send a template, use
[`POST /api/messages/send`](https://docs.theavoxai.com/avox-api/messages#template) with the `send` scope.

The JavaScript examples use the `avox()` helper from [Builder API reference](https://docs.theavoxai.com/avox-api/reference).

## Review status

Every new or edited template goes to WhatsApp for review. `status` is `PENDING` until WhatsApp
decides, then `APPROVED` or `REJECTED` (with `rejectedReason`); WhatsApp can later set `PAUSED`
or `DISABLED`. Only approved templates can be sent or used by an automation that's switched on.
Reviews usually take minutes and can take up to a day: check `GET /api/v1/templates/{templateId}`
no more than once a minute.

A template's fields: `id`, `metaTemplateId`, `name`, `language`, `category` (`MARKETING`,
`UTILITY`, `AUTHENTICATION`), `status`, `rejectedReason`, `qualityScore`, `components` (WhatsApp's
header, body, footer and buttons), `source`, `libraryId`, `lastEditedAt`, `syncedAt`, `etag`.

### GET /api/v1/templates

Query: `status` (`APPROVED`, `PENDING`, `REJECTED`, `PAUSED`, `DISABLED`...), `language`,
`limit` (1 to 100), `cursor`.

**curl**

```bash
curl "https://api.avox.com/api/v1/templates?status=APPROVED" -H "Authorization: Bearer $AVOX_API_KEY"
```

**JavaScript**

```js
const { data } = await avox("/templates?status=APPROVED");
```

### POST /api/v1/templates

Creates a template and sends it for review. Counts against your plan's templates; send an
`Idempotency-Key`. Three ways:

**An Avox library template** (ids in `GET /api/v1/catalog`, written and checked by Avox in
several languages): `libraryId`, and optionally `name` (default: the library id), `language`
(one of its `languages`). A template whose header is an image, video or document needs a sample
file uploaded in the dashboard's template wizard. A template with a sample link answers with a
`sample_link` warning: replace the link with yours (edit it, or write your own).

**Your own content:** `kind: "custom"`, `name` (small letters, numbers and `_`), `language` (like
`en_US`), `category` (`MARKETING` or `UTILITY`), `bodyText` (up to 1,024 characters, variables
`{{1}}`, `{{2}}`... in order), `sampleValues` (one realistic example per variable: WhatsApp
needs them), and optionally `headerFormat` (`NONE` or `TEXT`) with `headerText` and
`headerSampleValue`, `footerText` (up to 60 characters), `buttons` (`QUICK_REPLY` with `text`,
`URL` with `text` and `url`, `PHONE_NUMBER` with `text` and `phone_number`). `kind: "otp"` makes an
Authentication template (WhatsApp writes its text).

**A WhatsApp library template** (from `GET /api/v1/templates/library`): `libraryTemplateName`,
`name`, `language`, and its `bodyInputs` / `buttonInputs`.

**curl**

```bash
curl -X POST https://api.avox.com/api/v1/templates \
  -H "Authorization: Bearer $AVOX_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 7c2e9b4a-1d6f-4a3e-8b5c-9e0f1a2b3c4d" \
  -d '{
    "kind": "custom",
    "name": "order_shipped",
    "language": "en_US",
    "category": "UTILITY",
    "bodyText": "Hi {{1}}, your order {{2}} is on its way. It should reach you by {{3}}.",
    "sampleValues": ["Aditi", "A-1001", "Friday"],
    "footerText": "Reply STOP to stop updates",
    "buttons": [{ "type": "QUICK_REPLY", "text": "Track my order" }]
  }'
```

**JavaScript**

```js
const { ok, data, error } = await avox("/templates", {
  method: "POST",
  headers: { "Idempotency-Key": crypto.randomUUID() },
  body: JSON.stringify({ libraryId: "booking_reminder", language: "en_US" }),
});
if (!ok && error.code === "name_taken") console.log(error.details[0].message); // includes a free name to use
```

Answers `201` with `{ template }` (status `PENDING`). A name already used in that language
answers `name_taken` with a free name in `details`; WhatsApp refusing the content answers
`meta_refused` with WhatsApp's reason when it gave one.

### GET /api/v1/templates/\{templateId\}

The template, and `editing`: whether it can be edited now (`editable`, the `reason` when not,
`categoryLocked`, `nextAllowedAt` when an approved template used its edits).

**curl**

```bash
curl https://api.avox.com/api/v1/templates/TEMPLATE_ID -H "Authorization: Bearer $AVOX_API_KEY"
```

**JavaScript**

```js
let template;
do {
  await new Promise((r) => setTimeout(r, 60_000));
  template = (await avox(`/templates/${templateId}`)).data.template;
} while (template.status === "PENDING");
```

### PATCH /api/v1/templates/\{templateId\}

Edits the text and category: `category`, `bodyText`, and optionally `headerText`,
`headerSampleValue`, `footerText`, `sampleValues`. Name, language, buttons and a media header
stay as they are. WhatsApp reviews it again (`PENDING`). WhatsApp's rules: approved templates
can be edited once every 24 hours and 10 times in 30 days, and keep their category; rejected and
paused ones any time; pending ones not at all (`template_not_editable`, or
`template_edit_limit` with `Retry-After`). An edit that changes nothing is refused. Send
`If-Match` with the template's ETag.

**curl**

```bash
curl -X PATCH https://api.avox.com/api/v1/templates/TEMPLATE_ID \
  -H "Authorization: Bearer $AVOX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "category": "UTILITY", "bodyText": "Hi {{1}}, order {{2}} has shipped and should arrive by {{3}}.", "sampleValues": ["Aditi", "A-1001", "Friday"] }'
```

**JavaScript**

```js
await avox(`/templates/${t.id}`, { method: "PATCH", headers: { "If-Match": t.etag }, body: JSON.stringify({ category: t.category, bodyText: newText, sampleValues }) });
```

### DELETE /api/v1/templates/\{templateId\}

Deletes this language of the template, at WhatsApp and in Avox. Needs **Delete templates**.
Automations that send it stop sending it; check `GET /api/v1/automations` first.

**curl**

```bash
curl -X DELETE https://api.avox.com/api/v1/templates/TEMPLATE_ID -H "Authorization: Bearer $AVOX_API_KEY"
```

**JavaScript**

```js
await avox(`/templates/${templateId}`, { method: "DELETE" });
```

### GET /api/v1/templates/library

WhatsApp's own library of pre-written Utility templates, which are usually approved quickly.
Query: `search`, `topic`, `usecase`, `industry`, `language`, `limit` (1 to 50), `cursor`.

**curl**

```bash
curl "https://api.avox.com/api/v1/templates/library?search=delivery&language=en_US" -H "Authorization: Bearer $AVOX_API_KEY"
```

**JavaScript**

```js
const { data } = await avox("/templates/library?search=payment");
```

## Errors you might see

| Code | What to do |
| --- | --- |
| [`invalid_payload`](https://docs.theavoxai.com/api/errors#invalid_payload) | Fix the fields `details` names (a missing sample value is the usual one). |
| [`name_taken`](https://docs.theavoxai.com/api/errors#name_taken) | Use the free name in `details`, or another name. |
| [`meta_refused`](https://docs.theavoxai.com/api/errors#meta_refused) | Read WhatsApp's reason and change the content. |
| [`template_not_editable`](https://docs.theavoxai.com/api/errors#template_not_editable) | Wait for the review, or create a new template. |
| [`template_edit_limit`](https://docs.theavoxai.com/api/errors#template_edit_limit) | Wait until `Retry-After`. |
| [`plan_limit_reached`](https://docs.theavoxai.com/api/errors#plan_limit_reached) | Delete a template you don't use, or move to a bigger plan. |

## Related
