# Send a template

> Send an approved WhatsApp template to one customer from your own code, with its variables filled in, and follow it until it's read.

Source: https://docs.soosh.io/guides/api/send-a-template/

A template is the only message you can send a customer who hasn't written to
you in the last 24 hours. This guide sends the `diwali_offer` template to
Priya with her name and a coupon code.

## Before you start

- [An API key](https://docs.soosh.io/guides/integrations/create-an-api-key/) that can **Send messages, upload media** (`messages:send`) and **List and read templates** (`templates:read`)
- [An approved template](https://docs.soosh.io/guides/templates/get-a-template-approved/). You can make marketing and utility templates over the API with `POST /v1/templates`; authentication templates and templates with an image, video or document header are made in the app.

The examples keep the key in `SOOSH_API_KEY` and send to
`https://app.soosh.io/v1`. Use your own Soosh address if it's different.

## 1. Look up the template's variables

[List templates](https://docs.soosh.io/reference/api/templates/list-templates/) finds the template by name and language:

```sh
curl "https://app.soosh.io/v1/templates?name=diwali_offer&language=en" \
  -H "Authorization: Bearer $SOOSH_API_KEY"
```

Its `variables` list the exact keys a send must fill in:

```json
{
  "data": [
    {
      "id": "8d2f4c1e-7a3b-4e59-b0c6-1f2e3d4c5b6a",
      "name": "diwali_offer",
      "language": "en",
      "category": "MARKETING",
      "status": "APPROVED",
      "number_id": "0f6d3c1e-5b7a-4c52-9a55-3f6a2d5c8b10",
      "parameter_format": "positional",
      "body": "Hi {{1}}, our Diwali sale is on. Use your code at checkout.",
      "buttons": [{ "type": "COPY_CODE", "text": "Copy code" }],
      "variables": { "header": [], "body": ["1"], "buttons": { "0": ["1"] } }
    }
  ],
  "next_cursor": null
}
```

(Some fields are left out here.) This one needs body variable `1` and the
code for button `0`. A template with named variables lists the names, like
`"first_name"`, instead of numbers.

## 2. Send it

[Send a message](https://docs.soosh.io/reference/api/messages/send-message/) with `type: template`. Give it by `name` and `language`
together, or by `id`, not both: sending both is `422 invalid_field`. Send an
[`Idempotency-Key`](https://docs.soosh.io/reference/api/#retrying-safely), so a retry never sends
it twice:

```sh
curl https://app.soosh.io/v1/messages \
  -H "Authorization: Bearer $SOOSH_API_KEY" \
  -H "Idempotency-Key: diwali-2026-priya" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+919876543210",
    "type": "template",
    "template": {
      "name": "diwali_offer",
      "language": "en",
      "body": { "1": "Priya" },
      "buttons": { "0": "PRIYA10" }
    }
  }'
```

`to` is the phone number with its country code. Spaces, dashes and brackets
are ignored. To send to a contact you already have, use `contact_id`
instead. A number with no contact gets one.

Soosh checks everything before it saves anything, then answers `201` with the
[Message](https://docs.soosh.io/reference/api/messages/#object) in `pending`:

```json
{
  "id": "7c678987-a6fa-4a6e-b333-c57204c43eb7",
  "contact_id": "4ea0d485-435d-407f-837a-c7d67095f23a",
  "number_id": "0f6d3c1e-5b7a-4c52-9a55-3f6a2d5c8b10",
  "direction": "outgoing",
  "type": "template",
  "status": "pending",
  "template": { "id": "8d2f4c1e-7a3b-4e59-b0c6-1f2e3d4c5b6a", "name": "diwali_offer", "language": "en" },
  "sent_by": { "type": "api_key", "id": "5e1d2c3b-4a59-4f68-8e7d-6c5b4a392817", "name": "Order system" },
  "error": null
}
```

(Some fields are left out here.)

If a template has a variable in its header, send it as
`"header": {"text": "…"}`. If it has an image, video or document header,
upload the file with `POST /v1/media` and send `"header": {"media_id": "…"}`,
or send `"header": {"url": "https://…"}`.

## 3. Follow it

The message goes to WhatsApp straight away. Its `status` moves from `pending`
to `sent`, `delivered` and `read`, or to `failed` with an `error`. Follow it
in either of these ways:

- **Webhooks:** subscribe an endpoint to
  [`message.sent`](https://docs.soosh.io/reference/api/webhook-events/message-sent/) and
  [`message.status`](https://docs.soosh.io/reference/api/webhook-events/message-status/). See
  [Verify webhooks](https://docs.soosh.io/guides/api/verify-webhooks/).
- **Asking:** `GET /v1/messages/{id}` with the `id` from step 2.

If WhatsApp doesn't confirm a message Soosh sent, it stays `pending` instead
of being sent twice. It settles when WhatsApp reports its status, or fails
after 15 minutes with "WhatsApp didn't confirm this message in time".

## If the send is refused

| Code | What to do |
|---|---|
| `invalid_field` on `template.language` | Send `language` with `name`. |
| [`template_params`](https://docs.soosh.io/reference/api/errors/#template_params) | `details.missing` and `details.unexpected` list the keys to fix. Match `variables` exactly. |
| `template_not_approved` | Wait for WhatsApp to approve it. Its `status` shows where it is. |
| `template_ambiguous` | More than one of your numbers has the template. Add `number_id`, or send `template.id`. |
| `contact_opted_out` | The contact opted out of marketing messages. Don't send them marketing templates. |
| `number_unavailable` | The sending number isn't active. Reconnect it, or send `number_id` for another one. |
| `limit_reached` | Sending to a new number needs a new contact, and your workspace is at its `contacts` limit. |

The send's own errors are listed under
[Errors](https://docs.soosh.io/reference/api/messages/send-message/#errors) on its reference page.
For every code, see [Handle errors and limits](https://docs.soosh.io/guides/api/errors-and-limits/#every-error-code).

> **Cost:** Meta charges for each template message it delivers, by the template's
> category and the customer's country, and bills you directly. See
> [How campaign pricing works](https://docs.soosh.io/concepts/how-campaign-pricing-works/).

## Result

Priya gets the Diwali offer with her name and her code, and the message shows
in her chat in the Soosh inbox, sent by your key. A template doesn't reopen a
closed chat, so high-volume sends don't fill your team's inbox. A text, media
or button message sent by a key does.

## Related

- [Send a message](https://docs.soosh.io/reference/api/messages/send-message/)
- [List templates](https://docs.soosh.io/reference/api/templates/list-templates/)
- [Errors](https://docs.soosh.io/reference/api/errors/)
- [The 24-hour window](https://docs.soosh.io/concepts/the-24-hour-window/)
- [Template categories](https://docs.soosh.io/concepts/template-categories/)
- [Marketing opt-out](https://docs.soosh.io/concepts/marketing-opt-out/)
