lemlist
# Lemlist
Interact with the Lemlist API to manage campaigns, leads, sequences, schedules, activities, inbox, webhooks, unsubscribes, exports, and enrichment.
Full endpoint reference: `references/api-endpoints.md`
Official API docs: https://developer.lemlist.com/api-reference
## Setup
### 1. Get API key
1. Log in to [Lemlist](https://app.lemlist.com)
2. Go to **Settings > Integrations > API Keys**
3. Create a new key — copy immediately, shown **only once**
### 2. Configure in OpenClaw
Add to `~/.openclaw/openclaw.json`:
```json
{
"skills": {
"entries": {
"lemlist": {
"apiKey": "your-lemlist-api-key"
}
}
}
}
```
Alternative explicit format:
```json
{
"skills": {
"entries": {
"lemlist": {
"env": {
"LEMLIST_API_KEY": "your-lemlist-api-key"
}
}
}
}
}
```
### 3. Verify
Run: `Get my Lemlist team info`
### Docker sandbox
Forward the key explicitly:
```json
{
"agents": {
"defaults": {
"sandbox": {
"docker": {
"env": ["LEMLIST_API_KEY"]
}
}
}
}
}
```
## Authentication
Base URL: `https://api.lemlist.com/api`
Basic Auth with **empty username** (colon before key is mandatory):
```
Authorization: Basic base64(:LEMLIST_API_KEY)
```
## Python Helper
Use this pattern for all API calls:
```python
import urllib.request, os, json, base64
API_KEY = os.environ["LEMLIST_API_KEY"]
AUTH = base64.b64encode(f":{API_KEY}".encode()).decode()
BASE = "https://api.lemlist.com/api"
def api(path, method="GET", data=None):
body = json.dumps(data).encode() if data else None
req = urllib.request.Request(f"{BASE}{path}", data=body, method=method)
req.add_header("Authorization", f"Basic {AUTH}")
req.add_header("User-Agent", "OpenClaw/1.0")
if data:
req.add_header("Content-Type", "application/json")
return json.load(urllib.request.urlopen(req))
```
## Endpoint Summary
| Domain | Key endpoints |
|--------|--------------|
| **Team** | GET `/team`, `/team/members`, `/team/credits`, `/team/senders` |
| **Campaigns** | GET/POST `/campaigns`, PATCH `/campaigns/:id`, POST `pause`/`start` |
| **Sequences** | GET `/campaigns/:id/sequences`, POST/PATCH/DELETE steps |
| **Leads (campaign)** | GET/POST/PATCH/DELETE `/campaigns/:id/leads/:idOrEmail` |
| **Leads (global)** | GET `/leads`, POST `pause`/`start`/`interested`/`notinterested` |
| **Lead variables** | POST/PATCH/DELETE `/leads/:id/variables` |
| **Activities** | GET `/activities` (filter: `campaignId`, `type`) |
| **Schedules** | CRUD `/schedules`, POST `/campaigns/:id/schedules` |
| **Unsubscribes** | GET `/unsubscribes`, POST/DELETE `/unsubscribes/:value` |
| **Webhooks** | GET/POST/DELETE `/hooks` (max 200/team) |
| **Inbox** | GET `/inbox`, POST `email`/`linkedin`/`whatsapp`/`sms` |
| **Inbox labels** | CRUD `/inbox/labels`, assign via `/conversations/labels/:contactId` |
| **Companies** | GET `/companies`, `/companies/:id/notes` |
| **Contacts** | GET `/contacts`, `/contacts/:idOrEmail` |
| **Exports** | GET `/campaigns/:id/export` (sync), `/export/start` (async) |
| **Enrichment** | POST `/leads/:id/enrich`, GET `/enrich/:id`, POST `/enrich` (batch) |
| **Tasks** | GET/POST/PATCH `/tasks`, POST `/tasks/ignore` |
| **Lemwarm** | POST `start`/`pause`, GET/PATCH `settings` via `/lemwarm/:mailboxId` |
For request/response details, read `references/api-endpoints.md`.
## Pagination
Params: `offset` (default 0), `limit` (max 100), `page` (1-based, overrides offset).
Paginated responses include `pagination: { totalRecords, currentPage, nextPage, totalPage }`. Some older endpoints return a plain array.
## ID Prefixes
`cam_` campaign, `lea_` lead, `skd_` schedule, `seq_` sequence, `tea_` team, `usr_` user.
## Gotchas
- **User-Agent required** — set `User-Agent: OpenClaw/1.0`, Python's default UA is blocked by Cloudflare (403)
- **Basic Auth format** — empty username mandatory: `base64(":key")`, not `base64("key")`
- **No campaign deletion** — only pause via API
- **Email encoding** — `@` → `%40` in URL path params
- **Webhook auto-deletion** — 404/410 response silently removes the webhook
- **No rate limiting** — the public API does not throttle
- **Variable deletion** — `DELETE /leads/:id/variables` deletes vars, not the lead
- **Sync vs async export** — `/export` returns CSV directly, `/export/start` + poll for large volumes
- **Limits** — 100 items/page, 200 webhooks/team, 100 API keys/team
标签
skill
ai