Broadcasts API

The Broadcasts API lets you create and schedule marketing broadcasts programmatically — perfect for automating a weekly newsletter from your own pipeline. You send us tested, raw HTML with merge variables; we handle audience resolution, link and open tracking, unsubscribe compliance, and delivery pacing.

Early access. The Broadcasts API is currently in early access. It requires the Email API add-on, a verified workspace, and the early-access flag enabled for your workspace — contact support to join.

Authentication

All endpoints authenticate with your API key as a Bearer token, exactly like the Emails API. Your workspace is derived from the key — no workspace ID in the URL.

Authorization: Bearer YOUR_API_KEY

Create a broadcast

POST/v1/broadcasts

Creates a draft broadcast from raw HTML. The HTML is stored exactly as you send it; tracking links and required footers are applied when the broadcast is scheduled.

curl -X POST https://api.smashsend.com/v1/broadcasts \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Weekly newsletter #42",
    "subject": "This week: {{firstName}}, the new roadmap is live",
    "previewText": "Fresh updates from the team",
    "fromEmail": "news@yourdomain.com",
    "fromName": "Dale from Acme",
    "html": "<html><body><h1 style=\"background:#0b1f3a;color:#fff\">Hello {{firstName}}</h1><p>...</p><a href=\"{{unsubscribeUrl}}\">Unsubscribe</a></body></html>",
    "audience": { "all": true },
    "settings": { "trackOpens": true, "trackClicks": true }
  }'

Response (201): the draft broadcast plus every merge variable we detected in your HTML, subject and preview text.

{
  "broadcast": {
    "id": "cmp_a1b2c3d4e5f6g7h8i9j0k",
    "name": "Weekly newsletter #42",
    "status": "DRAFT",
    "subject": "This week: {{firstName}}, the new roadmap is live",
    "audience": { "all": true },
    "scheduledAt": null,
    "sentAt": null
  },
  "variables": {
    "detected": ["firstName", "unsubscribeUrl"],
    "unknown": []
  }
}

Raw HTML rules

Unsubscribe link is mandatory. If your HTML references {{unsubscribeUrl}} we leave your design untouched. If it doesn't, we append a standard unsubscribe footer — every marketing email must let recipients opt out. One-click unsubscribe headers are always added at the message level.

Link tracking. When trackClicks is on (default), every http(s) link is rewritten through your tracking domain at schedule time. mailto:, tel: and anchor links are never rewritten, and neither is the unsubscribe link.

Plain text. If you don't provide a text version we generate one from your HTML.

Size limit. The HTML body can be up to 500 KB. For best deliverability keep it under 102 KB (Gmail clips larger messages).

Merge variables

Use {{variableName}} anywhere in the HTML, subject or preview text. Variables resolve per recipient from their contact properties — built-ins like {{firstName}}, {{lastName}} and {{email}}, any custom property by its API slug, plus system URLs: {{unsubscribeUrl}}, {{manageUrl}} (manage preferences) and {{contactId}}.

Unknown variables are rejected by default. A variable that doesn't exist as a contact property renders as empty text in the recipient's inbox ("Hi ,"), so the create request fails with broadcast_unknown_variables listing the offending names. If you know what you're doing, pass "allowUnknownVariables": true.

Missing values (a contact without firstName) always render as empty text — write copy that degrades gracefully, or test with the test endpoint below.

Send a test

POST/v1/broadcasts/:broadcastId/test

Sends the broadcast to up to 10 workspace members with a [TEST] subject prefix. Merge variables are rendered so the email looks exactly like the real send. Always test before scheduling.

curl -X POST https://api.smashsend.com/v1/broadcasts/cmp_a1b2.../test \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "emails": ["you@yourdomain.com"] }'

Schedule (or send now)

POST/v1/broadcasts/:broadcastId/schedule

Locks the content, resolves the audience and queues the send. Omit sendAt to send immediately, or pass an ISO timestamp up to 90 days out. deliveryMethod controls pacing: ASAP, PROGRESSIVE, SMART (contact-timezone aware) or WARMUP. If your sending account is new we enforce WARMUP automatically — omit deliveryMethod and we always pick the safest available option.

curl -X POST https://api.smashsend.com/v1/broadcasts/cmp_a1b2.../schedule \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "sendAt": "2026-07-08T15:00:00Z" }'

Scheduled broadcasts can be stopped with POST /v1/broadcasts/:broadcastId/cancel any time before sending starts (the broadcast returns to draft).

Read broadcasts

GET/v1/broadcasts

Lists broadcasts (cursor-paginated, filter with ?status=DRAFT). Fetch one with GET /v1/broadcasts/:broadcastId — poll status to follow the lifecycle: DRAFT → SCHEDULED → IN_PROGRESS → COMPLETED.

Full example: automated weekly newsletter (Python)

import requests

API = "https://api.smashsend.com"
HEADERS = {"Authorization": "Bearer YOUR_API_KEY"}

# 1. Create the draft from your generated, client-safe HTML
create = requests.post(f"{API}/v1/broadcasts", headers=HEADERS, json={
    "name": "Weekly newsletter",
    "subject": "{{firstName}}, this week's update",
    "fromEmail": "news@yourdomain.com",
    "fromName": "Dale from Acme",
    "html": open("newsletter.html").read(),
    "audience": {"all": True},
}).json()

broadcast_id = create["broadcast"]["id"]
assert not create["variables"]["unknown"], create["variables"]

# 2. Send yourself a test
requests.post(f"{API}/v1/broadcasts/{broadcast_id}/test",
              headers=HEADERS, json={"emails": ["you@yourdomain.com"]})

# 3. Schedule for tomorrow 9am UTC (after you've checked the test!)
requests.post(f"{API}/v1/broadcasts/{broadcast_id}/schedule",
              headers=HEADERS, json={"sendAt": "2026-07-08T09:00:00Z"})

Errors

broadcast_api_not_enabled (403) — your workspace isn't in the early-access program yet.
broadcast_api_addon_required (402) — enable the Email API add-on in billing settings.
broadcast_api_workspace_not_verified (403) — your workspace must be verified before sending.
broadcast_unknown_variables (400) — fix the listed variables or pass allowUnknownVariables.
campaigns/invalid_from_email (400) — the from address isn't verified; the response lists your allowed emails and domains.
campaigns/delivery_method_not_available (400) — usually means WARMUP is required for a new sending account.