Broadcasts API
Send one-to-many campaigns to subscribed contacts using the same queue, suppression list, and delivery events as regular email sends.
How Broadcasts Work
A broadcast starts as a draft. When you send or schedule it, SMTPfast snapshots your selected audience, skips unsubscribed and suppressed addresses, creates one email per recipient, and queues each message for delivery.
Broadcasts are meant for marketing and product updates. They must include an unsubscribe token before they can send.
Audiences can be all subscribed contacts or one manual contact segment. Monthly broadcast limits are tied to your package: Free includes 2, Starter includes 10, Growth includes 50, and Scale includes 200.
{{unsubscribe_url}} or {{{RESEND_UNSUBSCRIBE_URL}}} in the markdown, HTML, or text body.Personalization
Tokens are resolved for each recipient at send time. Add a fallback after a pipe when a value may be blank.
# Hi {{contact.first_name|there}},
Your workspace is ready.
You are receiving this at {{contact.email}}.
Unsubscribe: {{unsubscribe_url}}How fast a broadcast goes out
When you send, SMTPfast prepares the recipients in the background and queues one email per contact. The queue sends up to about 14 emails a second, shared by all accounts, so a broadcast to 2,000 contacts usually goes out within a few minutes. The broadcast page shows the progress.
A new account sends in stages for its first week, which protects your domain's reputation and ours. A send larger than the stage allows is refused with a 429 that names the stage; scheduled sends count in the hour they go out.
| Account age | Recipients per send | Per hour | Per day |
|---|---|---|---|
| First hour | 100 | 100 | 200 |
| First day | 500 | 250 | 1,000 |
| First week | 2,000 | 1,000 | 3,000 |
To spread a large audience instead of sending it all at once, set send_over_minutes on the broadcast or on the send (in the dashboard: Delivery, on the review step). Recipients then go out evenly over that window from the send time, or from scheduled_at: recipient i of N goes out at start + i × window / N. Use 0 to send all at once, or 15 to 4320 minutes (72 hours). The window must end within 30 days.
If sending falls more than a minute behind that plan (for example during an outage on our side), the recipients still waiting are spread again evenly over the time left in the window, so they do not all go out at once when sending resumes. If the window is already over, the rest goes out at the normal broadcast send rate. The scheduled_at of each waiting email moves with it.
A spread send is counted in the hours it lands in, so it can fit the hourly limit above: in the first week, 2,000 recipients over 4 hours is 500 an hour and is accepted, while the same send all at once is refused. The daily limit still counts the whole send. Each hour of the window must also fit what else you have scheduled in it.
While it runs, the broadcast page shows how many have gone out. Canceling the broadcast stops every recipient that has not gone out yet and refunds them.
Broadcast Object
{
"object": "broadcast",
"id": "clx_broadcast123",
"name": "May product update",
"audience": "segment",
"audience_meta": { "segment_id": "seg_product" },
"from": "[email protected]",
"reply_to": null,
"subject": "New features for {{contact.first_name|there}}",
"status": "draft",
"scheduled_at": null,
"send_over_minutes": 0,
"queued_at": null,
"sent_at": null,
"recipient_count": 0,
"metrics": {
"total": 0,
"delivered": 0,
"opened": 0,
"clicked": 0,
"delivery_rate": 0,
"open_rate": 0,
"click_rate": 0
},
"created_at": "2026-05-05T12:00:00.000Z",
"updated_at": "2026-05-05T12:00:00.000Z"
}/v1/broadcastsList broadcasts in newest-updated order. Use status and q query parameters to filter the list.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| status | string | No | all, draft, scheduled, queued, sent, or canceled |
| q | string | No | Search by name, subject, or from address |
| limit | number | No | Number of broadcasts to return, up to 100 |
| page | number | No | Page number for pagination |
Response
{
"object": "list",
"data": [
{
"id": "clx_broadcast123",
"name": "May product update",
"status": "draft",
"metrics": { "total": 0, "delivered": 0 },
"created_at": "2026-05-10T09:00:00.000Z",
"updated_at": "2026-05-10T09:00:00.000Z"
}
],
"has_more": false,
"page": 1,
"page_size": 50,
"filtered_total": 1,
"total": 1,
"status_counts": { "draft": 1 }
}/v1/broadcastsCreate a draft broadcast. You can save partial drafts, target all contacts or a manual segment, then update the campaign before sending. Pass template_id to start from a template: its content fills the draft and any field you send wins.
Request Body
{
"name": "May product update",
"audience": "segment",
"segment_id": "seg_product",
"from": "[email protected]",
"subject": "New features for {{contact.first_name|there}}",
"markdown": "# Hi {{contact.first_name|there}},\n\nHere is what changed.\n\nUnsubscribe: {{unsubscribe_url}}"
}Response
{
"object": "broadcast",
"id": "clx_broadcast123",
"name": "May product update",
"status": "draft",
"created_at": "2026-05-10T09:00:00.000Z",
"updated_at": "2026-05-10T09:00:00.000Z"
}/v1/broadcasts/:idRetrieve a broadcast with rollup metrics, recent recipients, recipient events, and link click counts.
/v1/broadcasts/:idUpdate a draft or scheduled broadcast. Updating a scheduled broadcast cancels the old schedule and returns it to draft.
Request Body
{
"subject": "Updated subject",
"preview_text": "A short inbox preview"
}/v1/broadcasts/:id/testQueue a test email to one address using sample personalization data.
Request Body
{
"to": "[email protected]"
}Response
{
"object": "email",
"id": "email_abc123",
"status": "queued"
}/v1/broadcasts/:id/sendSend immediately or schedule within 30 days. The send creates a recipient snapshot from the selected audience and queues one email per eligible contact. Pass send_over_minutes to spread the recipients evenly over that window; left out, the broadcast's saved setting applies.
Request Body
{
"scheduled_at": "2026-05-12T14:00:00.000Z",
"send_over_minutes": 240
}Response
{
"object": "broadcast",
"id": "clx_broadcast123",
"name": "May product update",
"status": "scheduled",
"scheduled_at": "2026-05-12T14:00:00.000Z",
"created_at": "2026-05-10T09:00:00.000Z",
"updated_at": "2026-05-11T16:20:00.000Z",
"recipients": 1240,
"skipped": 18,
"batch_id": "batch_abc123"
}/v1/broadcasts/:id/cancelCancel a scheduled broadcast, or stop one that is sending or spread over a window. Emails that have not gone out yet are dropped and refunded; delayed queue jobs are removed where possible.
/v1/broadcasts/:idDelete a draft broadcast. Sent, queued, scheduled, and canceled broadcasts are retained for audit history.
/v1/broadcasts/:id/duplicateCopy a broadcast into a new draft. Content, sender and targeting carry over; the schedule, recipients and send history do not. Pass name for the copy, or get the original's with (copy) appended.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | No | Name for the copy |
/v1/broadcasts/:id/clicked-linksEvery link clicked in this broadcast, ordered by total clicks. clicks counts every click; unique_clicks counts distinct recipients, so one person clicking four times is four and one.
Response
{
"broadcast_id": "bc_01j9x3n8r1",
"links": [
{ "url": "https://acme.com/pricing", "clicks": 42, "unique_clicks": 31 }
],
"total_clicks": 42
}Recipients and audience preview
List who received a broadcast and what happened, and check an audience before you send.
/v1/broadcasts/{id}/recipientsRecipients for one event type, newest first. Same as Resend's List Recipients.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| type | string | No | sent, delivered, opened, clicked, bounced, complained, unsubscribed or suppressed |
| bounce_type | string | No | permanent, transient or undetermined, with type=bounced |
| string | No | Recipients whose address contains this text | |
| limit | integer | No | 1 to 100, default 20 |
| after | string | No | Cursor: the last recipient id of the previous page |
/v1/broadcasts/audienceHow many contacts a broadcast to everyone, or to one segment, would reach after unsubscribes, suppressions and invalid addresses are skipped.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| segment_id | string | No | Preview one segment |