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
Section titled “Before you start”- 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.
1. Look up the template’s variables
Section titled “1. Look up the template’s variables”List templates finds the template by name and language:
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.
2. Send it
Section titled “2. Send it”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:
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://…"}.
3. Follow it
Section titled “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.sentandmessage.status. See Verify webhooks. - Asking:
GET /v1/messages/{id}with theidfrom 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
Section titled “If the send is refused”| 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.
Result
Section titled “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.