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
One call configures everything. The configuration - campaign, schedule, settings, sending accounts, and sequence - is all-or-nothing: if any part fails validation (for example an SMTP account that isn’t yours), nothing is created.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. Sending accounts can be updated live - the change takes effect on the
next sends.