← all tools
Sequencers

Lemlist

Run email and LinkedIn as one sequence.

Cost per callBYOK · vendor billed
Your own keyrequired
CategorySequencers

lemlist sends across both channels, so a candidate who ignored the email gets a LinkedIn touch inside the same campaign. Your agent loads the leads and reports on who engaged. Nothing starts sending until you say so.

lemlist is activation. It takes a validated list and turns it into conversations.

things you can ask for

  • Add these candidates to the sequence once Enrichley has cleared them
  • How is the campaign performing, and who replied this week?
  • Pause the sequence for this client's staff
  • Log every reply against the candidate in Recruiterflow

works well with Lemlist

  • Enrichley

    clean addresses before a multichannel sequence starts

  • HeyReach

    more LinkedIn volume than lemlist alone will carry

  • Recruiterflow

    replies belong on the record, not in an inbox

  • Prospeo

    the enrichment that fills the sequence

Skills that use Lemlist

A skill is a whole pipeline your agent already knows. These ones call Lemlist as part of the run.

signal5 steps

Hiring sprint → competitor poach

TheirStack flags 50+ open roles. Poach displaced talent via Apollo + Lusha into Lemlist.

coming soon

What your agent reads before it touches Lemlist

Every tool ships with a written playbook, and the agent loads it before the first call. Auth, rate limits, what each call costs, which actions need your approval, and the mistakes worth avoiding. It is the difference between an agent that knows the tool and one that guesses at it.

Read the Lemlist docs →
Show the raw playbookwritten for the agent

HOW in lib/lemlist.py. Endpoint set cached at reference/docs/lemlist/raw/llms.txt.

Auth & config

  • Base URL: https://api.lemlist.com/api · Auth: HTTP Basic — API key as the password, empty username (client sets auth=('', key)). Env LEMLIST_API_KEY; never hardcode. get_team() = safe read-only pilot.
  • Core paths CONFIRMED from developer.lemlist.com (ReadMe .md + llms.txt, 2026-06-01). QUIRK: version=v2 query param required on get_campaigns (defaulted) and other v2 reads. Add-lead is POST /api/campaigns/{id}/leads/ with email in the body (not the path). Rate limit 20 req/2s. Full index: reference/docs/lemlist/raw/endpoints.md; request() covers the long tail (companies, inbox, schedules, enrich, people-database, etc.).

Approval gates (sending)

  • start_campaign begins sending; add_lead_to_campaign enrolls a lead into active sending — approval-gate (pilot, confirm, then batch).

Operations

Campaigns: get_campaigns, get_campaign, get_campaign_stats, start_campaign, pause_campaign. Leads: add_lead_to_campaign, remove_lead_from_campaign. Contacts: get_contacts, upsert_contact. Plus get_activities, enrich_lead, get_team. Else → generic request().

Handoff

Activation layer (multichannel). Enriched+validated leads → add to campaign → review → start. get_activities feeds reply/interest tracking back to the ATS.

Field notes (production experience)

Field-shape note: these are vendor-native operational notes. The client returns the raw vendor JSON and uses the method names in this file — read field shapes accordingly (no normalized-wrapper / result.data. prefix).

Flow: create/list campaign -> add sequence steps -> add contacts in small batches (10-25) -> review in the Lemlist UI (web_url returned on create/update) -> monitor activities/inbox.

  • Step types: email, linkedinInvite, linkedinSend, linkedinVisit, manual, phone, api, whatsappMessage, conditional, sendToAnotherCampaign.
  • Delays are in DAYS (0 = immediate, 2 = 2 days). Passing 172800 ("seconds") triggers a > 1500 days API error.
  • Lead export states: all, contacted, interested, notInterested, emailsBounced, paused, emailsSent, emailsOpened, emailsReplied.
  • Activity types: emailsSent, emailsOpened, emailsClicked, emailsReplied, emailsBounced, emailsUnsubscribed.
  • Inbox sends need IDs: send_email requires send_user_id, send_user_email, send_user_mailbox_id - list the inbox first to discover them.
  • Dedup: duplicate emails / linkedin_url within a batch are rejected; cross-batch dupes can 409.
  • Prefer editing sequence steps while the campaign is draft/paused.

Callable surface — lib/lemlist.py

Import: from lib.lemlist import Lemlist → instantiate Lemlist() (reads key from env). Base: https://api.lemlist.com/api. Generic passthrough: request(method, path, *, params, json).

  • add_lead_to_campaign(campaign_id: str, email: str, *, payload: dict | None = None, **query) -> Any — POST /api/campaigns/{campaignId}/leads/ — add a lead (CONFIRMED). email goes in the
  • enrich_lead(payload: dict) -> Any — POST /enrich — enrich a lead (see api-reference/endpoints/enrich).
  • get_activities(**params) -> Any — GET /activities — outreach activity events (opens, replies, etc.).
  • get_campaign(campaign_id: str) -> Any
  • get_campaign_stats(campaign_id: str, **params) -> Any
  • get_campaigns(*, version: str = 'v2', **params) -> Any — GET /api/campaigns — list campaigns. version=v2 is REQUIRED (defaulted here);
  • get_contacts(**params) -> Any
  • get_team() -> Any — GET /team — team info (safe read-only pilot).
  • pause_campaign(campaign_id: str) -> Any
  • remove_lead_from_campaign(campaign_id: str, email: str) -> Any
  • start_campaign(campaign_id: str) -> Any — POST /campaigns/{id}/start — starts sending (outreach!). Approval-gate.
  • upsert_contact(payload: dict) -> Any — Create/update a contact (see api-reference/endpoints/contacts/upsert-contact).