Skip to content

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.

10 minutesDevelopersUpdated

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.

  • An API key that can Send messages, upload media (messages:send) and List and read templates (templates:read)
  • An approved template. 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.

List templates finds the template by name and language:

Terminal window
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:

{
"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.

Send a 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, so a retry never sends it twice:

Terminal window
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 in pending:

{
"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://…"}.

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:

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”.

Code What to do
invalid_field on template.language Send language with name.
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 on its reference page. For every code, see Handle errors and limits.

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.