Skip to main content
A broadcast sends one SMS template to a list of recipients, personalised per row, at a rate you choose. You build it in four calls - create, upload recipients, preview, launch - then watch the counters move and export the outcome per recipient. The console offers the same flow under SMS & RCS → Broadcasts.

How a broadcast runs

1

Create a draft

Name it, pick the sending number and write the template.
2

Upload recipients

A CSV, XLSX or JSON list. Extra columns become template variables.
3

Preview

See rendered samples, segment counts and any variables the file is missing.
4

Launch

Send now or at scheduledAt. Pause, resume or cancel while it runs.
5

Track and export

Per-recipient statuses, live stats, and a CSV of the results.
Launching a broadcast sends real messages to every pending recipient and bills each one per segment. Run the launch call only with your own credentials, on a list you have consent to message.

1. Create a broadcast

Create a broadcast returns a draft:
cURL
Response - 201 Created
Edit a draft with Update a broadcast (same fields, partial). Once launched, the broadcast is read-only and an edit returns 409 {"error":"cannot edit a broadcast that is running"}.

2. Upload recipients

Upload recipients replaces the draft’s recipient list. Two body formats are accepted.
Send multipart/form-data with a file field (.csv or .xlsx, up to 10 MB) and an optional defaultCountry:
cURL
recipients.csv
  • The phone column is detected by header (phone, mobile, msisdn, number, to, phonenumber and similar). Without a match the first column is used.
  • A file with no header row gets columns named phone, column2, column3, …
  • The delimiter (,, ; or tab) is sniffed. For XLSX the first sheet is read.
  • Every other column becomes a template variable with the header as its name.
defaultCountry (default US) is the ISO 3166-1 alpha-2 country used to turn national-format numbers into E.164. Numbers that already start with + are kept as they are.
US, CA, GB, IN, AU, NZ, IE, DE, FR, ES, IT, NL, BE, CH, AT, SE, NO, DK, FI, PL, PT, BR, MX, AR, CO, CL, SG, MY, ID, PH, TH, VN, JP, KR, CN, HK, AE, SA, QA, IL, TR, ZA, NG, KE, EG, PK, BD, LK, NP. Any other value returns 400 {"error":"defaultCountry must be a supported ISO 3166-1 alpha-2 code"}.
The response summarises what was accepted:
Response - 200 OK
Limits and errors: up to 10,000 recipients per broadcast (422 too many recipients: the limit is 10000 per broadcast), files over 10 MB return 413, other extensions return 400 file must be .csv or .xlsx, and uploads to a broadcast that is no longer a draft return 409.

3. Preview

Preview a broadcast renders the template against the first recipients:
cURL
Response - 200 OK
  • samples shows the rendered text, its segments and encoding (GSM-7 or UCS-2) for each of the first limit recipients (default 5, maximum 50). See segments and encoding.
  • missingVariables lists placeholders in the template that no uploaded column provides. Fix the template or re-upload before you launch.
  • estimatedSegments is the total segments across all pending recipients - multiply by your per-segment rate for the expected cost.

4. Launch

Launch a broadcast starts sending. Only a draft can be launched.
cURL
The response is the broadcast object. Its status is running when sending starts at once, or scheduled when scheduledAt is in the future - it moves to running at that time. Launch checks return 422 with one of: Each recipient is sent through the same path as Send a message with the broadcast’s tag and DLT IDs, at ratePerSecond. Every send carries an idempotency key of broadcast:<broadcastId>:<recipientId>, so a retried worker never double-sends.

Pause, resume, cancel and delete

Any other transition returns 409 {"error":"cannot <action> a broadcast that is <status>"}. An unknown or malformed id returns 404 {"error":"broadcast not found"}. The worker moves a running broadcast to completed when every recipient has been processed, or to failed if the run cannot continue. When a send is refused for insufficient balance, the broadcast is paused with pauseReason: "insufficient_balance"; top up and call resume.

Broadcast statuses

draft, scheduled, running, paused, completed, cancelled, failed.

Track recipients and stats

Get a broadcast returns fresh stats:
List recipients pages through individual rows (limit 1-500, default 50; offset) and filters by status: Each recipient carries row, to, variables (the uploaded columns), messageId, errorCode, errorMessage and sentAt. Open the message itself with Retrieve a message for its full status history.

Live updates

Connect to the WebSocket and listen for broadcast.updated. The event carries the full broadcast object with stats on every status change and roughly every 2 seconds while the broadcast is running - enough to drive a progress bar without polling.

Export the results

Export a broadcast streams a CSV (text/csv, Content-Disposition: attachment; filename="broadcast-<id>.csv"):
cURL
Columns: row, to, status, message_id, error_code, error_message, sent_at, followed by one column per uploaded variable. Cells that begin with =, +, -, @ or a tab are prefixed with ' so spreadsheets do not treat them as formulas.

Listing broadcasts

List broadcasts returns {"broadcasts": [...], "total": n}, newest first, with limit 1-500 (default 50) and offset.

Before you go live

Compliance overview

Register before you send at volume.

Messaging numbers

Pick a registered sender for the broadcast.

Opt-outs

How opted-out numbers are excluded from every broadcast.

SMS

Segments, encoding and statuses behind each recipient.

India DLT

DLT IDs for broadcasts to Indian numbers.

WebSocket

Live broadcast.updated events.