Skip to main content
Create, personalize, and launch outbound email campaigns on top of an imported audience. The normal flow is 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:
  1. landbase-cli auth login — authenticate the session.
  2. landbase-cli account set — pick and persist the target account.
  3. landbase-cli contacts-import start — import contacts; this produces the tag the campaign targets.
Sending inboxes are configured separately on the account in the web app, not through the CLI. Without an active account the command exits with 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.
Create is instant and returns only { 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:
In template mode, message bodies may use only these bracketed variables (anything else is rejected): [Recipient's Name], [Recipient's Company Name], [Your Company], [Opener].
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 empty subject_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.
CSV columns: 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 as contacts-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).
Flags Re-uploading a fixed file is a full replace (idempotent). Terminal ingest phases: completed, partial, failed. The start response (without --watch):
With --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.
Bare coverage report — matched is the resolved audience size, covered the contacts with a complete message set, uncovered a sample still missing them:
With --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.
Flags
Launch ≠ sends. launch returns quickly with processing_messages and reaches scheduled shortly after — that means the audience is enrolled and handed to the scheduler, not that emails have gone out. Actual sends are further gated by inbox status and daily caps, the account send window (default 06:00–15:00 PT), and contact verification. Track real progress with status.
Returns { campaignId, status }status reaches scheduled shortly after:
With --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. Usage
integer
required
The campaign id.
Returns { 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
Returns { data: [...], totalCount }. See output schemas.

Errors