create → audience → messages → coverage → launch,
but a template-mode campaign can go straight from create to launch. For a
guided, end-to-end walkthrough see
How to launch a campaign.
email-campaigns is a platform-mode command. Before running it:landbase-cli auth login— authenticate the session.landbase-cli account set— pick and persist the target account.landbase-cli contacts-import start— import contacts; this produces the tag the campaign targets.
email-campaigns requires an account id...; pass --account=<id> per call as
an escape hatch.email-campaigns create
Create a campaign draft. Reads a JSON body describing the audience and the email sequence, and returns{ campaignId, status }. A template campaign carries
one shared message per step and is ready to launch immediately; a
personalized campaign carries a skeleton sequence whose per-contact copy you
upload later with messages.
Usage
string
required
Path to a JSON file with the campaign definition, or
- to read it from
stdin. See create --json config below for the body shape.{ campaignId, status }; audience and
exclusion counts come from status after launch.
create --json config
audience names its tag by exactly one of tagName (preferred — the
human-readable name contacts-import shows you) or tagId (the numeric id). If
a name matches more than one tag the call fails with tag_name_ambiguous;
re-issue with the explicit tagId. Optional filters: excludeContactedDays
(skip contacts touched in the last N days), excludeType ("contacted" or
"replied"), and limitPerCompany.
Each sequence.steps[] entry:
Example (template mode)
email-campaigns audience
Export the campaign’s resolved, enriched contacts as one wide CSV so you (or an AI agent) can write one personalized message per contact, per step. The file has the contact-context columns plus emptysubject_i/body_i pairs for each
step. Fill those cells in place and resubmit the same file with messages —
do not create a second CSV. Used only for personalized campaigns.
Usage
integer
required
The campaign (draft) id returned by
create.string
Write the CSV to this file and print a JSON summary to stdout. Without it, the
raw CSV is written to stdout (redirect it to a file yourself).
integer
Cap the number of exported contacts (positive integer). Useful for a quick
sample before generating copy for the whole audience.
email, first_name, last_name, title, company_name, company_website, industry, employee_range, linkedin_url, then subject_1, body_1, …, subject_N, body_N for the N steps. email is the join key and must
stay exactly as exported; subject_i ≤ 1000 chars, body_i ≤ 10000 chars.
With --out, the CSV is written to the file and stdout is a JSON summary;
without --out, the raw CSV is written to stdout (not JSON):
email-campaigns messages
Upload the filled wide CSV to the campaign. The back-end validates the file, matches rows by email, and ingests them asynchronously (same upload-and-poll shape ascontacts-import). Without --watch the
command returns the ingest-start response immediately; with --watch it polls
to a terminal phase and prints the final ingest status (including a coverage
summary).
Usage
integer
required
The campaign id to upload messages for.
string
required
Path to the filled messages CSV (the same file exported by
audience).
Re-uploading a fixed file is a full replace (idempotent). Terminal ingest
phases:
completed, partial, failed.
The start response (without --watch):
--watch, the final status once terminal — including a coverage summary:
coverage is null while the ingest is still in flight.
email-campaigns coverage
Inspect message coverage before launching — which matched contacts have a complete message set. Bare, it returns the coverage report; with--show <email>
it returns that one contact’s stored per-step messages.
Usage
integer
required
The campaign id to report coverage for.
string
A contact email. Returns that contact’s stored messages instead of the report.
matched is the resolved audience size, covered the
contacts with a complete message set, uncovered a sample still missing them:
--show <email> — one contact’s stored messages (null if none yet):
email-campaigns launch
Launch a draft. Takes no body — the campaign enrolls its audience and hands off to the send scheduler. Launch is blocked (campaign_coverage_incomplete)
until every matched contact has a complete message set; on a blocked launch the
CLI prints which contacts are still uncovered. With --watch the command polls
the status (up to 10 times, 10s apart) until it reaches a terminal state
(target: scheduled).
Usage
integer
required
The draft campaign id to launch.
Returns
{ campaignId, status } — status reaches scheduled shortly after:
--watch, stdout is the final
status object instead.
email-campaigns status
Composed status for one campaign — lifecycle plus the delivery funnel, exclusions, and timing estimates. Usageinteger
required
The campaign id.
{ campaignId, name?, status, stats?, outreach?, excluded?, timing? }.
Audience and exclusion counts are produced by the scheduler after launch —
read them here, not from the create/launch responses. See
output schemas.
email-campaigns list
List the account’s campaigns, newest first. Usage{ data: [...], totalCount }. See
output schemas.

