GET /send/campaigns/{campaign_id} will
tell you exactly what’s still missing.
Before your first campaign, connect at least one sender. Nothing launches
without one. See account setup.
The recipe
1
Create the campaign
draft. Nothing sends until you launch it.2
Add senders
Senders belong to the organization; here you pick which ones this campaign
draws from. Add several and sends spread across them.
GET …/senders shows the
current pool plus the org senders available to add.3
Declare what you know about each person
The person schema is the People tab’s columns. Declare it before enrolling
anyone, so their context has somewhere to land.Pass
{"fields": []} if you only need name, email, and company. Skipping
this step entirely gets you 409 PERSON_SCHEMA_REQUIRED when you enroll.4
Enroll people
From a list — this is where Leads and Send meet:
mapping connects list columns to person-schema fields. why_this_person
is the one-line reason this prospect is worth contacting — it’s what the
copy generator leans on, so point it at a real column or set
default_why_this_person.You can also pass people inline instead of a list_id, and row_ids to
take only specific rows. Either way it’s synchronous, up to 1,000 per call.5
Write the template
A template is one or more variants (A/B arms), each a list of steps.
personalized (and subject_personalized) mark phrases that should be
rewritten per recipient. A bare string is the phrase copied verbatim from
the body; { text, name, instruction } also names the variable and steers
generation. If a phrase doesn’t match the body exactly you get
409 TEMPLATE_SPANS_INVALID.Step channel is email, linkedin_message, linkedin_connect,
linkedin_comment, linkedin_react, or manual. manual is persistable,
not sendable — include it on a GET → PUT so UI-added steps aren’t dropped.
Comment and react steps act on the person’s posts; pass posts when you
enroll people inline, or the step waits (on_missing_post: hold) until a
post exists.Up to 10 variants, 15 steps each. Add arms one at a time with
POST …/templates/sequences
rather than replacing the whole template; each keeps a variant_key that is
never reused, so stats stay comparable over time.6
Read what will actually go out
Templates are not what people receive. Generate the real per-person copy and
read it before anything sends.That’s one LLM call per person, so it returns a Job. When it finishes, read
the results with
GET …/examples.A message that isn’t right can be fixed in place with
PATCH …/people/{sequence_id}/steps/{step_index},
and POST …/revert throws your
edits away and re-renders from the template.7
Set the schedule
Settings can be patched in any status, including while the campaign is
running. Omitted fields are left alone.
8
Dry run, then launch
Check the gates without committing:A dry run reports exactly what a real launch would check. Drop
dry_run to
go live.While it’s running
GET …/people pages everyone with
their current status, including bounced and unsubscribed, and takes a
search filter.
If you turned on require_message_approval, messages queue up until you release
them:
Stopping things
stop and remove both accept {"dry_run": true} if you want to see the blast
radius first.
What’s next
Account setup
Connect senders, buy domains, provision mailboxes.
Webhooks
Get replies, bounces, and opens pushed to you instead of polling.