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.
  • TemplatesGuidesFifty-seven starters sorted by goal, and how to keep a campaign as a template.
  • 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.
  • Mail appsGuidesComing soon: your Rasket address in Apple Mail, Outlook and the Gmail app.
  • Inbox APIGuidesOpen, read and answer support conversations from your app, with the same key.
  • Support inbox in your appGuidesA Contact us form that opens a conversation your team answers, in five minutes.
  • Replies to your emailsGuidesOne field on a send, and the customer's reply opens a conversation.
  • Let an agent triageGuidesAn AI agent reads, notes and drafts over MCP; a person sends.
  • 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, Zapier and n8n, a WordPress plugin, and Notion contacts.
  • 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.
  • VercelGuidesAdd Rasket on Vercel: a Sending key in each project as RASKET_API_KEY, no copying.
  • WordPressGuidesThe Rasket plugin: every email your site sends, through Rasket, with a safe fallback.
  • NotionGuidesTurn a Notion database of people into contacts in a segment, once or every hour.
  • Migrating to RasketGuidesBring contacts, unsubscribes, lists and templates from Mailchimp, Klaviyo and more.
  • 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.
  • InboxAPI referenceChannels, conversations, messages, notes and search in your support inbox.

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.

Before you send

After the gate, a send runs the content checks over the saved draft. POST /broadcasts/{id}/checks runs them without sending, and the dashboard's preview shows them beside the email.

The content checks
CheckWhat it looks for
VariablesFails on a {{{KEY}}} that is no contact field or property and has no default: it would be sent empty.
LinksFails on a link that is empty, just #, or not a full web address.
Link typesFails on a link that runs code. Warns on one that is http rather than https.
SubjectFails when there is none. Warns past 60 characters.
Preview textWarns when there is none, or past 150 characters.
Alt textWarns on an image with no alt text.
Image weightWarns past 1 MB of images you uploaded to Rasket.
Text and imagesWarns when the email is mostly pictures.
UnsubscribeWarns when the body has no unsubscribe link of its own. We add one anyway.

Each check is pass, warn or fail. A fail stops the send with 422 validation_error and the failing checks in details.checks. Send again with acknowledge_checks: true to send anyway. A warning never stops anything.

Links are read as written. We never visit them, and no request leaves for them.

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 plan's daily and monthly email volume like any other send, 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 contact property, upper- or lower-case as its key is written.
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.

A body copied from a visual template keeps its show-when rules, and each recipient gets only the blocks their rules allow. A campaign has no trigger event, so a template's repeated items and event details stay empty here.

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.

  • acknowledge_checksboolean

    Send even though a content check fails. Without it, a failing check is 422 validation_error with the failing checks in details.checks.

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 of your own verified for sending (not your team address, which reaches only your team and is for drafts and tests); 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.
  • Then the content checks run (POST /broadcasts/{id}/checks). A failing one — a link that goes nowhere, a merge variable that would be sent empty, no subject — is 422 validation_error with the failing checks in details.checks, unless acknowledge_checks is true.
  • 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.

Check a broadcast's content

POST /broadcasts/{id}/checks

The pre-send checks over the saved draft. Nothing is changed and no link is visited.

Path parameters

  • idstringRequired

    The broadcast's ID.

Request

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

Response 200

{
  "object": "email_checks",
  "checks": [
    {
      "code": "unresolved_variable",
      "status": "fail",
      "title": "Variables",
      "message": "{{{FIRSTNAME}}} is not a contact field or property, so it would be sent empty. Check the spelling, or add a default: {{{FIRSTNAME|friend}}}."
    },
    {
      "code": "preheader",
      "status": "warn",
      "title": "Preview text",
      "message": "There is no preview text, so inboxes show the first words of the email beside the subject."
    },
    {
      "code": "subject",
      "status": "pass",
      "title": "Subject",
      "message": "24 characters."
    }
  ]
}
  • Each check is pass, warn or fail, failures first. Only a fail stops a send, and acknowledge_checks sends anyway.
  • Links are read as written, never visited. Picture weight counts the images you uploaded to Rasket.

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.

Save a broadcast as a template

POST /broadcasts/{id}/save-as-template

A new published template with the broadcast's subject, HTML and text.

Path parameters

  • idstringRequired

    The broadcast's ID.

Request

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

Response 201

{
  "object": "template",
  "id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d20"
}
  • Works on a broadcast of any status. Each call makes a new template.
  • The template is named after the broadcast, or its subject if it has no name.
  • {{{MERGE}}} variables are kept. They fill when you send the template as a broadcast, not as a single email.
  • Your key needs to write templates and read broadcasts. A broadcast with no HTML is 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.