Broadcasts
One campaign.Thousands of contacts.
Build the list in batches of a thousand, give every recipient variables of its own, and send on the channel that fits — or let each contact be reached the way that works for them. The cost is reserved before the first message leaves, and the run is readable while it happens.
Channels a broadcast can take
Six values, and no others. smart decides per contact, which is why it is held to the same verification bar as SMS and email — it can route to either.
What gates a send
Drafting is free. Sending is not.
Verification gates the send, never the draft. Pick a channel and read exactly what it asks of you, what reads the content, and what a blocked send returns.
Both. Identity (KYC) and business (KYB) verification, and clearing one is not enough. smart is not exempt: it can route a contact to SMS or to email, so it answers to the same bar as those.
Automated content review first, then a person clears it before anything is sent.
403 kyc_required or 403 kyb_required, naming whichever one is still outstanding.
None of this touches a draft. Create the broadcast, add every recipient, rewrite the copy — no verification, no charge. The checks run at the send.
The state machine
Twelve states. Walk them.
Every status a broadcast can report, and every move between them. Click a status to read it; press a transition to take it.
Draft
Created, not submitted. It costs nothing, asks for no verification, and can be edited and refilled for as long as you want.
What it accepts
- PATCH /v1/broadcasts/{id} — rewrite the copy
- POST /v1/broadcasts/{id}/contacts — add up to 1,000 recipients per call
- DELETE /v1/broadcasts/{id} — throw it away
- POST /v1/broadcasts/{id}/send — submit it
Every move above fires the broadcast.status_changed webhook, so none of it has to be polled to be noticed.
One campaign, one message each
Every recipient carries its own variables.
A batch is a list of recipients, each with a templateVariables object of its own. Edit the body or any row and watch what that person actually receives — and what the endpoint would answer.
added
+14155551234
Hi John, order ORD-001 shipped today.
added
+5491133445566
Hi Lucía, order ORD-002 shipped today.
added
mara@example.com
Hi Mara, order ORD-003 shipped today.
3
added
0
duplicates
0
invalid
Up to 1,000 recipients per request, called as many times as the list needs. Duplicates and invalid entries come back counted, with a reason each, rather than dropped in silence. WhatsApp templates take two more objects per recipient: templateButtonVariables, keyed by button index, and templateHeaderVariables, keyed by 1.
While it runs
Counts, cost and a finish time.
One call answers with the whole picture. Drag the run forward, or cancel it mid-flight and watch what becomes of the recipients that had not left yet.
48%
percentComplete
5,000 recipients
startedAt 10:30 · eta 10:45
2,500
pending
100
sending
2,352
delivered
48
failed
0
skipped
$75.00
estimatedCost
$75.00
reservedAmount
$35.28
actualCost
The estimated cost is reserved from your balance when the send starts, so a run cannot get halfway through and run out of money. actualCost accrues on what was delivered, and the difference goes back.
Four calls
Broadcasts are in the SDK.
Create it, fill it, send it, watch it. Real methods in TypeScript and Python, and the same four steps over plain HTTP.
import Zavudev from '@zavudev/sdk';
const zavu = new Zavudev({ apiKey: process.env['ZAVUDEV_API_KEY'] });
// channel: smart | sms | sms_oneway | whatsapp | telegram | email
const broadcast = await zavu.broadcasts.create({
name: 'October update',
channel: 'smart',
text: 'Hi {{name}}, order {{order_id}} shipped today.',
});
console.log(broadcast.id, broadcast.status); // -> "draft"Write it once. Reach all of them.
Start free, no card. Drafts cost nothing — verification is only asked for at the send, and never on WhatsApp.