Skip to content
Esc
  • OverviewGuidesWhat exists today, and where to start.
  • QuickstartGuidesKey, domain, first send — in that order.
  • AuthenticationGuidesBearer keys, the mandatory User-Agent, and what each refusal means.
  • ErrorsGuidesThe whole vocabulary, with the status each name carries.
  • IdempotencyGuidesRetry a send without sending it twice.
  • PaginationGuidesCursors are item IDs, not page numbers.
  • Rate limitsGuidesTen a second per team, and the headers that tell you where you are.
  • EventsGuidesEvery event a webhook can carry, with one real payload each.
  • DomainsGuidesThe records, where they go at each registrar, and what the page does while you wait.
  • TrackingGuidesOpens and clicks: one record, two toggles, and what an open really means.
  • ReceivingGuidesInbound mail, and the Inbox: a webhook fires, you read it, you answer it.
  • InboxGuidesChannels, personal mailboxes and seats: who sees what, and where a reply goes.
  • Node SDKGuidesThe rasket package: typed from the API's own document, retries only what is safe.
  • Python SDKGuidesThe rasket package on PyPI: the Node client's methods, in snake_case, over httpx.
  • MCP serverGuidesConnect Claude, ChatGPT or any MCP client: your scopes, no key.
  • AI assistGuidesSubject lines, drafts and diagnosis — in the dashboard and over the API, off until you allow it.
  • AgentsGuidesLet an AI agent set Rasket up: the skill, the rules file, MCP, and the recipe they share.
  • OAuthGuidesLet another app act for a team: register, authorize with PKCE, exchange, refresh.
  • Single sign-onGuidesOIDC login for your team, a domain proved by DNS, enforcement and break-glass.
  • IntegrationsGuidesVercel, Netlify and Cloudflare, plus Zapier and n8n for workflows without code.
  • SMTPGuidesSend from anything that speaks SMTP: settings, setup guides, limits and replies.
  • ZapierGuidesSend email, add contacts and react to email events from a Zap, with no code.
  • n8nGuidesThe Rasket node and trigger for n8n workflows: install, connect, every operation.
  • EmailsAPI referenceSend, batch, retrieve, list, reschedule, cancel, attachments.
  • DomainsAPI referenceAdd a domain, publish its records, verify it.
  • API keysAPI referenceCreate, list, rename and revoke credentials.
  • WebhooksAPI referencePayloads, signature verification, retries and replay.
  • SuppressionsAPI referenceAddresses we will not send to, and why.
  • LogsAPI referenceEvery request made with this team's credentials.
  • MetricsAPI referenceDelivery, bounce, complaint and engagement counts.
  • TemplatesAPI referenceVersioned email content with typed variables, addressed by ID or alias.
  • ContactsAPI referenceYour audience: contacts, their typed properties, segments and topic choices.
  • SegmentsAPI referenceAudiences defined by a filter, by hand, or both.
  • TopicsAPI referenceWhat contacts subscribe to, and the preference page's list.
  • CampaignsAPI referenceCampaigns, at /broadcasts: one message to a segment, from draft to results.
  • ImportsAPI referenceCSV uploads: column mapping, conflicts and counts.
  • AutomationsAPI referenceWorkflows that run per contact: the graph, its versions, and every run.
  • Custom eventsAPI referenceThe names your product fires, and what starts a workflow.
  • ReceivingAPI referenceMail sent to you: the message, its attachments, its raw source.
  • OAuthAPI referenceClient registration, the token endpoint, and the grants a team has given.
  • TeamAPI referenceThe team a credential belongs to: its plan, sender identity, AI flag and members.
  • BillingAPI referencePlan, usage, invoices and add-ons, and the hosted pages where a customer pays.
  • AI helpersAPI referenceSubject lines, a first draft, and why an email did what it did.

API referenceCampaigns

Campaigns

One message to a segment. The dashboard calls it a campaign; the API calls the same thing a broadcast, at /broadcasts, with the broadcasts:read and broadcasts:write scopes. A broadcast is a draft until it is sent, passes a compliance gate on the way out, and becomes one ordinary email per recipient — each with its own events.

Lifecycle

draft → scheduled or queued → sending → sent. A cancel from scheduled or queued ends in canceled; a cancel while sending stops at the next page of recipients, and the sends already created go out. Only a draft can be updated or deleted.

The gate

A send is refused — and creates nothing — unless all of these hold, checked in this order. The first three and a missing body answer 422; paused marketing mail and a team that cannot send answer 403. GET /broadcasts/{id}/checklist runs the same checks without sending.

What a broadcast needs before it is queued
NeedsMeaning
A verified sending domainfrom is on a domain of yours verified for sending.
A postal addressSet once under Settings → Sender. It goes in the footer we add to a body with no unsubscribe link.
A segmentsegment_id names a live segment.
Marketing sends switched onMarketing mail can be paused platform-wide; while it is, every campaign send is refused.
A team in good standingA team that cannot send transactional mail cannot send a campaign either.
A bodyhtml, text, or a published template.

Recipients

  • The segment's members, minus anyone globally unsubscribed, opted out of the broadcast's topic, on the suppression list, or deleted. Each exclusion is recorded with its reason.
  • There is no single results endpoint. GET /broadcasts/{id}/recipients lists who was sent, delivered, opened, clicked, bounced, complained, unsubscribed or suppressed, by type; GET /broadcasts/{id}/clicked-links counts clicks; and GET /emails/metrics with the broadcast as a filter gives the totals.
  • Every recipient is an ordinary send: it counts toward your marketing allowance (never the transactional quota), carries List-Unsubscribe headers for one-click unsubscribe, and raises the same email.* events a transactional send does.

Merge variables

Bodies and the subject may carry {{{KEY}}} or {{{KEY|default}}}. A missing value takes the inline default, then the property's fallback_value, then the empty string. Values are HTML-escaped in html and written as-is in text and subject.

Merge variables
VariableValue
FIRST_NAMEThe contact's first name.
LAST_NAMEThe contact's last name.
EMAILThe contact's address.
<PROPERTY_KEY>Any declared contact property, upper- or lower-case as declared.
UNSUBSCRIBE_URLA one-click global unsubscribe link for this recipient.
PREFERENCES_URLThe hosted preference page for this recipient.

A body with neither {{{UNSUBSCRIBE_URL}}} nor {{{PREFERENCES_URL}}} gets a plain footer appended — an unsubscribe link and your postal address — so no broadcast leaves without both.

Endpoints

Create a broadcast

POST /broadcasts

A draft, or — with `send: true` — a broadcast queued straight through the gate.

Body

  • namestring

    A label for the dashboard. Not shown to recipients.

  • segment_idstring

    The segment the broadcast goes to.

  • fromstringRequired

    Name <address> on one of your verified domains.

  • subjectstringRequired

    The subject line. Merge variables are allowed.

  • reply_tostring[]

    Where replies go.

  • htmlstring

    The HTML body. At least one of html and text before sending.

  • textstring

    The plain-text body.

  • sendboolean

    Send now (or at scheduled_at) instead of leaving a draft. Defaults to false.

  • scheduled_atstring

    ISO 8601 or a phrase such as "in 2 hours", read as UTC. Between one minute and thirty days out. Only with send: true.

4 more fields (audience_id, preview_text, topic_id, template)
  • audience_idstring

    Deprecated alias of segment_id, accepted for compatibility. Use segment_id.

  • preview_textstring

    The inbox preview line.

  • topic_idstring

    Scope the broadcast to a topic: only contacts opted in to it receive it.

  • templateobject

    { id } of a published template to copy the content from, instead of html and text.

Request

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>"
}'

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.

List broadcasts

GET /broadcasts

Every broadcast, newest first.

Query parameters

  • limitinteger

    How many items to return, 1–100. Defaults to 20.

  • afterstring

    Return the page that follows this item ID. Mutually exclusive with before.

  • beforestring

    Return the page that precedes this item ID. Mutually exclusive with after.

  • searchstring

    Only broadcasts whose name or subject contains this, ignoring case. At most 200 characters.

  • statusstring

    Only broadcasts in this status: draft, scheduled, queued, sending, sent, canceled or failed.

Request

curl -X GET "https://api.rasket.com/broadcasts" \
  -H "Authorization: Bearer $RASKET_API_KEY" \
  -H "User-Agent: acme-billing/1.0"

Response 200

{
  "object": "list",
  "has_more": false,
  "data": [
    {
      "id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17",
      "name": "September product update",
      "audience_id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
      "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.

Retrieve a broadcast

GET /broadcasts/{id}

One broadcast, with its content and status.

Path parameters

  • idstringRequired

    The broadcast's ID.

Request

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"

Response 200

{
  "id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17",
  "name": "September product update",
  "audience_id": "78261eea-8f8b-4381-83c6-79fa7120f1cf",
  "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.

Update a broadcast

PATCH /broadcasts/{id}

Change a draft. Only the fields present are touched.

Path parameters

  • idstringRequired

    The broadcast's ID.

Body

  • namestring

    A label for the dashboard. Not shown to recipients.

  • segment_idstring

    The segment the broadcast goes to.

  • fromstring

    Name <address> on one of your verified domains.

  • subjectstring

    The subject line. Merge variables are allowed.

  • reply_tostring[]

    Where replies go.

  • htmlstring

    The HTML body. At least one of html and text before sending.

  • textstring

    The plain-text body.

3 more fields (audience_id, preview_text, topic_id)
  • audience_idstring

    Deprecated alias of segment_id, accepted for compatibility. Use segment_id.

  • preview_textstring

    The inbox preview line.

  • topic_idstring

    Scope the broadcast to a topic: only contacts opted in to it receive it.

Request

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"
}'

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.

Delete a broadcast

DELETE /broadcasts/{id}

Remove a draft.

Path parameters

  • idstringRequired

    The broadcast's ID.

Request

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"

Response 200

{
  "object": "broadcast",
  "id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17",
  "deleted": true
}
  • Drafts only. A broadcast that was sent keeps its recipients and metrics; one that was scheduled must be canceled instead.

Send a broadcast

POST /broadcasts/{id}/send

Queue a draft now, or schedule it.

Path parameters

  • idstringRequired

    The broadcast's ID.

Body

  • scheduled_atstring

    ISO 8601 or a phrase such as "in 2 hours", read as UTC. Between one minute and thirty days out. Omit it — or send no body at all — to send now.

Request

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"
}'

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, or marketing sends paused platform-wide, 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.

Cancel a broadcast

POST /broadcasts/{id}/cancel

Stop a scheduled or queued broadcast.

Path parameters

  • idstringRequired

    The broadcast's ID.

Request

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"

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.

List a broadcast's recipients

GET /broadcasts/{id}/recipients

Who was sent, delivered, opened, clicked, bounced, complained, unsubscribed or suppressed.

Path parameters

  • idstringRequired

    The broadcast's ID.

Query parameters

  • typestringRequired

    sent, delivered, opened, clicked, bounced, complained, unsubscribed or suppressed.

  • emailstring

    Only recipients whose address contains this.

  • bounce_typestring

    permanent, transient or undetermined. Only with type=bounced.

  • limitinteger

    How many items to return, 1–100. Defaults to 20.

  • afterstring

    Return the page that follows this item ID. Mutually exclusive with before.

  • beforestring

    Return the page that precedes this item ID. Mutually exclusive with after.

Request

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"

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.

Check a broadcast

GET /broadcasts/{id}/checklist

Every condition of the send gate, passed or not, in the order a send checks them.

Path parameters

  • idstringRequired

    The broadcast's ID.

Request

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"

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
    },
    {
      "condition": "marketing_enabled",
      "passed": true
    },
    {
      "condition": "team_can_send",
      "passed": true
    },
    {
      "condition": "body",
      "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.

Duplicate a broadcast

POST /broadcasts/{id}/duplicate

A new draft with the same content, named `<name> (copy)`.

Path parameters

  • idstringRequired

    The broadcast's ID.

Request

curl -X POST "https://api.rasket.com/broadcasts/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17/duplicate" \
  -H "Authorization: Bearer $RASKET_API_KEY" \
  -H "User-Agent: acme-billing/1.0"

Response 201

{
  "object": "broadcast",
  "id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17"
}
  • The segment must still exist, or the copy is refused with 422 invalid_parameter.

Send a test of a broadcast

POST /broadcasts/{id}/test

Send the draft to up to five inboxes.

Path parameters

  • idstringRequired

    The broadcast's ID.

Headers

1 more field (Idempotency-Key)
  • Idempotency-Keystring

    Retries with the same key send the test once.

Body

  • tostring[]Required

    One to five addresses.

Request

curl -X POST "https://api.rasket.com/broadcasts/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17/test" \
  -H "Authorization: Bearer $RASKET_API_KEY" \
  -H "User-Agent: acme-billing/1.0" \
  -H "Content-Type: application/json" \
  -d '{
  "to": ["you@acme.example"]
}'

Response 202

{
  "object": "broadcast_test",
  "broadcast_id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17",
  "data": [
    {
      "id": "4ef9a417-02e9-4d39-ad75-9611e0fcc33c",
      "to": "you@acme.example"
    }
  ]
}
  • Each test counts as a send. Variables use their defaults, and unsubscribe links are placeholders.
  • Draft only (409 resource_locked). The token also needs emails:send.