A draft, or — with `send: true` — a broadcast queued straight through the gate.
Body
Body| Field | Type | Description |
|---|
name | string | A label for the dashboard. Not shown to recipients. |
segment_id | string | The segment the broadcast goes to. |
from | string | Name <address> on one of your verified domains. |
subject | string | The subject line. Merge variables are allowed. |
reply_to | string[] | Where replies go. |
html | string | The HTML body. At least one of html and text before sending. |
text | string | The plain-text body. |
send | boolean | Send now (or at scheduled_at) instead of leaving a draft. Defaults to false. |
scheduled_at | string | ISO 8601, between one minute and thirty days out. Only with send: true. |
›3 more fields (preview_text, topic_id, template)
Body, less common| Field | Type | Description |
|---|
preview_text | string | The inbox preview line. |
topic_id | string | Scope the broadcast to a topic: only contacts opted in to it receive it. |
template | object | { id } of a published template to copy the content from, instead of html and text. |
curl -X POST "https://api.rasket.com/broadcasts" \
-H "Authorization: Bearer $RASKET_API_KEY" \
-H "User-Agent: acme-billing/1.0" \
-H "Content-Type: application/json" \
-d '{
"name": "September product update",
"segment_id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
"from": "Acme <news@send.acme.example>",
"subject": "What shipped in September",
"reply_to": ["hello@acme.example"],
"html": "<p>Hi {{{FIRST_NAME|there}}},</p><p>Here is what shipped in September.</p><p><a href=\"{{{UNSUBSCRIBE_URL}}}\">Unsubscribe</a></p>"
}'
const response = await fetch("https://api.rasket.com/broadcasts", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.RASKET_API_KEY}`,
"User-Agent": "acme-billing/1.0",
"Content-Type": "application/json",
},
body: JSON.stringify({
name: "September product update",
segment_id: "78261eea-8f8b-4381-83c6-79fa7120f1cf",
from: "Acme <news@send.acme.example>",
subject: "What shipped in September",
reply_to: ["hello@acme.example"],
html: "<p>Hi {{{FIRST_NAME|there}}},</p><p>Here is what shipped in September.</p><p><a href=\"{{{UNSUBSCRIBE_URL}}}\">Unsubscribe</a></p>"
}),
});
const { id } = await response.json();
import os
import requests
response = requests.post(
"https://api.rasket.com/broadcasts",
headers={
"Authorization": f"Bearer {os.environ['RASKET_API_KEY']}",
"User-Agent": "acme-billing/1.0",
},
json={
"name": "September product update",
"segment_id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
"from": "Acme <news@send.acme.example>",
"subject": "What shipped in September",
"reply_to": ["hello@acme.example"],
"html": "<p>Hi {{{FIRST_NAME|there}}},</p><p>Here is what shipped in September.</p><p><a href=\"{{{UNSUBSCRIBE_URL}}}\">Unsubscribe</a></p>"
},
)
id = response.json()["id"]
Response 201
{
"object": "broadcast",
"id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17"
}
from and subject are required; everything else can wait for an update. Sending needs a segment and a body.- Bodies may carry
{{{KEY}}} or {{{KEY|default}}} over FIRST_NAME, LAST_NAME, EMAIL, every contact property key, UNSUBSCRIBE_URL and PREFERENCES_URL, rendered per recipient. - A body with neither
{{{UNSUBSCRIBE_URL}}} nor {{{PREFERENCES_URL}}} gets a footer with an unsubscribe link and your postal address appended, so no broadcast leaves without one. - With
send: true, a gate refusal creates nothing.
Every broadcast, newest first.
Query parameters
Query parameters| Field | Type | Description |
|---|
limit | integer | How many items to return, 1–100. Defaults to 20. |
after | string | Return the page that follows this item ID. Mutually exclusive with before. |
before | string | Return the page that precedes this item ID. Mutually exclusive with after. |
curl -X GET "https://api.rasket.com/broadcasts" \
-H "Authorization: Bearer $RASKET_API_KEY" \
-H "User-Agent: acme-billing/1.0"
const response = await fetch("https://api.rasket.com/broadcasts", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.RASKET_API_KEY}`,
"User-Agent": "acme-billing/1.0",
},
});
const data = await response.json();
import os
import requests
response = requests.get(
"https://api.rasket.com/broadcasts",
headers={
"Authorization": f"Bearer {os.environ['RASKET_API_KEY']}",
"User-Agent": "acme-billing/1.0",
},
)
print(response.json())
Response 200
{
"object": "list",
"has_more": false,
"data": [
{
"id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17",
"name": "September product update",
"segment_id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
"status": "sent",
"created_at": "2026-09-08T22:22:17.595Z",
"sent_at": "2026-09-09T09:00:04.118Z"
}
]
}
scheduled_at and sent_at are absent until they are set, never null. Deleted drafts are not listed.
One broadcast, with its content and status.
Path parameters
Path parameters| Field | Type | Description |
|---|
id* | string | The broadcast's ID. |
curl -X GET "https://api.rasket.com/broadcasts/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17" \
-H "Authorization: Bearer $RASKET_API_KEY" \
-H "User-Agent: acme-billing/1.0"
const response = await fetch("https://api.rasket.com/broadcasts/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.RASKET_API_KEY}`,
"User-Agent": "acme-billing/1.0",
},
});
const { id } = await response.json();
import os
import requests
response = requests.get(
"https://api.rasket.com/broadcasts/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17",
headers={
"Authorization": f"Bearer {os.environ['RASKET_API_KEY']}",
"User-Agent": "acme-billing/1.0",
},
)
id = response.json()["id"]
Response 200
{
"object": "broadcast",
"id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17",
"name": "September product update",
"segment_id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
"from": "Acme <news@send.acme.example>",
"subject": "What shipped in September",
"reply_to": ["hello@acme.example"],
"preview_text": "Three new features and a faster editor.",
"status": "draft",
"created_at": "2026-09-08T22:22:17.595Z",
"html": "<p>Hi {{{FIRST_NAME|there}}},</p><p>Here is what shipped in September.</p><p><a href=\"{{{UNSUBSCRIBE_URL}}}\">Unsubscribe</a></p>",
"text": null,
"topic_id": null
}
status is one of draft, scheduled, queued, sending, sent, canceled or failed.
Change a draft. Only the fields present are touched.
Path parameters
Path parameters| Field | Type | Description |
|---|
id* | string | The broadcast's ID. |
Body
Body| Field | Type | Description |
|---|
name | string | A label for the dashboard. Not shown to recipients. |
segment_id | string | The segment the broadcast goes to. |
from | string | Name <address> on one of your verified domains. |
subject | string | The subject line. Merge variables are allowed. |
reply_to | string[] | Where replies go. |
html | string | The HTML body. At least one of html and text before sending. |
text | string | The plain-text body. |
›2 more fields (preview_text, topic_id)
Body, less common| Field | Type | Description |
|---|
preview_text | string | The inbox preview line. |
topic_id | string | Scope the broadcast to a topic: only contacts opted in to it receive it. |
curl -X PATCH "https://api.rasket.com/broadcasts/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17" \
-H "Authorization: Bearer $RASKET_API_KEY" \
-H "User-Agent: acme-billing/1.0" \
-H "Content-Type: application/json" \
-d '{
"subject": "What shipped in September — and what is next"
}'
const response = await fetch("https://api.rasket.com/broadcasts/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17", {
method: "PATCH",
headers: {
Authorization: `Bearer ${process.env.RASKET_API_KEY}`,
"User-Agent": "acme-billing/1.0",
"Content-Type": "application/json",
},
body: JSON.stringify({
subject: "What shipped in September — and what is next"
}),
});
const { id } = await response.json();
import os
import requests
response = requests.patch(
"https://api.rasket.com/broadcasts/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17",
headers={
"Authorization": f"Bearer {os.environ['RASKET_API_KEY']}",
"User-Agent": "acme-billing/1.0",
},
json={
"subject": "What shipped in September — and what is next"
},
)
id = response.json()["id"]
Response 200
{
"object": "broadcast",
"id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17"
}
- A broadcast past
draft is 400 validation_error; cancel it first if it has not started sending.
Remove a draft.
Path parameters
Path parameters| Field | Type | Description |
|---|
id* | string | The broadcast's ID. |
curl -X DELETE "https://api.rasket.com/broadcasts/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17" \
-H "Authorization: Bearer $RASKET_API_KEY" \
-H "User-Agent: acme-billing/1.0"
const response = await fetch("https://api.rasket.com/broadcasts/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17", {
method: "DELETE",
headers: {
Authorization: `Bearer ${process.env.RASKET_API_KEY}`,
"User-Agent": "acme-billing/1.0",
},
});
const { id } = await response.json();
import os
import requests
response = requests.delete(
"https://api.rasket.com/broadcasts/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17",
headers={
"Authorization": f"Bearer {os.environ['RASKET_API_KEY']}",
"User-Agent": "acme-billing/1.0",
},
)
id = response.json()["id"]
Response 200
{
"object": "broadcast",
"id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17",
"deleted": true
}
- Drafts only. A broadcast that was sent keeps its report; one that was scheduled must be canceled instead.
Queue a draft now, or schedule it.
Path parameters
Path parameters| Field | Type | Description |
|---|
id* | string | The broadcast's ID. |
Body
Body| Field | Type | Description |
|---|
scheduled_at | string | ISO 8601, between one minute and thirty days out. Omit it to send now. |
curl -X POST "https://api.rasket.com/broadcasts/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17/send" \
-H "Authorization: Bearer $RASKET_API_KEY" \
-H "User-Agent: acme-billing/1.0" \
-H "Content-Type: application/json" \
-d '{
"scheduled_at": "2026-09-12T09:00:00Z"
}'
const response = await fetch("https://api.rasket.com/broadcasts/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17/send", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.RASKET_API_KEY}`,
"User-Agent": "acme-billing/1.0",
"Content-Type": "application/json",
},
body: JSON.stringify({
scheduled_at: "2026-09-12T09:00:00Z"
}),
});
const { id } = await response.json();
import os
import requests
response = requests.post(
"https://api.rasket.com/broadcasts/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17/send",
headers={
"Authorization": f"Bearer {os.environ['RASKET_API_KEY']}",
"User-Agent": "acme-billing/1.0",
},
json={
"scheduled_at": "2026-09-12T09:00:00Z"
},
)
id = response.json()["id"]
Response 200
{
"id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17"
}
- The gate refuses with
422 unless: from is on a domain verified for sending; the team has a postal address (Settings → Sender); the segment resolves; and the broadcast has a body. A team that cannot send is 403. - Recipients are the segment's members, minus anyone globally unsubscribed, opted out of the broadcast's topic, suppressed or deleted. Each is an ordinary send with
email.* events of its own. - The response is
{ id } alone, as the reference document has it.
Stop a scheduled or queued broadcast.
Path parameters
Path parameters| Field | Type | Description |
|---|
id* | string | The broadcast's ID. |
curl -X POST "https://api.rasket.com/broadcasts/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17/cancel" \
-H "Authorization: Bearer $RASKET_API_KEY" \
-H "User-Agent: acme-billing/1.0"
const response = await fetch("https://api.rasket.com/broadcasts/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17/cancel", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.RASKET_API_KEY}`,
"User-Agent": "acme-billing/1.0",
},
});
const { id } = await response.json();
import os
import requests
response = requests.post(
"https://api.rasket.com/broadcasts/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17/cancel",
headers={
"Authorization": f"Bearer {os.environ['RASKET_API_KEY']}",
"User-Agent": "acme-billing/1.0",
},
)
id = response.json()["id"]
Response 200
{
"object": "broadcast",
"id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17"
}
- A broadcast mid-send stops at its next page of five hundred recipients; sends already created go out. Only
scheduled and queued (or sending) broadcasts can be canceled.
Who was sent, delivered, opened, clicked, bounced, complained, unsubscribed or skipped.
Path parameters
Path parameters| Field | Type | Description |
|---|
id* | string | The broadcast's ID. |
Query parameters
Query parameters| Field | Type | Description |
|---|
type* | string | sent, delivered, opened, clicked, bounced, complained, unsubscribed or suppressed. |
email | string | Only recipients whose address contains this. |
bounce_type | string | permanent, transient or undetermined. Only with type=bounced. |
limit | integer | How many items to return, 1–100. Defaults to 20. |
after | string | Return the page that follows this item ID. Mutually exclusive with before. |
before | string | Return the page that precedes this item ID. Mutually exclusive with after. |
curl -X GET "https://api.rasket.com/broadcasts/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17/recipients?type=clicked&limit=20" \
-H "Authorization: Bearer $RASKET_API_KEY" \
-H "User-Agent: acme-billing/1.0"
const response = await fetch("https://api.rasket.com/broadcasts/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17/recipients?type=clicked&limit=20", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.RASKET_API_KEY}`,
"User-Agent": "acme-billing/1.0",
},
});
const data = await response.json();
import os
import requests
response = requests.get(
"https://api.rasket.com/broadcasts/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17/recipients?type=clicked&limit=20",
headers={
"Authorization": f"Bearer {os.environ['RASKET_API_KEY']}",
"User-Agent": "acme-billing/1.0",
},
)
print(response.json())
Response 200
{
"object": "list",
"has_more": false,
"data": [
{
"id": "cur_01k4xq8p9m",
"contact_id": "e169aa45-1ecf-4183-9955-b1499d5701d3",
"email": "ronald.williams@example.com",
"count": 2,
"clicked_links": [
{
"url": "https://acme.example/changelog",
"clicks": 2
}
]
}
]
}
id is an opaque cursor for paging, not an entity id. count appears for opened and clicked, bounce_type for bounced, clicked_links for clicked.contact_id is null for a contact deleted since the send.
Every URL clicked, with total and unique clicks.
Path parameters
Path parameters| Field | Type | Description |
|---|
id* | string | The broadcast's ID. |
Query parameters
Query parameters| Field | Type | Description |
|---|
limit | integer | How many items to return, 1–100. Defaults to 20. |
after | string | Return the page that follows this item ID. Mutually exclusive with before. |
before | string | Return the page that precedes this item ID. Mutually exclusive with after. |
curl -X GET "https://api.rasket.com/broadcasts/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17/clicked-links" \
-H "Authorization: Bearer $RASKET_API_KEY" \
-H "User-Agent: acme-billing/1.0"
const response = await fetch("https://api.rasket.com/broadcasts/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17/clicked-links", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.RASKET_API_KEY}`,
"User-Agent": "acme-billing/1.0",
},
});
const data = await response.json();
import os
import requests
response = requests.get(
"https://api.rasket.com/broadcasts/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17/clicked-links",
headers={
"Authorization": f"Bearer {os.environ['RASKET_API_KEY']}",
"User-Agent": "acme-billing/1.0",
},
)
print(response.json())
Response 200
{
"object": "list",
"has_more": false,
"data": [
{
"id": "cur_01k4xq9r2d",
"url": "https://acme.example/changelog",
"clicks": 318,
"unique_clicks": 241
}
]
}
- Requires click tracking on the sending domain; without it there is nothing to count.
Every condition of the send gate, passed or not, in the order a send checks them.
Path parameters
Path parameters| Field | Type | Description |
|---|
id* | string | The broadcast's ID. |
curl -X GET "https://api.rasket.com/broadcasts/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17/checklist" \
-H "Authorization: Bearer $RASKET_API_KEY" \
-H "User-Agent: acme-billing/1.0"
const response = await fetch("https://api.rasket.com/broadcasts/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17/checklist", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.RASKET_API_KEY}`,
"User-Agent": "acme-billing/1.0",
},
});
const data = await response.json();
import os
import requests
response = requests.get(
"https://api.rasket.com/broadcasts/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17/checklist",
headers={
"Authorization": f"Bearer {os.environ['RASKET_API_KEY']}",
"User-Agent": "acme-billing/1.0",
},
)
print(response.json())
Response 200
{
"object": "broadcast_compliance",
"broadcast_id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17",
"sendable": false,
"conditions": [
{
"condition": "sending_domain",
"passed": true
},
{
"condition": "postal_address",
"passed": false,
"name": "validation_error",
"message": "A postal address is required before sending a broadcast."
},
{
"condition": "segment",
"passed": true
}
]
}
- A failed condition carries the
name and message a send would answer with. - It is a snapshot:
POST /broadcasts/{id}/send runs the same gate again when you call it.