lemlist
Run multichannel outreach
- Category
- Sales & CRM
- Primary Subcategory
- Sales Engagement & Outreach Automation
Integration details
Description
lemlist is a sales engagement platform for running multichannel outreach across email, LinkedIn, calls, WhatsApp, and SMS from a single sequence. Campaigns and sequences: create campaigns, draft and preview personalized multichannel sequences step by step, set up A/B variants and AI-generated variables, validate a campaign before launch, and start, pause, or resume it. Leads and prospecting: search your existing campaign leads, add or import leads, update their data and custom variables, and search the lemlist leads database to build new lists. Enrichment tools can look up a lead's professional email and phone number, individually or in bulk, using enrichment credits from your plan. Signals and watch lists: build watch lists that track buying signals on companies you care about, browse the signal library, and turn a watch list into a campaign. CRM and contacts: create and update contacts and companies, organize them into lists, import them from CSV, and push campaign leads into your contact database. Conversations and activity: read your unified inbox, follow up on conversations, reply to a lead, review call activity and outcomes, and work through your task list. Deliverability and sending infrastructure: check the deliverability and DNS health of your sending domains, review and configure DNS records, run a deliverability audit and inbox placement tests, and connect, test, and manage the mailboxes you send from. Reporting: track how campaigns perform with detailed stats and reports across channels. Account: review your team, users, sending settings, unsubscribe list, and webhooks. All actions run on your own lemlist workspace with your own data, using the permissions granted to the connected account.
- Integration type
- Plugin
- Verification status
- Not applicable
- Platform
- ChatGPT
- Primary Subcategory
- Sales Engagement & Outreach Automation
- Secondary Subcategories
- None listed
- Brand
- lemlist
- Access
- Account required
- First tracked
- 2026-09-19
- Tool count
- 123
- Geography
- US
The Primary Subcategory used for this profile’s headline score.
Other Subcategories where the Integration is listed.
Get alerts for lemlist
Get updates when lemlist’s Discoverability Score or category rank changes.
ChatGPT Plugin Discovery Score
lemlist in Sales Engagement & Outreach Automation
#8of 15competitors
This is the score for the Integration’s Primary Category, Sales Engagement & Outreach Automation. lemlist's tools align with this Category, which is why we measure it here. Claude did not find it in connector search, show it in the connector picker, or invoke it in the measured contested Runs. That is why the score is 0.
What we measure
One core score. Three important factors to discoverability.
- How often your Plugin appeared in the picker, or Claude invoked it directly, across contested conversations. This percentage is the Discoverability Score; the headline number is rounded.Sets the score
Picked
· 0/100 - Whether Claude found your Plugin in connector search. It must be Found before it can reach the picker, but the score counts picker appearances—not search results.Diagnostic
Found
· 0/100 - What position your Plugin appeared in when it was shown in the picker. This shows prominence, but it does not affect the score.Diagnostic
Positioned
· 0/100
Competing in ChatGPT Sales Engagement & Outreach Automation
View Category123 tools agents can invoke
Add one or more leads to a campaign in a single call (max 100). Requires campaignId + a non-empty leads array. Each lead must have at least one identifying field (email, firstName, lastName, companyName, phone, linkedinUrl, linkedinUrlSalesNav, or customVariables). Server-side bulk dedup runs during the import — **do NOT call search_campaign_leads or search_contacts to pre-check** before this tool. The response reports each existing lead with outcome="skippedAlreadyInCampaign" (or "skippedDuplicateCrossCampaign" when deduplicate=true), so the LLM has full visibility without an extra round-trip. Invalid leads are reported in the results array with outcome="missingIdentifier", "forbiddenCustomKey", etc. — they do not abort the rest of the batch. Company matching: send companyDomain alongside companyName whenever you can (the work email usually gives it away). A name on its own only matches companies that have no domain, so omitting the domain creates a SECOND company with the same name and moves the contact onto it. Enrichment options (findEmail, verifyEmail, linkedinEnrichment, findPhone) and deduplicate apply to every lead in the batch. ⚠️ Enrichment COSTS CREDITS per successfully added lead — warn the user before enabling.
add_leads_to_campaign
REQUIRES CONFIRMATION: Add a step to an ALREADY CREATED campaign sequence (modification only). For initial campaign creation use save_campaign_from_proposal instead — it materializes the whole tree atomically. Supported types: email, linkedinSend, linkedinInvite, linkedinVisit, linkedinFollow, linkedinEndorse, linkedinLikeLastPost, linkedinCommentLastPost, linkedinWithdrawInvitation, linkedinVoiceNote (LinkedIn voice message. Two INDEPENDENT settings: recordMode = how the audio is produced, manual = the "Mark as manual" toggle. Set recordMode="ai" to generate the audio from a script via ElevenLabs: pass the script in `message` (full Liquid syntax) and the voice in `voiceId` (call list_voice_profiles first). When NO AI voice is available, set `manual: true` so the step becomes a per-lead recording task and the campaign stays launchable: do NOT set a voiceId and the script is optional (`message` is then only the optional LinkedIn invite-fallback text). Do NOT create a non-manual voice note with recordMode="manual" and no audio - the auto-send path still requires a recorded file at launch), manual, phone, whatsappMessage, sms, conditional, sendToAnotherCampaign, api, enrichment (⚠️ COSTS CREDITS: automatically enriches leads at this sequence step using the specified workflowIds; requires MULTI plan). By default the step is appended at the end; pass `index` (zero-based) to insert at a specific position (e.g. index=0 to insert before the first existing step). For YES/NO branching use type="conditional" with conditionKey and delayType. delayType is ALWAYS required: use "within" or "waitUntil" for action conditions (hasScore, emailsOpened, emailsClicked, emailsUnsubscribed, meetingBooked, linkedinInviteAccepted, linkedinOpened, aircallDone), use "within" with delay 0 for field-check conditions (hasEmailAddress, hasLinkedinUrl, hasPhoneNumber). For hasScore: use scoreComparator ("$gte"/"$lt") and scoreThreshold (0-100). For hasEmailAddress: use emailStatusFilter (["deliverable","risky","undeliverable","unverified"]). For aircallDone ("Call status", branch on native lemlist call dispositions): use callStatusFilter (call status KEYS, e.g. ["connected-positive","no-answer"]; keys are team-specific, call get_call_statuses first; omit to match any completed call). For customLeadInfo (branch on any custom lead variable): use customField (variable name, e.g. "secteur"; prefix "fields." for a contact field), customOperator ("equal"/"contains"/"empty"/"notEmpty"), customValue (required for equal/contains), with delayType="within" and delay 0. To move a lead between campaigns (e.g. when a LinkedIn invitation is not accepted within 7 days), use type="conditional" with conditionKey="linkedinInviteAccepted" and delayType="waitUntil", then add a type="sendToAnotherCampaign" step (with targetCampaignId) inside the NO branch. Beware of cycles between campaigns. For type="api" (outbound webhook to Zapier/Make/n8n/Pipedream/etc.): provide method (GET or POST only, iso with the lemlist UI) and url. The URL supports Liquid templating against lead variables. The request body for POST is automatically the lead data — custom bodies and custom headers are not supported. Response returns sub-sequence IDs for YES/NO branches. Also returns the full updated step list in `steps` (each with its real `stepId`, `sequenceId`, `type`, `delay`). Reuse those ids for any follow-up edit in the same turn — do NOT call get_campaign_context to rediscover steps. REQUIRES userConfirmed=true. Fails on running campaigns.
add_sequence_step
Add one or more email addresses OR whole email domains to the unsubscribe blocklist in a single call. Blocks all future campaign sends. Use delete_unsubscribe to reverse. **Accepted values (each entry in `emails`):** - An email address, e.g. "[email protected]" — blocks that address only. - A domain starting with "@", e.g. "@acme.com" — blocks every lead whose email is on that domain. Batch semantics: - One call handles up to 1000 targets. Always pass ALL the values the user asked to block in a single call. Do NOT call the tool once per email. - Duplicates and values that are already unsubscribed are silently ignored server-side (no per-item failure). - Use the "@domain.com" form when the user wants to stop contacting everyone at a company (e.g. "block @luxottica.com").
add_unsubscribe
Add existing CRM contacts to a contact list. **When to use:** - User wants to organize contacts into lists (e.g. "Nurturing", "Hot leads") - User wants to move or copy contacts from search results into a specific list - After searching contacts with search_contacts, user wants to group them **Parameters:** - contactIds: Contact IDs in ctc_xxx format (required, max 1,000) - listId: Target contact list ID in clt_xxx format (required) **IMPORTANT:** - To get valid contact IDs, call search_contacts first - To get a valid listId, call get_contact_lists first — never invent or guess a list ID - Contacts already in the list are silently skipped (no duplicates) **Example:** { "contactIds": ["ctc_abc123", "ctc_def456"], "listId": "clt_xyz789" }
add_contacts_to_list
Enrich one or more contacts (max 500). ASYNC — lemAgent clients receive a 'dataRef' to pass to bulk_get_enrichment_results. External MCP clients receive an inline 'results' array of { enrichmentId?, error?, metadata? } to poll individually. ALL options COST CREDITS per item. Types: find_email, find_phone, verify, linkedin_enrichment. Submitting an enrichment does NOT mean data will be found. An enrichment can complete with nothing found. Always confirm the actual result via bulk_get_enrichment_results (check each 'summary') before telling the user any data was found.
bulk_enrich_data
Poll one or more enrichments in one call. Provide exactly one of: a dataRef returned by bulk_enrich_data (first poll), the nextPollRef from a previous result (subsequent polls), OR a plain enrichmentIds list — not both. Each call returns ONLY the enrichments that completed or failed in this poll. Use nextPollRef as the dataRef input for the next call. Repeat until pending=0. When pending=0, the dataRef contains ALL completed rows from every poll — pass it to display_table to show the full results in one table. Intermediate polls return a dataRef with only the newly completed rows for incremental display. A completed enrichment (status "done") can still return NO data. Inspect each result's 'summary' before reporting anything: when 'summary.noDataFound' is true (or the only fields present are 'emailNotFound'/'phoneNotFound'), tell the user that profile was "not found". Never claim an email, headline, or company was found, and never narrate fields that are absent from the 'summary'. An empty results table means nothing was found, not success. lemAgent clients get compact summaries + dataRef + nextPollRef; external MCP clients get full 'data' and 'input' inline per entry.
bulk_get_enrichment_results
Compute cold-email infrastructure sizing from campaign inputs. Returns: - Peak daily volume + injection rate - Mailbox count (raw and with safety buffer) - ESP split (Google / Microsoft / SMTP) - Domains needed per seat (cap: 3 mailboxes per domain) - Warmup timeline (rampup + 14-day stabilization) - Lemlist slot cost (included + extras at $9/month) - Brand-consistent domain name suggestions - Mailbox naming proposals per SDR (when sdrs provided), with SDR userId echoed back in `sdrPlans[].userId` if it was passed in All math is deterministic — pure domain function, no LLM math. Use in Step 2 of the outreach-infra skill, after gathering campaign inputs via ask_question.
calculate_infrastructure
⚠️ **REQUIRED FIRST STEP**: You MUST call `load_skill("api-reference")` once in the current session before `call_api`. The server rejects every `call_api` until then. `load_skill("api-reference")` returns the live catalog of available endpoints (cached 1h from the OpenAPI spec). Without it the model cannot know which paths exist; with it, `call_api` is unlocked for the session. ⚠️ **FALLBACK ONLY** — Use a dedicated tool whenever one exists in your tools list. Call `call_api` only when no dedicated tool matches. Common operations are covered by dedicated tools — scan your tools list first for matches in these categories before reaching for `call_api`: - **Campaigns:** list, details, stats, reports, create, start/pause, readiness - **Leads:** add to campaign, update, enrich, search within a campaign - **Sequences:** list steps, add step, update step (with preview) - **Contacts & lists:** search, create, manage CRM lists - **Inbox:** list/read conversations, send email/LinkedIn/SMS/WhatsApp - **Team & user:** team info, members, settings, connected channels - **Enrichment:** single / bulk / lead; poll results - **Webhooks & unsubscribes:** list, create, delete - **People database:** filter options, search, push to contacts **Strict server-side validation:** - Endpoints covered by a dedicated tool are **rejected** — the error names the tool to use. - If that tool is **not in your tools list** (this connector exposes a narrowed set), the call runs instead and the result carries a `hint` naming the tool and the bucket that would provide it. Relay that hint to the user: they can widen their connector URL to get the dedicated tool. - Endpoints not found in the lemlist OpenAPI spec are **rejected** — suggestions of similar spec endpoints are returned in the error. **Genuine use cases (no dedicated tool yet):** - Campaign schedules: `GET /api/campaigns/:campaignId/schedules`, `POST /api/campaigns/:campaignId/schedules/:scheduleId` (associate), `DELETE /api/campaigns/:campaignId/schedules/:scheduleId` (remove), `GET /api/schedules`, `POST /api/schedules` (create) - Email templates - Any documented endpoint without a dedicated tool **Safety rules:** - GET requests execute immediately - POST, PUT, PATCH, DELETE require `confirmed: true` after user approval **Full API reference:** https://developer.lemlist.com/api-reference **Example — replace a campaign schedule:** 1. `POST /api/campaigns/cam_xxx/schedules/skd_new` (associate new) 2. `DELETE /api/campaigns/cam_xxx/schedules/skd_old` (remove old)
call_api
Check DNS health for email sending domains (MX, SPF, DMARC, blacklists). Returns score (0-100), per-check status, and DNS fix records.
check_domain_health
Write DNS records for a team-owned domain. Two modes: - Provide **records**: replaces the domain's full record set (SPF / DMARC / MX / CNAME etc.). - Provide **dkimRecord**: appends the DKIM TXT record only (after mailbox provisioning). Use in Step 4 (initial SPF/DMARC/MX) and Step 6 (DKIM after Google/M365 gives the public key) of the outreach-infra skill.
configure_domain_dns
Connect a custom SMTP/IMAP email account for sending and receiving emails. For Google/Microsoft, use the UI instead. - You need SMTP credentials for sending and IMAP credentials for receiving - Ports are typically 587 (SMTP) and 993 (IMAP) with TLS enabled - The sender email will be verified before the account is connected
connect_email_account
Copy every lead from one campaign into another, in a single call, with FULL fidelity. Prefer this over composing search_campaign_leads + add_leads_to_campaign whenever the user wants to copy / recreate / move / duplicate the leads of a whole campaign into another campaign (e.g. "copy the leads from campaign A into campaign B", "put everyone from the old campaign into the rebuilt one"). Composing the two other tools drops fields (Sales Nav URL, phone, custom variables) and creates new empty contacts — this tool does not. Use when the user asks about: - Copying/recreating a whole campaign's leads into another campaign - Repopulating a freshly duplicated campaign (duplication never copies leads) from the original Contract rules reproduced by the backend: - Works by lead id server-side: it reuses each lead's existing CRM contact (no empty duplicate) and copies every variable (linkedinUrlSalesNav, phone, custom fields). - Both campaigns must belong to the current team; sourceCampaignId and targetCampaignId must be different. - ADDS to the target (source campaign is left untouched). Leads already in the target follow the same dedup rules as a manual push.
copy_campaign_leads
Use ONLY in the People Database scope. Return the exact number of People Database documents (leads or companies) that match a set of filters, without returning the documents themselves. Use it when: - The user asks how many people or companies match a set of criteria. - To refine a set of filters after people_database_nl_to_filters. - To size an audience before running a full search or building a campaign. - To compare how restrictive two filter sets are. Every filterId must be an exact id returned by list_people_database_filters.
people_database_search_count
Create a NEW AI variable column (an AI-generated column in the Leads table: icebreaker, opener, company research, etc.) on a campaign. Provide the column name, the AI-generation prompt, and optionally the model. The column is created team-owned and editable, wired into the campaign so it shows up in the Leads table and generates for leads. Use {{variable}} placeholders in the prompt to reference existing fields or columns. The variable name must be unique on the campaign — creating a duplicate is rejected. To edit an existing column's prompt instead, use update_ai_variable_prompt; to read existing columns, use get_ai_variable_prompts. Creating the column only sets it up — it does NOT generate values. Values are generated per lead later (from the Leads table UI or on import) and that is what consumes credits, not this call. Pass autofill:true to turn the column's auto-generate toggle on, so every lead added or imported to the campaign afterwards (CSV import, CRM sync, manual add) generates it automatically; it stays off by default. To scrape LinkedIn profiles for the column, pass tools:["enrich-linkedin"] AND reference {{linkedinUrl}} in the prompt; enabling any tool forces the premium lemlist model and lemlist-credit billing (per lead, at generation). Use when the user asks to: - Add a new AI column / AI variable to a campaign's leads - Generate a new piece of AI content (research, icebreaker, summary) per lead - Have an AI column filled automatically for every lead imported into a campaign This mutates campaign configuration, so confirm the column name and prompt with the user before calling.
create_ai_variable_prompt
Create campaign. If subject AND body are provided, creates the first email step. If omitted, creates an empty sequence (use add_sequence_step to add a condition or any step type as the first step). Call add_sequence_step for each additional step. Supports Liquid syntax, including spin for variations (only when the user asks for them): {% spin %}{% variation %}Hello{% variation %}Hi{% endspin %} — each variation must be genuinely different wording, never the same text repeated.
create_campaign_with_sequence
Create one or more campaign folders that share the same parent, in a single call. Use when the user asks about: - Adding one or several folders at the same level (pass them all in `names`). - Creating sub-folders under an existing folder (pass its `parentId`). For a nested chain (A > B > C) call once per level instead, threading each returned folderId as the next `parentId`. Contract rules reproduced by the backend: - Each name must be unique among folders that share the same parent. - Depth is capped at 15 levels, 50 folders per level, 500 folders per team. - Best-effort: valid names are created even if others fail; the response lists `created` and `failed` (with a per-name reason).
create_campaign_folder
Create a People Database persona for the current team. Use when the user asks about: - Saving a set of People Database filters as a reusable audience - Defining an ICP / persona to reuse later Contract rules reproduced by the backend: - name must be non-empty and unique within the team (duplicates are rejected) - mode must be "leads": company personas are not supported yet - every filterId must be an exact id returned by list_people_database_filters, and its values must come from get_people_database_filter_values - filters gated by a plan the team does not have are silently dropped Returns the created persona id (pdp_xxx).
create_people_database_persona
Get a presigned URL to upload a file from the user's machine to lemlist storage, then reference it by key. Use this to AVOID retyping large file contents through the conversation. Flow: 1. Call this tool with purpose, fileName, and the EXACT fileSize in bytes. 2. Upload the raw file to the returned uploadUrl with an HTTP PUT, e.g.: curl -T leads.csv -H "Content-Type: <contentType>" "<uploadUrl>" 3. Pass the returned uploadKey to the tool that consumes it: - purpose="leadsCsv" → import_leads_to_campaign - purpose="contactsCsv" → import_contacts_from_csv - purpose="companiesCsv" → import_companies_from_csv - purpose="csvData" → read_uploaded_csv The URL is short-lived (expiresInSeconds). fileSize MUST be the real byte size of the file — it is signed into the URL, so a mismatch makes the upload fail, and a size above the limit is rejected up front.
create_upload_url
Create a new watch list for the current team. Use when the user asks about: - Starting to monitor a new signal type - Setting up a watch list end-to-end (create + configure + activate) - Creating a draft watch list that the user will configure later in the UI Contract rules reproduced by the backend: - activate=true ⇒ segmentType AND signalProcessingType must be set - signalProcessingType="create_opportunity" ⇒ signalOpportunityTemplate required (and forbidden otherwise) - personaId is accepted ONLY on a company watch list with signalProcessingType="push_to_campaign" (any other config is rejected), and only for teams in the personas beta - personaId is optional there: without it the signals are still recorded, they simply source no contact, so nothing reaches the campaign - get a personaId from list_people_database_personas (or create_people_database_persona); never invent one - Only segmentType="all" is accepted via API (CRM lists and CSV imports are not)
create_watch_list
Create a webhook for real-time campaign activity notifications. Max 200 per account, no duplicate URLs. Filter by activity type (emailsSent, emailsOpened, emailsReplied, etc.) and/or campaignId.
create_webhook
Create a new static contact list in the user's CRM. **When to use:** - User wants to create a new contact list to organize contacts - User asks to group contacts into a new list that doesn't exist yet **Parameters:** - name: Name of the list (required, max 200 characters) **After creating the list:** - Use add_contacts_to_list to add contacts to the newly created list - The returned list ID (clt_xxx) can be used immediately **Example:** { "name": "Nurturing" }
create_contact_list
Create a new company in the user's Lemlist company database, or update an existing one (upsert). Requires both a name AND a domain. If a company with the same domain, LinkedIn URL, or Sales Navigator URL already exists, it will be updated instead of creating a duplicate. Returns the company data and whether it was created or updated.
create_or_update_company
Create a new contact in the user's Lemlist contact database, or update an existing one (upsert). Requires at least an email OR linkedinUrl as identifier. If a contact with the same email or LinkedIn URL already exists, it will be updated instead of creating a duplicate. Returns the contact data and whether it was created or updated. Use search_contacts first to check if the contact already exists.
create_or_update_contact
Delete one or more campaign folders. Campaigns are NEVER deleted — each folder's campaigns and sub-folders move up one level (to the parent folder, or to the root if the folder was at the top). Use when the user asks about: - Removing one or several folders while keeping their campaigns (pass them all in `folderIds`). Contract rules reproduced by the backend: - Deleting a folder is blocked if a sub-folder would collide, by name, with a folder already present in the parent — rename the conflicting sub-folder first. - Best-effort: each id is handled independently; the response lists `deleted` and `failed` (with a per-id reason).
delete_campaign_folder
Permanently delete leads from ONE campaign in a single bulk call. Irreversible: it also removes each lead's activity and task history in that campaign. Use when the user asks about: - Removing a specific set of leads from a campaign at once (e.g. after moving or segmenting them elsewhere) - Cleaning leads out of a campaign without calling the unitary delete endpoint one lead at a time Two-phase confirmation flow (mandatory): 1. First call WITHOUT confirmed (or confirmed=false): returns the count and a sample of the exact leads that will be deleted, with status="awaiting_confirmation". Show these to the user and get explicit approval via ask_question. 2. Once the user has approved, call again with confirmed=true to actually delete. Contract rules reproduced by the backend: - Scoped to a SINGLE campaignId; a lead id is unique to one campaign (campaignId + email). - Every leadId MUST belong to campaignId. Ids from another campaign (or already deleted) are rejected with an error, not silently skipped. Re-fetch the ids via search_campaign_leads on the target campaign. - At most 1000 lead ids per call. - Never call with confirmed=true without explicit user approval.
delete_campaign_leads
REQUIRES CONFIRMATION: Delete a lemlist company. Only the lemlist record is removed — no CRM-side propagation. REQUIRES userConfirmed=true. By default the call fails with COMPANY_HAS_CONTACTS if contacts are still attached; pass force=true to detach them (their companyId is unset) before deleting. Typical use: as the final step of the duplicate-remapping flow — after reassigning contacts of a duplicate to the canonical company (via create_or_update_contact with companyId), drop the now-empty duplicate.
delete_company
REQUIRES CONFIRMATION: Delete a lemlist contact by its ID (ctc_xxx) or email. Only the lemlist record is removed — no CRM-side propagation. Deletion cascades to the contact's leads, opportunities, list memberships, inbox conversations and activities. REQUIRES userConfirmed=true. Fails with CONTACT_DELETE_BLOCKED when the contact cannot be deleted right now (e.g. an enrichment is still running — retry once it finishes).
delete_contact
Delete a memory by topic. Use this when: - The user asks you to forget something - Information is explicitly outdated or incorrect - The user says "that's no longer true" or "forget about..."
delete_memory
Delete a People Database persona of the current team. The deletion is permanent. Use when the user asks about: - Removing a persona they no longer need - Cleaning up duplicate or outdated personas Important: - Ask the user to confirm before calling this tool; there is no undo. - Use list_people_database_personas to resolve a persona name into its id. - An unknown id, another team's persona, and the auto-generated system persona all fail the same way (not found) — none of them can be deleted here.
delete_people_database_persona
REQUIRES CONFIRMATION: Delete a step from a campaign sequence. Use this to remove a step that was added by mistake or is no longer needed (e.g. a wrongly-placed warm-up step). Cascades sub-sequences for conditional steps. Returns the full updated step list in `steps` (each with its real `stepId`, `sequenceId`, `type`, `delay`). Reuse those ids for any follow-up edit in the same turn — do NOT call get_campaign_context to rediscover steps. REQUIRES userConfirmed=true. Fails on running campaigns: pause the campaign first.
delete_sequence_step
Remove one or more email addresses OR whole email domains from the unsubscribe list in a single call. Re-enables the targets to be contacted again in future campaigns. **Accepted values (each entry in `emails`):** - An email address, e.g. "[email protected]" — re-enables that address only. - A domain starting with "@", e.g. "@example.com" — re-enables every address on that domain (only removes a domain-level block; per-address blocks stay). Batch semantics: - One call handles up to 1000 targets. Always pass ALL the values the user asked to re-subscribe in a single call. Do NOT call the tool once per email. - Values that weren't unsubscribed (or are protected internal blocks) are silently ignored server-side. **Use this when:** - Leads were unsubscribed by mistake - A lead wants to re-subscribe to your campaigns - You need to re-enable communication with specific emails or domains - Testing campaigns with your own email address **Important notes:** - Once removed, the emails can receive campaigns again - This does NOT automatically re-add the leads to any campaign - The emails will need to be added to campaigns manually - Use with caution — respect unsubscribe preferences **Example:** { "emails": ["[email protected]", "@partner.com"] } **Common workflow:** 1. Check if the emails are unsubscribed (via search_campaign_leads) 2. Call delete_unsubscribe with the full list to remove them from the unsubscribe list 3. Add the leads back to a campaign if needed **IMPORTANT:** Do NOT pass confirmed=true on your first call. Use the returned emails to ask the user to confirm via ask_question, then call again with confirmed=true.
delete_unsubscribe
Delete a watch list. The backend performs a soft delete (status set to "delete") and stops processing signals for this watch list immediately. Use when the user asks about: - Removing a watch list they no longer want to monitor - Cleaning up outdated or duplicate watch lists Two-phase confirmation flow: 1. First call WITHOUT confirmed (or confirmed=false): returns the watch list details and status="awaiting_confirmation". Use these details to ask the user to confirm via ask_question. 2. Once the user has explicitly approved, call again with confirmed=true to actually delete. Important: - Never call with confirmed=true without explicit user approval. - Use list_watch_lists first if you need to resolve a name into a watch list ID. - The watch list is soft-deleted; its signals are not removed.
delete_watch_list
Delete a webhook from your lemlist account. The webhook will stop receiving notifications immediately. **Use this when:** - Removing outdated integrations - Cleaning up unused webhooks - Replacing a webhook (delete old, create new) - Webhook URL has changed and needs to be recreated **Important notes:** - Once deleted, the webhook cannot be recovered - The webhook will immediately stop receiving notifications - Use get_webhooks to find the webhook ID first **Example:** { "webhookId": "hoo_abc123xyz" } **Common workflow:** 1. Call get_webhooks to list all webhooks 2. Find the webhook ID you want to delete 3. Call delete_webhook with that ID
delete_webhook
Disconnect email account. Stops sending immediately. Cannot be undone. Use get_user_channels to find account ID.
disconnect_email_account
Show leads in an interactive workspace table. Users can select, filter, and push to campaigns. For the two-step pattern (lemleads_search in companies mode with `description` -> display_leads), you MUST pass the returned `dataRef` to this tool. The server resolves it to the full company set server-side and injects a `currentCompanyByIds` filter so the leads table queries leads at those companies. This persists in the workspace item (no 30-min TTL concern). Do NOT copy the `companyIds` array into a `currentCompanyByIds` filter inline — emitting hundreds of IDs inline risks truncation; pass them via the `companyIds` field instead and the server builds the filter for you. FOLLOW-UP TURNS over an existing companies table ("find CEOs of those companies", "now show me leads from this list", "and the marketing directors"): the workspace already holds the company set, so DO NOT re-run lemleads_search. Recovery order: 1. If the companies-mode lemleads_search `dataRef` from earlier is still in your context AND was issued in the last ~30 minutes, pass it as `dataRef`. 2. Otherwise, call `get_workspace_items({ itemType: "companies" })`, read `data.companyIds` from the workspace_companies item, and pass that array via the `companyIds` field on this tool. The server builds `currentCompanyByIds` for you (no truncation risk). Re-running lemleads_search to "re-verify the count" loses the curated set and is what produces the bad / off-topic lead lists. Otherwise (no prior companies table involved), call display_leads directly with filters only — the table loads data dynamically. Pass any combination of `filters`, `dataRef`, and `companyIds` together; they are AND-combined server-side. To modify an existing LEADS search: get_workspace_items -> display_leads with updated filters + replaceItemId. Only pass replaceItemId when the target item is itself a leads table — never to convert a companies/messages/other item into leads. To show a different artifact type alongside, omit replaceItemId so a new item is appended.
display_leads
Fetch one page of People Database leads for the workspace-leads table. App-only: called by the leads grid iframe (pagination, select-all), not by the agent. Returns the raw Elastic hits the iframe transforms into rows, the total count, and the already-in-campaign / already-in-contacts maps.
display_leads_page
Display a data table in the workspace panel. CRITICAL RULES — follow exactly or the table will be empty: 1. dataRef: If the source tool returned a dataRef string, pass it as dataRef (preferred — avoids large data transfer). The rows will be resolved automatically from the stored reference. 2. rows: Only if no dataRef is available. Pass the ORIGINAL data array from the tool result AS-IS. NEVER construct row objects manually or map/transform the array. 3. columns: Use suggestedColumns from the source tool result directly when available. NEVER invent column keys — they must match actual property names in the row objects. PREFERRED: dataRef=result.dataRef, columns=result.suggestedColumns, groupKey=result.groupKey, tableType=result.tableType FALLBACK: rows=result.campaigns, columns=result.suggestedColumns WRONG: rows=result.campaigns.map(c => ({sentCount: c.stats.sentCount})) — this strips data Always forward groupKey and tableType from the source tool when available.
display_table
Enrich existing campaign lead. ASYNC — poll with bulk_get_enrichment_results (pass enrichmentIds: [id]). For non-campaign contacts use bulk_enrich_data. ALL options COST CREDITS.
enrich_lead
Find real, validated LinkedIn URLs to monitor for a watch list type. Returns LinkedIn URLs (person /in/ or company /company/ depending on the type), sourced and validated from live web search and grounded in the team's business context (AI Context Center). Use when the user asks about: - Pre-filling the LinkedIn URLs for a linkedinPeopleProfile, linkedinCompanyProfile, competitorConnections or competitorReactions watch list - Discovering relevant LinkedIn profiles or company pages to watch Important: - Only the 4 LinkedIn signal types are accepted; any other type is rejected. - Pass an optional "focus" to steer the search; otherwise it falls back to the type's name. - Returns an empty list when no relevant URLs are found. - Rate-limited per user per day (a limited number of calls).
find_watch_list_linkedin_urls
Generate an AI-powered outreach campaign for an existing watch list. Builds a campaign from a predefined sequence template, writes every step's copy with AI (steered by copyStyle and the watch list's signal), links it to the watch list, and returns the campaign with its generated sequences. Use when the user asks about: - Turning a watch list's signals into a ready-to-run outreach campaign - Auto-generating a sequence + AI copy targeted at what the watch list monitors Flow: - Run it on an existing watch list, or create one first (create_watch_list), then call this tool to generate its campaign. - autoLaunch=true launches the campaign immediately; false leaves it in draft. Important: - The watch list (watchListId) must exist for the current team. - reviewBeforeSend only applies when autoLaunch=true.
generate_campaign_for_watch_list
Read the AI-generation prompts of a campaign's AI variable columns (the AI-generated columns in the Leads table: icebreakers, openers, contextual openers, etc.). Returns one entry per AI variable: its variable name, the prompt used to generate it, and the AI model. Prompts come back verbatim, with raw {{variable}} placeholders (e.g. {{firstName}}) left unresolved, since a prompt is a template applied across all leads (there is no single lead to resolve against). Use when the user asks to: - See how an AI column (icebreaker, opener, ...) is generated for a campaign - Review or audit the prompt behind a campaign's AI variables before editing it Read-only: no credits consumed, nothing is changed. To edit a prompt, use update_ai_variable_prompt; to add a new column, use create_ai_variable_prompt.
get_ai_variable_prompts
Return the published business context for the current team — markdown describing the company, its value propositions, ICP, products, etc., generated from the team's website. Use BEFORE: - crafting any messaging, sequence step, or persona suggestion - recommending watch list types (so the AI knows what the team sells and to whom) - onboarding flows that need to reference the team's business Response shape: - data: null → no business context generated yet (suggest running the onboarding generation) - data: { markdown, sourceUrl, generatedAt, lastEditedAt, updatedAt }
get_business_context
List call activities from the lemlist dialer (cold calls), with filtering and pagination. Use when the user asks about: - Calls made or received through the lemlist dialer - Filtering calls by campaign, lead, contact, user, status/disposition, direction, or date range - Reviewing call outcomes, durations, or which leads were called Each call includes direction, duration, status/disposition, phone provider, whether a recording exists, the AI transcript summary, and the associated lead/contact/campaign/user IDs. Use get_call_details with an activityId to fetch the recording URL and full transcript for a single call.
get_call_activities
Get full details for ONE dialer call by its activity ID, including the recording URL and transcript. Use when the user asks about: - The recording or transcript of a specific call - The full context of a call (lead, contact, company, campaign, call note, disposition) Returns call metadata, the associated lead/contact/company/campaign/user, the manual call note (if any), and — unless includeRecording is false — a temporary recording URL plus the full transcript. Use get_call_activities first to find the activityId.
get_call_details
List this team's configured call statuses (dispositions) — the valid KEYS for update_call_status. Use when: - BEFORE update_call_status, to pick a valid status key for this team (keys are team-specific: defaults plus any custom statuses) - The user asks which call dispositions / statuses exist Returns each status with its key (what update_call_status expects), label, and side effects: whether it marks the lead answered / positive / negative and whether it pauses campaigns.
get_call_statuses
Get configuration and settings for one or more campaigns (timezone, emoji, labels, senders, sequences). For metrics use get_campaigns_stats, for email content use get_campaign_sequences. MUTUALLY EXCLUSIVE — pass EITHER campaignId (single) OR campaignIds (1-20, batch), never both and never neither. Sending both fields together is rejected with a validation error. When campaignIds is used, the result is an array in the same order; a campaign that fails to load carries an "error" field on its entry while the others still succeed.
get_campaign_details
Get the email sequences and their content (subject, body) for one or more campaigns. Useful for reviewing copywriting and email flow. CALL THIS TOOL whenever the user asks to: - Audit / review / check a campaign against standards, best practices, a checklist, or a "cahier des charges" - Verify compliance of a campaign built via the MCP - Assess whether manual steps have the right title / priority - Inspect the full step-by-step structure with task-mode metadata (manual, priority, title), CC recipients, and condition branches This is the authoritative source for per-step data — prefer it over the sidebar campaign context for any compliance or standards audit. A/B tests: when a step runs an A/B test, its top-level subject/message are variant A. The parallel variant B is returned in a "variantB" object, and "abTest" carries the test state (true while running, "A"/"B" once a winner is picked). Covers email and linkedinInvite steps. Absent when the step has no A/B test. Always check both variants before answering questions about an A/B step. Task-mode fields returned per step (only surfaced when the step is manual — either manual=true on a togglable channel type, or a natively-manual type like phone/manual; auto steps get none of them): - manual: true when a togglable channel step (email, linkedinSend, linkedinInvite, linkedinVoiceNote, whatsappMessage, sms) is set to "Manual step" instead of auto-send. Absent when automated. Natively-manual types (manual, phone) don't emit this — they're always manual. - priority: task priority (0=Low, 1=Medium, 2=High). Absent when unset (None). - title: task title displayed in the review UI. MUTUALLY EXCLUSIVE — pass EITHER campaignId (single) OR campaignIds (1-20, batch), never both and never neither. Sending both fields together is rejected with a validation error. When campaignIds is used, the result is an array in the same order; a campaign that fails to load carries an "error" field on its entry while the others still succeed.
get_campaign_sequences
List campaigns with search, filtering and sorting. - Use 'search' to find campaigns by name (recommended first approach) - Use 'labels' to filter by campaign labels/tags (OR semantics, accepts names or lab_ IDs) - Each campaign in the response includes its labels as an array of names - Results sorted by newest first by default - Returns dataRef for display_table (pass dataRef + suggestedColumns) - Use get_campaigns_stats for detailed metrics with date filtering.
get_campaigns
Get lifetime stats for MULTIPLE campaigns in one call. Returns metadata, sender info, and 65+ metrics per campaign. No date filtering - for time-based analysis use get_campaigns_stats.
get_campaigns_reports
Get detailed stats for one or more campaigns, with optional time-period filtering. Returns lead funnel, message metrics (total + per-channel breakdown), and per-step breakdown. Omit startDate/endDate for all-time (lifetime) stats. Timezone & date bounds: - startDate/endDate accept TWO formats: 1. Calendar day "YYYY-MM-DD" — interpreted as start/end of day in the given timezone. 2. Full ISO 8601 datetime ("2026-04-01T00:00:00+05:30", "...Z") — used as-is, the timezone arg is ignored. - When YYYY-MM-DD is used and "timezone" is omitted, the tool resolves the timezone in this order: (1) the calling user's profile.timezone if set in their Lemlist preferences, (2) Europe/Paris. - Lemlist has no per-team timezone setting; the UI shows numbers using the BROWSER's local timezone. To exactly mirror what a user sees in the Lemlist UI, capture campaignReportsTimePeriod from the UI session and pass those ISO 8601 strings here — that removes timezone ambiguity entirely. Aggregation matches the Lemlist UI Campaign Reports tiles: - `messageMetrics.sent` ↔ "Messages sent" tile (events: emailsSent + linkedinSent + linkedinInMailSent + linkedinVoiceNoteDone + smsSent + whatsappMessageSent). - `messageMetrics.delivered` ↔ "Delivered" tile (emailsSentNotBounced + linkedinSent + linkedinInMailSent + linkedinVoiceNoteDone + smsDelivered + whatsappMessageDelivered). - `leadMetrics.reached` ↔ "Leads reached" tile (unique leads with a contact activity). - `channelMetrics.linkedinInvitationAccepted` ↔ "Invitation accepted" tile (linkedinInviteAccepted events). - `*Percentage` fields use the same 1-decimal rounding as the UI: Math.round(x / total * 1000) / 10. - `messageMetrics.perChannel` mirrors the UI channel dropdown (email / linkedin / sms / whatsapp / others). - Note: this is the same pipeline as the UI Campaign Reports tile — DIFFERENT from the Reports Dashboard (/reports-dashboards/) which aggregates leads by first-contact date with a different formula. Comparing this MCP output to Reports Dashboard tiles WILL produce mismatches by design. Use when the user asks about: - Campaign performance (overall or over a specific period) - Comparing stats across multiple campaigns - Monthly/weekly campaign analysis - Multi-channel reporting (email vs LinkedIn vs SMS vs WhatsApp) - Any campaign metrics or analytics
get_campaigns_stats
How do I improve a ChatGPT Plugin's discoverability?
The levers are the listing surface agents actually read: names, descriptions, keywords, tool metadata, and registry health. Which lever matters depends on where discovery breaks, which is what continuous measurement shows.
What are lemlist alternatives on ChatGPT?
As of 2026-09-21, lemlist competes with Reply.io, Outreach, Mixmax, Amplemarket, FirstTouch, Instantly.ai, JobPhoning, Lightmeter, LinkupAPI, MimikFlow, OneUp Today, SalesBreaker GTM, Taverity, toflow.ai in ChatGPT Sales Engagement & Outreach Automation, ranked by public Discoverability Score.
Where does lemlist rank in Sales Engagement & Outreach Automation on ChatGPT?
As of 2026-09-21, lemlist ranks #8 of 15 in ChatGPT Sales Engagement & Outreach Automation with a Discoverability Score of 0/100 (Invisible).
Where is this profile measured?
This profile uses the geography attached to the latest public registry snapshot: US. Locale tags are intentionally omitted.