Appearance
Create a broadcast
Compose one message for a whole segment of your audience — or for everyone.
http
POST /v1/broadcastsRequires a Full access API key — a broadcast reaches your audience, so a sending key embedded in an app cannot fire one.
For the concepts behind broadcasts — segments, topics, how a send fans out — see the Broadcasts guide.
Body parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
from | string | Yes | The sender address. Max 320 characters. |
subject | string | Yes | The subject line. Max 998 characters. |
segment_id | string | No | The segment to send to. Omit it to target your whole audience. |
topic_id | string | No | A topic to scope the send to. |
html | string | null | No | The HTML body. Contact properties render here — see below. |
text | string | null | No | A plain-text part. If omitted, the plain text is derived from the html at send time. |
preview_text | string | null | No | Inbox preview text. Max 255 characters. |
reply_to | string | null | No | A reply-to address. Max 320 characters. |
name | string | null | No | A friendly name for the broadcast. Defaults to Untitled broadcast. Max 160 characters. |
send | boolean | No | Send (or schedule) the broadcast in the same call. Defaults to false. |
scheduled_at | string | null | No | When to send. Only meaningful with send: true — see Scheduling. |
Unlike Resend, segment_id is optional here. Omit it and the broadcast targets your whole audience; pass one to narrow the send to that segment.
Examples
Create a draft. It is saved but not sent — send it later with Send a broadcast.
bash
curl -X POST 'https://api.sendgrail.com/v1/broadcasts' \
-H "Authorization: Bearer $SENDGRAIL_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"name": "July product update",
"segment_id": "3f1c9a52-6d0e-4a1b-9a2f-7c4e1b0d8e33",
"from": "News <news@yourdomain.com>",
"subject": "What shipped this month",
"html": "<p>Hi {{{contact.first_name}}}, here is what is new.</p>"
}'js
const res = await fetch('https://api.sendgrail.com/v1/broadcasts', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.SENDGRAIL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'July product update',
segment_id: '3f1c9a52-6d0e-4a1b-9a2f-7c4e1b0d8e33',
from: 'News <news@yourdomain.com>',
subject: 'What shipped this month',
html: '<p>Hi {{{contact.first_name}}}, here is what is new.</p>',
}),
});
const broadcast = await res.json();Create and send immediately, in one call, by passing send: true:
bash
curl -X POST 'https://api.sendgrail.com/v1/broadcasts' \
-H "Authorization: Bearer $SENDGRAIL_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"from": "News <news@yourdomain.com>",
"subject": "What shipped this month",
"html": "<p>Hi {{{contact.first_name}}}, here is what is new.</p>",
"send": true
}'Create and schedule for later — add scheduled_at alongside send: true:
bash
curl -X POST 'https://api.sendgrail.com/v1/broadcasts' \
-H "Authorization: Bearer $SENDGRAIL_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"from": "News <news@yourdomain.com>",
"subject": "What shipped this month",
"html": "<p>Hi {{{contact.first_name}}}, here is what is new.</p>",
"send": true,
"scheduled_at": "in 1 hour"
}'Response
The create call returns the new broadcast's id only:
json
{
"id": "e4f9a2c1-7b83-4d6e-9a1f-2c5b8e0d3a47"
}Fetch the full object at any time with Retrieve a broadcast.
Contact properties render in the body
Anywhere in html or text you can drop a contact property tag, and it renders per recipient the same way it does in a template:
html
Hi {{{contact.first_name}}}, thanks for being with us.Scheduling
scheduled_at accepts either natural language — "in 1 hour", "tomorrow 9am" — or an ISO 8601 timestamp like "2026-08-05T11:52:01Z".
- It must be within 30 days. Further out is a
422 validation_error. - A time under ~30 seconds away sends immediately rather than scheduling.
scheduled_at only takes effect with send: true. On a draft (send false or omitted) it is ignored — set the time when you actually send.
Unknown segment or topic
A segment_id or topic_id that doesn't belong to your team answers 404:
json
{
"message": "No segment with the id 3f1c9a52-6d0e-4a1b-9a2f-7c4e1b0d8e33.",
"code": "not_found",
"request_id": "8f2c1e64-1b17-4f8c-9f0e-3b6c1e0f5c31"
}See Errors for the full list of codes.