Agent Skill · Landbase

landbase-email-campaigns

Create and launch outbound email campaigns from an imported audience via landbase-cli. Use when the user wants to build, personalize, send, or check an email campaign — covers the create -> audience -> messages -> coverage -> launch flow, the per-contact personalized-CSV path, and the "launch != sends" gotcha.

Provider: Landbase Path in repo: tools/landbase-email-campaigns/SKILL.md

Skill body

Landbase email campaigns

landbase-cli email-campaigns runs the full outbound flow on top of the platform gateway. The normal order is:

create -> audience -> messages -> coverage (optional check) -> launch

Run landbase-cli email-campaigns --help for the exact subcommand/flag reference; this skill is the procedural guide.

Prereqs (in order)

  1. landbase-cli auth login — platform session.
  2. landbase-cli account set — pick + persist the account id.
  3. Import contacts via the contacts-import skill — a hard handoff: follow that skill end to end and do not run contacts-import start until its mapping flow has produced a resolved mapping for the body. The import produces the tag the campaign targets; contacts-import status <importId> surfaces both tagName and tagId.

Sending inboxes are configured separately on the account (in the web app), not via this CLI.

Identifying the audience tag

The audience names its tag by exactly one of:

The back-end resolves tagName to an id within the account. Tag names are not guaranteed unique per account; if a name matches more than one tag the create call fails with tag_name_ambiguous and lists the candidate {id, name, type} — re-issue with the explicit tagId from that list.

create body shape

Template mode (one shared message per step)

Channel must be "email"; step orders contiguous from 1; each step carries an inline message. Bodies may use ONLY these bracketed variables (anything else 400s): [Recipient's Name] [Recipient's Company Name] [Your Company] [Opener].

{
  "schemaVersion": 1,
  "name": "Q2 outreach",
  "audience": {
    "type": "tag",
    "tagName": "Q2 Leads",
    "excludeContactedDays": 30,
    "excludeType": "contacted",
    "limitPerCompany": 2
  },
  "sequence": {
    "steps": [
      {
        "order": 1,
        "channel": "email",
        "daysDelay": 0,
        "message": { "subject": "...", "body": "..." }
      },
      {
        "order": 2,
        "channel": "email",
        "daysDelay": 3,
        "message": { "subject": "...", "body": "..." }
      }
    ]
  }
}

("tagId": 15 may be used instead of "tagName" — exactly one.)

Personalized mode (per-contact messages generated locally by an AI agent)

Set "messaging": { "mode": "personalized" } on create. Steps are a skeleton — order/channel/daysDelay only, NO inline message. The agent fills ONE wide CSV (one row per contact) and uploads it; the back-end matches by email and sends the copy verbatim (no server-side generation).

Create-first flow:

  1. landbase-cli email-campaigns create --json campaign.json (mode personalized, N steps)
  2. landbase-cli email-campaigns audience --campaign <id> --out audience.csv
  3. (agent) landbase-cli onboarding get — pull seller-side context for the copy.
  4. (agent) fill subject_1/body_1 ... subject_N/body_N in audience.csv, in place.
  5. landbase-cli email-campaigns messages --campaign <id> --csv audience.csv --watch
  6. landbase-cli email-campaigns coverage --campaign <id> --show <email> (spot-check)
  7. landbase-cli email-campaigns launch <id> --watch

Seller context (step 3) matters. onboarding get returns aboutCompany / aboutAudience / aboutCompetition — the value prop, ICP, and differentiation the copy needs to land. The more complete the account onboarding, the better the generated messages; fill it in (onboarding update) before generating.

The wide CSV = the exported context columns + subject_i/body_i for each step. email is the join key (must match the export exactly). subject_i ≤ 1000 chars, body_i ≤ 10000 chars. The back-end validates the upload and reports per-row errors in the ingest status. Upload is async + idempotent (re-upload a fixed file = full replace).

Coverage gate. launch is BLOCKED on incomplete coverage — fix the CSV and re-upload. Partial / covered-only launch is not supported; every matched contact must have a message.

Assignment (optional — send from a teammate’s inboxes)

By default the caller owns the campaign and their inboxes send. To send from another account user:

--watch runs long — prefer a sub-agent

Both messages --watch (ingest) and launch --watch poll and can block for a minute or more (launch polls up to 10×10s; ingest longer). When driving from a coding agent, dispatch the --watch call as a sub-agent so it doesn’t tie up the main session. Without --watch the command returns immediately and you poll later with messages / status.

LAUNCH != SENDS (the trap)

launch returns immediately with "processing_messages" and hands the audience to the async scheduler; the campaign reaches "scheduled" a little later. launch --watch polls the status (max 10, 10s apart) so you can see it land on "scheduled" — on timeout the launch already succeeded, just keep polling with status.

"scheduled" means enrolled + handed to the send scheduler; actual sends are further gated by inbox status + daily caps, the account send window (default 06:00–15:00 PT), and contact verification. status returns:

{ status, stats{delivered,replies,bounced,contacted},
  outreach{inQueue,inProgress,completed}, excluded{...},
  timing{estimatedDaysToFirstTouchComplete,estimatedDaysToCompletion,dailyCapacity} }

Audience accounting: create and launch return only { campaignId, status }. Enrollment

Errors (upstream bodies surface verbatim)

Example (import -> create -> launch -> track)

# import.json must already carry the resolved "mapping" built by the
# contacts-import skill — never start without one.
landbase-cli contacts-import start --json import.json
landbase-cli email-campaigns create --json campaign.json
# If the campaign is assigned to a teammate this exits 1 CONFIRMATION_REQUIRED:
# show the user the assignee and re-run with `--yes` only after they confirm.
landbase-cli email-campaigns launch 123 --watch
landbase-cli email-campaigns status 123

Work with this as data

Every skill here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for agent skills

4 MCP tools reach this
  • find_skillsBrowse and filter every skill in the catalog.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This skill
curl "https://apis.io/api/v1/skills/landbase-email-campaigns"
All agent skills
curl "https://apis.io/api/v1/skills?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.