---
url: "https://smashsend.com/docs/api/broadcasts"
title: SMASHSEND Broadcasts API Reference
domain: smashsend.com
locale: en
type: docs
words: 844
cited_by: 0
indexed_by: stealpage
---

1.  [
    
    Home
    
    ](https://smashsend.com/)

/

3.  [
    
    Docs
    
    ](https://smashsend.com/docs)

/

5.  [
    
    API Reference
    
    ](https://smashsend.com/docs/api)

/

7.  [
    
    Broadcasts
    
    ](https://smashsend.com/docs/api/broadcasts)

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.