# Lemlist

> Manage email campaigns, enrich leads, and track engagement activities through Lemlist's sales engagement platform.

Source: https://cotera.co/docs/reference/tools/individual-tools/lemlist

---

**Authentication Type:** API Key
**Description:** Manage email campaigns, enrich leads, and track engagement activities through Lemlist's sales engagement platform.

***

## Beta Notice

**This tool is currently in beta testing and not yet available for general use.**

To get the Lemlist tool added to your Cotera workspace, please contact our support team at [support.cotera.co](https://support.cotera.co).

***

## Authentication

To authenticate, you'll need a Lemlist API Key. Learn how to create one in the [Lemlist API documentation](https://developer.lemlist.com/).

***

## Activity

### Get Activities

List activities across campaigns — email sent, opened, clicked, replied, LinkedIn actions, and more. Supports filtering by activity type, campaign, lead, date range, and pagination.

**Operation Type:** Query (Read)

**Parameters:**

* **type** `string` (optional): Filter by activity type (e.g. `emailsSent`, `emailsOpened`, `emailsClicked`, `emailsReplied`, `linkedinInviteAccepted`). Must match exact spelling from Lemlist's `ActivityType` enum.
* **campaignId** `string` (optional): Filter by campaign identifier.
* **leadId** `string` (optional): Filter by lead identifier.
* **isFirst** `boolean` (optional): When `true`, only return the first activity.
* **offset** `number` (optional): Number of records to skip for pagination (defaults to `0`). Increment by `limit` to page through results.
* **limit** `number` (optional): Records per request (defaults to `100`, maximum `100`).
* **minDate** `string` (optional): Only return activities with `createdAt >= minDate`. Accepts a Unix timestamp or ISO 8601 datetime.
* **maxDate** `string` (optional): Only return activities with `createdAt <= maxDate`. Must be after `minDate`. Accepts a Unix timestamp or ISO 8601 datetime.

**Returns:**

* **activities** `array of objects`: Activity records, each with fields like `_id`, `type`, `leadId`, `campaignId`, `sequenceId`, `sequenceStep`, `createdAt`, `userId`, `userName`, `leadFirstName`, `leadLastName`, `leadEmail`, `leadCompanyName`, `contactId`, `teamId`, and `lead`.

**Example:**

```json
{
  "type": "emailsReplied",
  "campaignId": "cam_abc123",
  "minDate": "2024-01-01T00:00:00Z",
  "maxDate": "2024-03-31T23:59:59Z",
  "limit": 100,
  "offset": 0
}
```

***

## Campaign

### Create Campaign

Create a new email outreach campaign in Lemlist. Returns the campaign ID and sequence ID needed to add steps and leads.

**Operation Type:** Mutation (Write)

**Parameters:**

* **name** `string` (required): The name of the campaign.
* **timezone** `string` (optional): Timezone for the campaign schedule (e.g. `"America/New_York"`). Defaults to `null`.

**Returns:**

* **id** `string`: The campaign ID.
* **sequenceId** `string`: The sequence ID (use with Add Email Step / Add LinkedIn Step).
* **scheduleIds** `array of strings`: List of schedule IDs.
* **name** `string`: The campaign name.
* **state** `string`: The current state of the campaign (e.g. `"draft"`).

**Example:**

```json
{
  "name": "Q1 Outbound — Enterprise",
  "timezone": "America/New_York"
}
```

***

### Get Campaign

Retrieve details of a specific Lemlist campaign by its ID.

**Operation Type:** Query (Read)

**Parameters:**

* **campaignId** `string` (required): The ID of the campaign to fetch.

**Returns:**

* **id** `string`: The campaign ID.
* **name** `string`: The campaign name.
* **status** `string`: The current status (e.g. `"draft"`, `"running"`, `"paused"`).
* **createdAt** `string`: ISO 8601 timestamp of when the campaign was created.
* **sequenceId** `string` (nullable): The sequence ID associated with the campaign.
* **hasError** `boolean`: Whether the campaign has any errors.

**Example:**

```json
{
  "campaignId": "cam_abc123"
}
```

***

### Get Campaign Leads

List the leads in a Lemlist campaign, newest first. Optionally filter by state and cap the number returned.

**Operation Type:** Query (Read)

**Parameters:**

* **campaignId** `string` (required): The ID of the campaign to list leads for.
* **state** `string` (optional): Filter by lead state (e.g. `scanned`, `contacted`, `interested`, `notInterested`). Leave empty for all states.
* **limit** `number` (optional): Maximum number of leads to return (default `100`, max `500`).

**Returns:**

* **leads** `array of objects`: Campaign leads, newest first. Each lead includes its `id`, `contactId`, `state`, and other lead fields.

**Example:**

```json
{
  "campaignId": "cam_abc123",
  "state": "interested",
  "limit": 50
}
```

***

### Get Campaign Sequences

Fetch the sequences of a Lemlist campaign, including each sequence's steps (email/LinkedIn/conditional), delays, messages, and step IDs. Useful for finding a `stepId` to skip, or understanding a campaign's structure.

**Operation Type:** Query (Read)

**Parameters:**

* **campaignId** `string` (required): The ID of the campaign to fetch sequences for.

**Returns:**

* **sequences** `array of objects`: The campaign sequences. Each entry includes its `id`, `steps` (with `type`, `delay`, `message`, `subject`, `conditions`, etc.), and `level`.

**Example:**

```json
{
  "campaignId": "cam_abc123"
}
```

***

## Contact

### Get Contact

Retrieve a contact from the Lemlist people directory by ID or email. Returns contact details, custom fields, unsubscribe status, and associated campaigns.

**Operation Type:** Query (Read)

**Parameters:**

* **idOrEmail** `string` (required): The contact ID or email address to look up.

**Returns:**

* **id** `string`: The contact ID.
* **fullName** `string` (nullable): The contact's full name.
* **email** `string` (nullable): The contact's email address.
* **fields** `object`: Custom fields and metadata for the contact.
* **unsubscribed** `boolean`: Whether the contact has unsubscribed.
* **campaigns** `array of objects`: List of campaigns the contact is part of.

**Example:**

```json
{
  "idOrEmail": "jane.doe@example.com"
}
```

***

### Get Contact Messages

Retrieve the message conversation (inbox thread) for a contact by contact ID. Returns the messages exchanged plus pagination metadata. Optionally marks the conversation as read.

**Operation Type:** Query (Read)

**Parameters:**

* **contactId** `string` (required): The unique identifier of the contact whose conversation should be retrieved.
* **userId** `string` (optional): ID of the user viewing the conversation. Required when `markAsRead` is `true`.
* **limit** `number` (optional): The maximum number of messages to return.
* **skip** `number` (optional): Number of messages to skip for pagination (defaults to `0`).
* **markAsRead** `boolean` (optional): When `true`, marks the conversation as read. Requires `userId` to be set. Defaults to `false`.

**Returns:**

* **messages** `array of objects`: Message objects in the conversation, each with `_id`, `type`, `messageId`, `createdAt`, `sendUserId`, `sendUserName`, `sendUserEmail`, `leadEmail`, `contactId`, `message` (HTML body), `subject`, and `attachments`.
* **pagination** `object`: Pagination metadata (`total`, `page`, `limit`).

**Example:**

```json
{
  "contactId": "con_abc123",
  "limit": 20,
  "skip": 0,
  "markAsRead": false
}
```

***

### Upsert Contact

Create or update a contact in the Lemlist people directory. Matches on email or LinkedIn URL to decide whether to create or update.

**Operation Type:** Mutation (Write)

**Parameters:**

* **email** `string` (optional): The contact's email address.
* **linkedinUrl** `string` (optional): The contact's LinkedIn profile URL.
* **firstName** `string` (optional): The contact's first name.
* **lastName** `string` (optional): The contact's last name.
* **phone** `string` (optional): The contact's phone number.
* **jobTitle** `string` (optional): The contact's job title.
* **companyDomain** `string` (optional): The contact's company domain.
* **companyId** `string` (optional): The Lemlist company ID to associate this contact with.

**Returns:**

* **id** `string`: The contact ID.
* **created** `boolean`: Whether a new contact was created.
* **updated** `boolean`: Whether an existing contact was updated.
* **email** `string` (nullable): The contact's email address.
* **fullName** `string` (nullable): The contact's full name.

**Example:**

```json
{
  "email": "jane.doe@example.com",
  "firstName": "Jane",
  "lastName": "Doe",
  "jobTitle": "VP of Engineering",
  "companyDomain": "example.com"
}
```

***

## Company

### Upsert Company

Create or update a company in the Lemlist directory. Matches on domain to decide whether to create or update.

**Operation Type:** Mutation (Write)

**Parameters:**

* **name** `string` (required): The company name.
* **domain** `string` (required): The company domain (e.g. `"acme.com"`).
* **linkedinUrl** `string` (optional): The company's LinkedIn page URL.
* **industry** `string` (optional): The company's industry.
* **location** `string` (optional): The company's location.
* **size** `string` (optional): The company size (e.g. `"51-200"`).
* **description** `string` (optional): A short description of the company.

**Returns:**

* **id** `string`: The company ID.
* **created** `boolean`: Whether a new company was created.
* **updated** `boolean`: Whether an existing company was updated.
* **domain** `string` (nullable): The company's domain.

**Example:**

```json
{
  "name": "Acme Inc",
  "domain": "acme.com",
  "industry": "Software",
  "size": "51-200",
  "location": "San Francisco, CA"
}
```

***

## Enrichment

### Enrich

Enrich a person with additional data — find a verified email, find a phone number, enrich LinkedIn profile data, or verify an email. Returns an enrichment ID to poll for results (see Get Enrichment Result).

**At least one action flag** (`findEmail`, `findPhone`, `linkedinEnrichment`, or `verifyEmail`) must be `true`, otherwise the tool throws an error. You must also supply enough identity input for the requested action (e.g. a `linkedinUrl` for `linkedinEnrichment`, or `firstName` + `lastName` + `companyDomain`/`companyName` to find an email).

**Operation Type:** Query (Read)

**Parameters:**

* **email** `string` (optional): The person's email address. Required with `verifyEmail`; also usable as input for other enrichments. Defaults to `null`.
* **linkedinUrl** `string` (optional): The person's LinkedIn profile URL. On its own this is enough for `linkedinEnrichment`. Defaults to `null`.
* **firstName** `string` (optional): The person's first name. Combine with `lastName` + `companyDomain`/`companyName` to find an email without a `linkedinUrl`. Defaults to `null`.
* **lastName** `string` (optional): The person's last name. Defaults to `null`.
* **companyDomain** `string` (optional): The person's company website domain (e.g. `example.com`). Defaults to `null`.
* **companyName** `string` (optional): The person's company name (e.g. `Acme Inc`). An alternative to `companyDomain` for matching. Defaults to `null`.
* **jobTitle** `string` (optional): The person's job title. Improves email-finding accuracy. Defaults to `null`.
* **webhookUrl** `string` (optional): URL Lemlist will POST the enrichment result to when it completes, as an alternative or addition to polling. Defaults to `null`.
* **findEmail** `boolean` (optional): Find a verified email address. Needs `firstName` + `lastName` + `companyDomain`/`companyName` (`jobTitle` improves accuracy). Defaults to `false`.
* **findPhone** `boolean` (optional): Find a phone number. Defaults to `false`.
* **linkedinEnrichment** `boolean` (optional): Run LinkedIn profile enrichment. Needs `linkedinUrl`, or `firstName` + `lastName` + `companyDomain`/`companyName`. Defaults to `false`.
* **verifyEmail** `boolean` (optional): Verify an existing email address. Requires the `email` input. Defaults to `false`.

**Returns:**

* **enrichmentId** `string`: The ID of the enrichment request. Use with Get Enrichment Result to poll for the enriched data.

**Example:**

```json
{
  "firstName": "Jane",
  "lastName": "Doe",
  "companyDomain": "example.com",
  "jobTitle": "VP of Engineering",
  "findEmail": true,
  "linkedinEnrichment": true
}
```

***

### Get Enrichment Result

Fetch the result of a Lemlist enrichment by its ID. Enrichment is **asynchronous**: while processing, the tool returns `inProgress: true` with an empty `data` object (HTTP 202). Poll until `inProgress` is `false` and `status` is `"done"`.

**Operation Type:** Query (Read)

**Parameters:**

* **enrichmentId** `string` (required): The enrichment ID returned by the Enrich tool (e.g. `enr_123`).

**Returns:**

* **enrichmentId** `string`: The enrichment ID.
* **status** `string`: The enrichment status (e.g. `"done"`, `"inProgress"`).
* **inProgress** `boolean`: `true` when the enrichment is still processing. Poll again until `false`.
* **input** `object`: The input parameters the enrichment was requested with.
* **data** `object`: The enriched results (e.g. `email`, `phone`, `LinkedIn` data). Empty until the enrichment is done.

**Example:**

```json
{
  "enrichmentId": "enr_abc123"
}
```

***

## Inbox

### Get Inboxes

List the inboxes (conversation threads) for a Lemlist user. Returns inbox metadata including the associated contact, channels, and reply status, plus pagination.

**Operation Type:** Query (Read)

**Parameters:**

* **userId** `string` (required): The ID of the user whose inboxes (conversations) should be listed.
* **page** `number` (optional): The page number to retrieve. Defaults to `null`.
* **limit** `number` (optional): The maximum number of inboxes to return. Defaults to `null`.

**Returns:**

* **inboxes** `array of objects`: Inbox (conversation) objects, each with `_id`, `opportunities`, `lastActivityAt`, `channels`, `teamId`, `contactId`, `users`, `createdAt`, `haveReplies`, `lastRepliedAt`, `lastRepliedChannel`, and `contact` (with `_id`, `fullName`, `email`).
* **pagination** `object`: Pagination metadata (`total`, `page`, `limit`).

**Example:**

```json
{
  "userId": "usr_abc123",
  "page": 1,
  "limit": 50
}
```

***

### Send LinkedIn Message

Send a LinkedIn message to a lead from a Lemlist team member's connected LinkedIn account.

**Operation Type:** Mutation (Write)

**Parameters:**

* **sendUserId** `string` (required): The ID of the Lemlist team member (user) whose connected LinkedIn account will send the message.
* **leadId** `string` (required): The ID of the lead the message is being sent to.
* **contactId** `string` (required): The ID of the contact the message is being sent to.
* **message** `string` (required): The LinkedIn message content to send.

**Returns:**

* **ok** `boolean`: Whether the LinkedIn message was accepted for sending.

**Example:**

```json
{
  "sendUserId": "usr_abc123",
  "leadId": "lea_def456",
  "contactId": "con_ghi789",
  "message": "Hi Jane, I came across your profile and wanted to connect. Would love to share how we help engineering leaders like you."
}
```

***

## Lead

### Create Lead

Add a new lead to a specific Lemlist campaign. Supports standard fields plus arbitrary custom variables (via `customFields`) that become `{{merge_tags}}` in your campaign templates.

**Operation Type:** Mutation (Write)

**Parameters:**

* **campaignId** `string` (required): The ID of the campaign to add the lead to.
* **email** `string` (required): The lead's email address.
* **firstName** `string` (optional): The lead's first name.
* **lastName** `string` (optional): The lead's last name.
* **companyName** `string` (optional): The lead's company name.
* **jobTitle** `string` (optional): The lead's job title.
* **linkedinUrl** `string` (optional): The lead's LinkedIn profile URL.
* **phone** `string` (optional): The lead's phone number.
* **icebreaker** `string` (optional): A personalized icebreaker message, available as `{{icebreaker}}` in templates.
* **customFields** `object` (optional): Arbitrary custom variables to set on the lead. Each key becomes a merge tag available in templates as `{{key}}` — e.g. `{"ai_company_trigger": "...", "ai_risk_hypothesis": "..."}`. Keys that collide with standard fields (`email`, `firstName`, `companyName`, etc.) are ignored. Defaults to `null`.
* **deduplicate** `boolean` (optional): When `true`, Lemlist checks other campaigns for the email and will not insert the lead if it already exists anywhere. Defaults to `false`.

**Returns:**

* **id** `string`: The lead ID.
* **campaignId** `string`: The campaign ID.
* **campaignName** `string`: The campaign name.
* **email** `string`: The lead's email address.
* **firstName** `string` (nullable): The lead's first name.
* **lastName** `string` (nullable): The lead's last name.
* **isPaused** `boolean`: Whether the lead is paused.

**Example:**

```json
{
  "campaignId": "cam_abc123",
  "email": "jane.doe@example.com",
  "firstName": "Jane",
  "lastName": "Doe",
  "companyName": "Acme Inc",
  "jobTitle": "VP of Engineering",
  "customFields": {
    "ai_company_trigger": "Just raised Series B",
    "ai_risk_hypothesis": "Scaling engineering team rapidly"
  },
  "deduplicate": true
}
```

***

### Get Lead

Look up a lead by email address across all campaigns. Returns lead status, campaign information, and custom variables.

**Operation Type:** Query (Read)

**Parameters:**

* **email** `string` (required): The email address of the lead to look up.

**Returns:**

* **leads** `array of objects`: Lead objects with `id`, `status`, `state`, `isPaused`, `campaignId`, `campaignName`, `campaignStatus`, and `variables`.

**Example:**

```json
{
  "email": "jane.doe@example.com"
}
```

***

### Launch Lead

Launch a lead that is in review (start sending them the campaign sequence). Requires an `emailPro` plan or higher. Fails if the lead is paused, already launched, or the campaign has step errors.

**Operation Type:** Mutation (Write)

**Parameters:**

* **leadId** `string` (required): The ID of the lead to launch.

**Returns:**

* **ok** `boolean`: Whether the lead was launched.

**Example:**

```json
{
  "leadId": "lea_abc123"
}
```

***

### Skip Step

Skip a specific sequence step for a lead in a Lemlist campaign, so that step is not sent to them. Condition steps cannot be skipped.

**Operation Type:** Mutation (Write)

**Parameters:**

* **campaignId** `string` (required): The ID of the campaign the lead is in.
* **leadIdOrEmail** `string` (required): The lead's ID or email address.
* **stepId** `string` (required): The ID of the sequence step to skip for this lead. Use Get Campaign Sequences to find step IDs.

**Returns:**

* **skipped** `boolean`: Whether the step was skipped for the lead.

**Example:**

```json
{
  "campaignId": "cam_abc123",
  "leadIdOrEmail": "jane.doe@example.com",
  "stepId": "stp_def456"
}
```

***

### Update Lead Variables

Set custom variable values on an existing Lemlist lead (by lead ID), creating any variables that do not exist yet. Use this to populate personalization merge tags like `{{ai_company_trigger}}` on a lead that already exists.

**Operation Type:** Mutation (Write)

**Parameters:**

* **leadId** `string` (required): The Lemlist lead ID (e.g. `"lea_8xJSc7sV7ggpiVnXe"`), as returned by Create Lead or Get Lead.
* **variables** `object` (required): Custom variables to set on the lead as key/value pairs. Each key is a merge tag available in templates as `{{key}}`. Keys that collide with standard fields (`email`, `firstName`, `companyName`, etc.) are ignored.

**Returns:**

* **leadId** `string`: The lead ID that was updated.
* **ok** `boolean`: `true` when the update succeeded.
* **updated** `array of strings`: The variable names that were sent.

**Example:**

```json
{
  "leadId": "lea_8xJSc7sV7ggpiVnXe",
  "variables": {
    "ai_company_trigger": "Just raised a $20M Series B",
    "ai_role_relevance": "Scaling their data infrastructure team"
  }
}
```

***

## Sequence

### Add Email Step

Add an email step to a Lemlist campaign sequence. Use the `sequenceId` returned from Create Campaign to attach a subject and message to the sequence.

Plain text is accepted and automatically converted to HTML paragraphs and `<br />` tags so formatting is preserved. You may also pass HTML directly. Merge tags like `{{firstName}}` or `{{ai_company_trigger}}` work in either format.

**Operation Type:** Mutation (Write)

**Parameters:**

* **sequenceId** `string` (required): The ID of the sequence to add the email step to (the `sequenceId` returned when creating a campaign).
* **subject** `string` (required): The email subject line. Maximum 400 characters (applied to the raw template, including any Liquid syntax).
* **message** `string` (required): The body content of the email. Plain text or HTML. Merge tags work in either case.
* **index** `number` (optional): The position within the sequence to insert the step (must be `>= -1`). If omitted or greater than the number of existing steps, the step is added to the end.
* **delay** `number` (optional): Delay in days before executing this step (`0`–`1500`). Defaults to `0` for the first step and `1` for subsequent steps.

**Returns:**

* **id** `string`: The step ID.
* **type** `string`: The step type (always `"email"`).
* **delay** `number` (nullable): The delay in days before executing the step.
* **emailTemplateId** `string` (nullable): The ID of the email template created for this step.
* **message** `string` (nullable): The body content of the email.

**Example:**

```json
{
  "sequenceId": "seq_abc123",
  "subject": "Quick question about {{companyName}}'s growth",
  "message": "Hi {{firstName}},\n\nI noticed {{ai_company_trigger}}.\n\nWould love to share how we help teams like yours.\n\nBest,\nAlex",
  "delay": 0
}
```

***

### Add LinkedIn Step

Add a LinkedIn step to a Lemlist campaign sequence — connection invite, message, profile visit, follow, like/comment on last post, or withdraw invitation. Use alongside Add Email Step to build mixed email + LinkedIn cadences.

**Operation Type:** Mutation (Write)

**Parameters:**

* **sequenceId** `string` (required): The ID of the sequence to add the LinkedIn step to (the `sequenceId` returned when creating a campaign).
* **type** `string` (required): The LinkedIn action. One of:
  * `linkedinVisit` — view the prospect's profile
  * `linkedinInvite` — send a connection request (optional note via `message`)
  * `linkedinSend` — send a direct message to a connection (`message` required)
  * `linkedinFollow` — follow the prospect
  * `linkedinLikeLastPost` — like the prospect's most recent post
  * `linkedinCommentLastPost` — comment on the prospect's most recent post
  * `linkedinWithdrawInvitation` — withdraw a pending connection request
* **message** `string` (optional): The message text. Used by `linkedinInvite` (the connection note, optional — keep under \~300 chars) and `linkedinSend` (required). Plain text only. Merge tags like `{{firstName}}` work. Ignored by visit/follow/like/comment/withdraw steps. Defaults to `null`.
* **altMessage** `string` (optional): Alternate message for `linkedinSend` steps only (Lemlist A/B testing). Defaults to `null`.
* **index** `number` (optional): The position within the sequence to insert the step (must be `>= -1`). If omitted or greater than the number of existing steps, the step is added to the end. Defaults to `null`.
* **delay** `number` (optional): Delay in days before executing this step (`0`–`1500`). Defaults to `0` for the first step and `1` for subsequent steps. Defaults to `null`.

**Returns:**

* **id** `string`: The step ID.
* **type** `string`: The step type that was created.
* **delay** `number` (nullable): The delay in days before executing the step.
* **message** `string` (nullable): The message stored on the step, if any.

**Example:**

```json
{
  "sequenceId": "seq_abc123",
  "type": "linkedinInvite",
  "message": "Hi {{firstName}}, I came across your profile and thought it would be great to connect.",
  "delay": 2
}
```

***

## Common Use Cases

**Build a Full Outreach Sequence:**

* Create a campaign with Create Campaign to get the `campaignId` and `sequenceId`
* Add email steps with Add Email Step using the `sequenceId`
* Add LinkedIn touchpoints with Add LinkedIn Step for multi-channel cadences
* Add leads with Create Lead, passing custom personalization variables via `customFields`

**Enrich Prospects Before Adding Them:**

* Call Enrich with `findEmail: true` and name + company domain to discover email addresses
* Poll Get Enrichment Result until `inProgress: false` and `status: "done"`
* Use the enriched data to populate Create Lead or Upsert Contact

**Monitor Campaign Performance:**

* Use Get Campaign to check status and error state of a campaign
* Use Get Campaign Leads to see leads filtered by state (`interested`, `notInterested`, etc.)
* Use Get Activities to pull engagement events (opens, clicks, replies) by campaign or date range

**Manage Replies and Conversations:**

* Use Get Inboxes to list conversation threads for a team member
* Use Get Contact Messages to read the full message thread for a specific contact
* Use Send LinkedIn Message to respond to a lead via LinkedIn from within Cotera

**Personalize Existing Leads:**

* Look up a lead with Get Lead to confirm they exist before re-enrolling
* Set or update merge tag values with Update Lead Variables without re-creating the lead
* Use Skip Step to bypass a sequence step that's no longer relevant for a specific lead

