Skip to content

Create a broadcast

Compose one message for a whole segment of your audience — or for everyone.

http
POST /v1/broadcasts

Requires 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

ParameterTypeRequiredDescription
fromstringYesThe sender address. Max 320 characters.
subjectstringYesThe subject line. Max 998 characters.
segment_idstringNoThe segment to send to. Omit it to target your whole audience.
topic_idstringNoA topic to scope the send to.
htmlstring | nullNoThe HTML body. Contact properties render here — see below.
textstring | nullNoA plain-text part. If omitted, the plain text is derived from the html at send time.
preview_textstring | nullNoInbox preview text. Max 255 characters.
reply_tostring | nullNoA reply-to address. Max 320 characters.
namestring | nullNoA friendly name for the broadcast. Defaults to Untitled broadcast. Max 160 characters.
sendbooleanNoSend (or schedule) the broadcast in the same call. Defaults to false.
scheduled_atstring | nullNoWhen 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.

Transactional email on your own domain.