Scopes
Lifecycle is deliberately a separate scope from
campaigns:write: starting a
campaign spends send quota and sender reputation. A key with only campaigns:write
can build and edit a campaign but cannot start sending. Creating with
launch: true therefore needs both scopes.Create a campaign
A campaign created through the API sends from all connected mailboxes of your
workspace (“use all accounts” mode).
accounts attaches mailboxes to the campaign,
but it does not limit which mailboxes send.accounts must be your workspace’s own accounts. leads are best-effort and
summarized in the response. If launch: true is set and the campaign can’t start,
the call still returns 201 - the campaign is created as a draft, with
launched: false and a launchError explaining why (start it later with
POST /v1/campaigns/{id}/start). Because the response is a success, a retry with
the same Idempotency-Key replays it instead of creating a second draft.
sendingMinutesStart / sendingMinutesEnd are minutes from midnight in the
campaign timezone - 540 = 09:00, 1020 = 17:00. Step delays are counted from
the previous step; the first step sends immediately when a lead enters.Response
Launch and control sending
Drive the send lifecycle through explicit routes -/start, /pause, or /resume.
To end a campaign, pause it (or delete it); completion otherwise happens
automatically when the end date passes or every lead has been sent.
"launch": true in the create
body (requires campaigns:lifecycle).
A campaign must have at least one lead and a sequence to start. A launch
attempt without them is rejected
400 on POST /start; on create-with-launch
the campaign is still created and returned as a draft (201, launched: false,
with a launchError).Send a test email
Before you launch, send yourself a rendered preview of one step variant, from a real mailbox, exactly as a lead would receive it.Response
personalization decides where merge variables come from. dummy fills them
with placeholders. lead uses a real lead, which you name with leadId. There
is no fallback: asking for lead without a leadId is rejected, so a test can
never quietly leak the wrong person’s data into an email.
The content is the campaign’s own: you cannot supply a body here, so this is not
a way to send arbitrary mail.A test goes out from a real mailbox and counts toward that mailbox’s daily
limit, but not toward your monthly email quota. It is capped at 12 tests per
day per workspace (
429 beyond that).The recipient must not be blocked in your workspace. A test carries your campaign
content, so the same do-not-email rules apply to it as to a real send: it is
refused for anyone on your blacklist, by address or by domain. That list is your
own instruction not to contact someone, and a test is not an exception to it.400 means something about the request needs changing – the mailbox rejected
the recipient, for example – and the message says what. If the send fails on our
side instead, you get a 503: the request was fine, it costs you no quota,
and retrying shortly is the right move. Distinguishing the two matters if you
retry automatically: a 400 is worth giving up on, a 503 is not.
Tags
Every campaign inGET /v1/campaigns carries its tags – the ones you set in the
dashboard. The API reads them and lets you filter by them, so “the campaigns for
client X” is a single call rather than a full page-through.
Tags are created, renamed, and deleted in the dashboard, not through the API.
There is no
/v1/tags resource.Campaign tags and mailbox tags are separate sets. Two tags with
the same name on the two pages are different tags, and their ids never cross over: a
campaign tag id passed to GET /v1/accounts?tags= matches nothing.Check status
A lightweight poll of live send-state, the schedule window, and headline metrics:Response
Update
PATCH touches only the sections you supply. Supplying accounts or sequence
replaces that section entirely (the sequence is replaced in place - you always
end up with exactly the steps you sent). A supplied sequence must have at least
one step - an empty array is rejected (400); omit the field to leave the
sequence unchanged.
Unlike create,
PATCH applies each supplied section independently - it is not a
single cross-section transaction, so a later section failing does not roll back an
earlier one. Send one section at a time if you need to isolate failures. The
sequence of a campaign that is actively sending cannot be changed; pause it
first. accounts can be updated live, but it does not limit which mailboxes
send - the campaign sends from all connected mailboxes of the workspace.