Skip to main content
Create, personalize, and launch outbound LinkedIn campaigns on top of an imported audience. The flow mirrors email-campaignscreate → audience → messages → coverage → launch — with LinkedIn-specific deltas: steps run from order 0 (the connection request), messages are body-only, and there’s an extra sendability report. For a guided walkthrough see How to launch a campaign.
linkedin-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.
  4. A connected LinkedIn account, configured in the web app — required to launch. Launch sends from every connected LinkedIn account on the account.
Without an active account the command exits with linkedin-campaigns requires an account id...; pass --account=<id> per call as an escape hatch.

linkedin-campaigns create

Create a campaign draft. Reads a JSON body describing the audience and the message sequence, and returns { campaignId, status }. A template campaign carries one shared message per message-bearing step; 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 }; 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. Each sequence.steps[] entry: Example (template mode)

linkedin-campaigns audience

Export the campaign’s resolved contacts as one wide CSV so you (or an AI agent) can write one personalized message per contact, per message-bearing step. The file has the contact-context columns plus an empty message_<order> cell for each message-bearing order. Fill those cells in place and resubmit the same file with messages. 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.
integer
Cap the number of exported contacts (positive integer).
CSV columns: linkedin_url, first_name, last_name, title, company_name, company_website, industry, then message_<order> per message-bearing order. linkedin_url is the join key and must stay exactly as exported; each message_<order> is ≤ 5000 chars. message_0 is the connection-request note (sent with the invite); message_1.. are follow-ups. 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):
orders are the message-bearing step orders that drive the message_<order> columns.

linkedin-campaigns messages

Upload the filled wide CSV to the campaign. The back-end validates the file, matches rows by linkedin_url, and ingests them asynchronously. Without --watch the command returns the ingest-start response immediately; with --watch it polls to a terminal phase and prints the final ingest status. 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. Terminal ingest phases: completed, partial, failed. The start response (without --watch):
With --watch, the final status once terminal — the coverage.samples carry LinkedIn URLs and ordered bodies:
coverage is null while the ingest is still in flight.

linkedin-campaigns coverage

Inspect message coverage before launching — which matched contacts have a complete message set. Bare, it returns the coverage report; with --show <linkedinUrl> it returns that one contact’s stored per-step messages. Usage
integer
required
The campaign id to report coverage for.
string
A contact’s LinkedIn URL. Returns that contact’s stored messages instead of the report.
coverage and sendability are draft-only reports. After launch they return 409 coverage_unavailable / sendability_unavailable.
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 <linkedinUrl> — one contact’s ordered messages (null if none yet):

linkedin-campaigns sendability

Explain why the sendable audience is smaller than the tag: totals plus a per-reason breakdown. sendable is what the campaign will message; excluded is the count of tagged contacts not currently sendable. The contacts* reason counts are independent diagnostics that may overlap and need not sum to excluded. Usage
integer
required
The campaign (draft) id.
Draft-only (see the note under coverage). sendable is what the campaign will message (== total); excluded = tagged − sendable. The contacts* reason counts are optional diagnostics that may overlap and need not sum to excluded:

linkedin-campaigns launch

Launch a draft. Takes no body — the campaign enrolls its audience and hands off to the send pipeline, sending from every connected LinkedIn account. Launch is blocked (campaign_coverage_incomplete) until every matched contact has a complete message set. 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. Reaching scheduled means the audience is enrolled and handed to the send pipeline — invites and messages then go out on a throttled cadence bounded by LinkedIn rate limits and per-account caps, not all at once. Track real progress with status.
Returns { campaignId, status }:
With --watch, stdout is the final status object instead.

linkedin-campaigns status

Status for one campaign — type, lifecycle, and allocated/sent stats. Usage
integer
required
The campaign id.
Returns { campaignId, name?, status, campaignType?, stats? }. See output schemas.

linkedin-campaigns list

List the account’s campaigns, newest first. Usage
Returns { data: [...], totalCount }. See output schemas.

Errors