A broadcast sends one template to many customers, each with their own
variables. It’s the API’s version of a campaign, and shows in
Campaigns in the app like any other. This guide sends the diwali_offer
template to Priya and Rahul.
Before you start
Section titled “Before you start”- An API key that can Create, cancel and resume broadcasts (
broadcasts:write) and Read broadcasts and recipients (broadcasts:read) - An approved template on the number you send from. Authentication templates can’t be broadcast.
- Room in your plan’s broadcast messages for this month
Look up the template’s variables first, as in
Send a template.
Every recipient fills in exactly those keys.
1. Choose who gets it
Section titled “1. Choose who gets it”Send exactly one of these:
recipients: a list of 1 to 10,000 phone numbers, each with its own variables. Use it when your system decides who gets the message.audience: your contacts with any of some tags, with the variables taken from each contact. Use it when Soosh already has the contacts.
Either way Soosh leaves out numbers that aren’t valid, repeats of a number
already in the list, and, for a marketing template, contacts who opted out of
marketing messages. It counts them in the broadcast’s skipped. Mexican and
Argentine mobiles count as one number however WhatsApp writes them (with or
without the 1 after 52, or the 9 after 54).
If that leaves nobody, a list is refused with 422 invalid_field. An
audience is collected after the broadcast is made, so there the broadcast
becomes failed instead, with paused_reason saying why. The same happens
when a collected audience doesn’t fit in this month’s broadcast messages.
2. Create the broadcast
Section titled “2. Create the broadcast”Create a broadcast with one of the two.
To a list
Section titled “To a list”curl https://app.soosh.io/v1/broadcasts \ -H "Authorization: Bearer $SOOSH_API_KEY" \ -H "Idempotency-Key: diwali-2026" \ -H "Content-Type: application/json" \ -d '{ "name": "Diwali offer", "template": { "name": "diwali_offer", "language": "en" }, "recipients": [ { "to": "+919876543210", "name": "Priya", "body": { "1": "Priya" }, "buttons": { "0": "PRIYA10" } }, { "to": "+919812345678", "name": "Rahul", "body": { "1": "Rahul" }, "buttons": { "0": "RAHUL10" } } ] }'If any recipient’s variables don’t match the template, nothing is saved. The
answer is one 422 template_params, and details.rows lists up to 100 bad
rows as {index, missing, unexpected}. The whole request can be at most
4 MB.
To everyone with a tag
Section titled “To everyone with a tag”curl https://app.soosh.io/v1/broadcasts \ -H "Authorization: Bearer $SOOSH_API_KEY" \ -H "Idempotency-Key: diwali-2026-vip" \ -H "Content-Type: application/json" \ -d '{ "name": "Diwali offer for VIPs", "template": { "name": "diwali_offer", "language": "en" }, "audience": { "tags": ["VIP"], "exclude_tags": ["Unsubscribed"], "body": { "1": { "from": "contact.name", "fallback": "there" } }, "buttons": { "0": { "from": "attribute:coupon", "fallback": "DIWALI10" } } } }'Each variable says where its value comes from:
from |
The value |
|---|---|
contact.name |
The contact’s name |
contact.phone |
The contact’s number, as + and digits |
attribute:<name> |
One of the contact’s attributes, like attribute:coupon |
text:<value> |
The same text for everyone, like text:Diwali |
fallback is used when a contact has no usable value. It’s required for
contact.name and attribute: sources.
The audience is the contacts that already existed when you made the broadcast, with the tags they have when Soosh collects them, a moment later. A contact added after you made the broadcast isn’t included, even if it has the tag. A contact that already existed and is tagged after you made it is included.
The broadcast comes back at once as preparing while Soosh collects the
audience. It then sends, or becomes scheduled, on its own.
3. Optional: send it later
Section titled “3. Optional: send it later”Add send_at, 5 minutes to 30 days from now, in RFC 3339:
"send_at": "2026-11-01T04:30:00Z"The broadcast is scheduled until then. Its messages count against the
month it sends in.
4. Follow it
Section titled “4. Follow it”The answer to step 2 is the broadcast. Keep its id, then follow it in
either of these ways:
- Webhooks: subscribe an endpoint to
broadcast.statusto hear of every change of status. Addmessage.statusto hear about each message. - Asking:
GET /v1/broadcasts/{id}returns itsstatus,counts(total,sent,delivered,read,failed,replied,clicked) andskipped.
To see what happened to each customer, list the recipients, for example only the failed ones:
curl "https://app.soosh.io/v1/broadcasts/$BROADCAST_ID/recipients?status=failed" \ -H "Authorization: Bearer $SOOSH_API_KEY"A broadcast ends as completed, cancelled, failed or missed. See
Campaign statuses.
5. Pause, resume or cancel
Section titled “5. Pause, resume or cancel”A broadcast pauses on its own when something stops it, and paused_reason
says why, for example “This workspace has sent its 1,000 broadcast messages for October. Campaigns can be resumed from November 1, or contact support to raise the limit.”
- Resume:
POST /v1/broadcasts/{id}/resumecarries on with apausedbroadcast. The template must still be approved, and the rest must fit in this month’s broadcast messages. - Cancel:
POST /v1/broadcasts/{id}/cancelstops it for good. Messages already being sent finish; the rest are never sent.
Limits
Section titled “Limits”| Limit | Value |
|---|---|
| Recipients in a list | 1 to 10,000 |
| Request size | 4 MB |
| Tags in an audience | 1 to 20, and up to 20 to leave out |
| Broadcasts, templates and uploads made, and usage read | 10 a minute for each workspace, together |
| Broadcast messages | Your plan’s broadcast_messages_per_month. Soosh checks before it starts, and a broadcast that reaches the limit while sending pauses. |
Broadcasts don’t count against api_messages_per_second. See
Rate limits.
Result
Section titled “Result”Priya and Rahul each get the offer with their own name and code. The broadcast shows in Campaigns in the app, made by your key, and its results update as WhatsApp reports them.