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.
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_KEYCreates 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": []
}
}• 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).
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}}.
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.
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"] }'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).
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.
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"})• 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.