# Broadcasts API

A one-off send: its own email, a segment, and a time. Membership is resolved when it sends, not when it's scheduled.

| Method & path                             | What it does                                                                                   |
|-------------------------------------------|-----------------------------------------------------------------------------------------------|
| `GET /api/v1/broadcasts`                  | All of them. Filter with `?status=`.                                                           |
| `POST /api/v1/broadcasts`                 | Compose one. Body: `name`, `segment_id`, `email_source`, `email_id`, `emails_per_hour`.     |
| `GET /api/v1/broadcasts/:id`              | One, with its email, segment and stats.                                                       |
| `PATCH /api/v1/broadcasts/:id`            | Update `name`, `segment_id`, `emails_per_hour`.                                             |
| `DELETE /api/v1/broadcasts/:id`           | Only a draft or a canceled one. `409` otherwise.                                             |
| `POST /api/v1/broadcasts/:id/replace_email` | Swap the email, while it's still a draft or scheduled.                                      |
| `POST /api/v1/broadcasts/:id/schedule`    | Body: `send_at`. See [scheduling](/content/docs/api/broadcasts#scheduling/index.html) for how the time is read. |
| `POST /api/v1/broadcasts/:id/unschedule`  | Back to draft, keeping its email and audience. `409` unless scheduled.                       |
| `POST /api/v1/broadcasts/:id/send_now`    | Send it. Answers with the recipient count.                                                    |
| `POST /api/v1/broadcasts/:id/cancel`      | Cancel it and everything it has queued.                                                       |

## A broadcast never shares its email

`email_source` is required and accepts only `scratch` or `copy`. `shared` is refused with `422`, on the server, rather than trusted to whichever client is asking.

```
POST /api/v1/broadcasts
{ "email_source": "copy", "email_id": 42, "segment_id": 3, "name": "July announcement" }
```

What one broadcast sent should stay what it sent. If a broadcast pointed at a shared library row, editing a sequence step months later could silently rewrite the record of a send that already went out — so every broadcast gets a row of its own, blank or copied. This is also why `emails/` in a manager repo fills up with rows that exist for one send: expected, not drift, and the [used-in filter](/content/docs/api/emails.html#used-in/index.html) is how you tell them apart.

The email can only be swapped or forked while the broadcast is still a **draft or scheduled**. Once it's sending or sent, its email is history.

## Scheduling

`send_at` takes any parseable datetime. A time **without a UTC offset** — `"2026-08-10T08:30"` — is read in the account's timezone: the profile timezone setting, Eastern Time if none is set. Include an offset (`"2026-08-10T08:30:00-04:00"`) to say exactly what you mean regardless of that setting. Responses always carry the offset. A time already in the past is refused with `422`.

`unschedule` undoes scheduling and nothing else: the broadcast goes back to draft with its email and audience intact. `cancel` is the harder stop — it moves the broadcast to canceled and kills anything already queued, which is the tool once sending has started.

## Delivery

Sending fans out through the ordinary paced queue — one queued email per recipient. Guards, send windows and tracking all apply, and every broadcast gets a full report.

The fan-out is spread across time at the broadcast's sending pace: `emails_per_hour` when the broadcast sets one, otherwise the account default (`sending.broadcast_emails_per_hour`, 5,000 by default). The pace is written into each queued row's due time at send time, so the queue shows the real schedule — 20,000 recipients at 5,000/hour is four hours of visible, cancelable rows. Set `emails_per_hour` to `null` to go back to the account default.

## Audience

Resolved at send time from the segment's live rules, not stored when you schedule. A segment that grows between now and Friday means more recipients on Friday. Unsubscribed people are excluded, and the standing suppression guard checks again for every individual send.

Broadcasts are runtime rather than authoring, so they don't appear in a [manager repo](/content/docs/reference/definitions-repo.html) — though the emails they mint do.

See also: [Emails API](/content/docs/api/emails.html) · [Segments API](/content/docs/api/segments.html) · [Broadcasts, for humans](/content/docs/usage/broadcasts.html)
