Leads API
Manage lead lists and individual leads. Import leads, search, export, and organize them into lists and folders.
List Lead Lists
/api/leads/listsRetrieve all lead lists for the authenticated user, newest updated first.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
search | string | Filter lists by name (case-insensitive) |
curl --location --request GET 'https://outreach.weezly.com/api/leads/lists' \
--header 'X-API-KEY: sk_live_YOUR_API_KEY'{
"lists": [
{
"id": "cm3list789abc",
"name": "SaaS Founders (West Coast)",
"description": "Founders of B2B SaaS companies in CA, WA, OR",
"userId": "user_123",
"leadCount": 245,
"folderId": null,
"folder": null,
"primarySource": "SEARCH",
"createdAt": "2026-08-01T08:00:00.000Z",
"updatedAt": "2026-08-15T14:30:00.000Z",
"campaigns": [
{
"id": "cm3camp456",
"name": "Q3 SaaS Outreach",
"status": "ACTIVE"
}
]
}
]
}Response Codes
| 200 | Lists returned successfully |
| 401 | Unauthorized |
Create Lead List
/api/leads/listsCreate a new lead list.
Request Body
| Parameter | Type | Description |
|---|---|---|
namerequired | string | Name of the lead list |
description | string | Optional description |
curl --location --request POST 'https://outreach.weezly.com/api/leads/lists' \
--header 'X-API-KEY: sk_live_YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"name": "Enterprise CTOs",
"description": "CTOs at companies with 500+ employees"
}'{
"list": {
"id": "cm3list_new123",
"name": "Enterprise CTOs",
"description": "CTOs at companies with 500+ employees",
"userId": "user_123",
"leadCount": 0,
"createdAt": "2026-08-18T10:00:00.000Z",
"updatedAt": "2026-08-18T10:00:00.000Z"
}
}Response Codes
| 201 | List created successfully |
| 400 | Name is required |
| 401 | Unauthorized |
Get Lead List
/api/leads/lists/:idGet a lead list with paginated leads. Supports free-text search, sorting, and server-side attribute filters that hold across pagination.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
search | string | Search leads by name, company, job title, headline, email, or location |
page | number | Page number (default: 1) |
limit | number | Leads per page (default: 25, max: 100) |
sortBy | string | Sort field: addedAt, fullName, company, jobTitle, email, location, createdAt (default: addedAt) |
sortOrder | string | asc or desc (default: desc) |
filters | string | URL-encoded JSON object of attribute filters, applied server-side (see below) |
idsOnly | string | Set to 1 to return only the matching lead IDs in display order, without pagination |
The filters object supports: photo, email, and phone (each "yes" or "no" for presence), connectionsMin / connectionsMax (numbers, note that LinkedIn reports at most 500), jobTitle (matches job title or headline), company, and country (a country name or 2-letter code). Example: ?filters={"email":"yes","country":"DE"} (URL-encoded).
curl --location --request GET 'https://outreach.weezly.com/api/leads/lists/:id' \
--header 'X-API-KEY: sk_live_YOUR_API_KEY'{
"list": {
"id": "cm3list789abc",
"name": "SaaS Founders (West Coast)",
"description": "Founders of B2B SaaS companies",
"leadCount": 245
},
"leads": [
{
"id": "cm3lead_001",
"firstName": "Sarah",
"lastName": "Chen",
"fullName": "Sarah Chen",
"headline": "CEO at TechStartup Inc.",
"jobTitle": "CEO",
"company": "TechStartup Inc.",
"email": "sarah@techstartup.com",
"phone": null,
"location": "San Francisco, CA",
"linkedinUrl": "https://linkedin.com/in/sarahchen",
"photoUrl": "https://media.licdn.com/...",
"connectionStatus": "UNKNOWN",
"source": "SEARCH",
"createdAt": "2026-08-01T08:00:00.000Z"
}
],
"total": 245,
"page": 1,
"totalPages": 10
}{
"ids": ["cm3lead_001", "cm3lead_002", "cm3lead_003"]
}Response Codes
| 200 | List and leads returned |
| 404 | List not found |
| 401 | Unauthorized |
Update Lead List
/api/leads/lists/:idUpdate a lead list's name, description, or folder.
Request Body
| Parameter | Type | Description |
|---|---|---|
name | string | New name for the list |
description | string | New description |
folderId | string|null | Move the list into a folder (null or empty string to unfile it). Allowed regardless of how the list is used. |
curl --location --request PATCH 'https://outreach.weezly.com/api/leads/lists/:id' \
--header 'X-API-KEY: sk_live_YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"name": "SaaS Founders (Updated)",
"folderId": "cm3folder123"
}'{
"list": {
"id": "cm3list789abc",
"name": "SaaS Founders (Updated)",
"description": "Founders of B2B SaaS companies",
"folderId": "cm3folder123",
"leadCount": 245,
"updatedAt": "2026-08-18T10:05:00.000Z"
}
}Response Codes
| 200 | List updated, returns the updated list |
| 400 | Name cannot be empty |
| 404 | List not found |
| 401 | Unauthorized |
Delete Lead List
/api/leads/lists/:idDelete a lead list and all its entries. Leads themselves are not deleted. If any campaigns use the list, the request is rejected with 400 unless you explicitly opt into deleting those campaigns too.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
deleteCampaigns | string | Set to true to also delete every campaign that uses this list. Running campaigns (ACTIVE or PAUSED) are stopped first, then deleted together with the list. Use with care, this cannot be undone. |
curl --location --request DELETE 'https://outreach.weezly.com/api/leads/lists/:id' \
--header 'X-API-KEY: sk_live_YOUR_API_KEY'{
"ok": true,
"deletedCampaigns": 0
}{
"error": "Cannot delete this list because it is used in: Q3 SaaS Outreach. Remove it from those campaigns first.",
"campaigns": ["Q3 SaaS Outreach"],
"campaignDetails": [
{ "id": "cm3camp456", "name": "Q3 SaaS Outreach", "status": "ACTIVE" }
]
}Response Codes
| 200 | List deleted (deletedCampaigns reports how many campaigns were removed with it) |
| 400 | List is used by campaigns and deleteCampaigns=true was not passed |
| 404 | List not found |
| 401 | Unauthorized |
Add Lead to List
/api/leads/lists/:id/leadsAdd a lead to the list. All fields are optional, but you should provide at least a name and a LinkedIn URL for outreach to work. If a lead with the same LinkedIn URL already exists for this user, it is linked to the list (and enriched with any new fields) instead of duplicated.
Request Body
| Parameter | Type | Description |
|---|---|---|
firstName | string | First name |
lastName | string | Last name |
fullName | string | Full name (derived from first/last name when omitted, and vice versa) |
headline | string | LinkedIn headline |
jobTitle | string | Job title |
company | string | Company name |
email | string | Email address |
phone | string | Phone number |
location | string | Location |
linkedinUrl | string | LinkedIn profile URL (normalized and used for deduplication) |
website | string | Company website URL, stored on the list entry as a "Website" custom field (used for website personalization) |
curl --location --request POST 'https://outreach.weezly.com/api/leads/lists/:id/leads' \
--header 'X-API-KEY: sk_live_YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"firstName": "Marcus",
"lastName": "Johnson",
"headline": "VP Engineering at ScaleUp",
"company": "ScaleUp Solutions",
"email": "marcus@scaleup.io",
"linkedinUrl": "https://linkedin.com/in/marcusjohnson",
"website": "https://scaleup.io"
}'{
"lead": {
"id": "cm3lead_new456",
"firstName": "Marcus",
"lastName": "Johnson",
"fullName": "Marcus Johnson",
"headline": "VP Engineering at ScaleUp",
"company": "ScaleUp Solutions",
"email": "marcus@scaleup.io",
"linkedinUrl": "https://www.linkedin.com/in/marcusjohnson",
"source": "MANUAL",
"createdAt": "2026-08-18T10:00:00.000Z"
}
}{
"lead": { "id": "cm3lead_new456", "fullName": "Marcus Johnson" },
"alreadyInList": true
}Response Codes
| 201 | Lead added to list |
| 200 | Lead already existed in this list (alreadyInList: true) |
| 404 | List not found |
| 401 | Unauthorized |
Remove Lead from List
/api/leads/lists/:id/leads/:leadIdRemove a lead from the list. The lead record itself is not deleted.
curl --location --request DELETE 'https://outreach.weezly.com/api/leads/lists/:id/leads/:leadId' \
--header 'X-API-KEY: sk_live_YOUR_API_KEY'{ "ok": true }Response Codes
| 200 | Lead removed from list |
| 404 | Lead or list not found |
| 401 | Unauthorized |
Bulk Delete Leads
/api/leads/lists/:id/leads/bulk-deleteRemove multiple leads from the list at once.
Request Body
| Parameter | Type | Description |
|---|---|---|
leadIdsrequired | string[] | Array of lead IDs to remove |
curl --location --request POST 'https://outreach.weezly.com/api/leads/lists/:id/leads/bulk-delete' \
--header 'X-API-KEY: sk_live_YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"leadIds": [
"cm3lead_001",
"cm3lead_002",
"cm3lead_003"
]
}'{ "deleted": 3 }Response Codes
| 200 | Leads removed from the list |
| 400 | No lead IDs provided |
| 404 | List not found |
Export Leads
/api/leads/lists/:id/exportExport all leads from a list as a CSV file download (not JSON). Columns: Full Name, First Name, Last Name, Headline, Job Title, Company, Email, Phone, Location, LinkedIn URL, plus one column per custom field defined on the list.
curl --location --request GET 'https://outreach.weezly.com/api/leads/lists/:id/export' \
--header 'X-API-KEY: sk_live_YOUR_API_KEY'Full Name,First Name,Last Name,Headline,Job Title,Company,Email,Phone,Location,LinkedIn URL
Sarah Chen,Sarah,Chen,CEO at TechStartup Inc.,CEO,TechStartup Inc.,sarah@techstartup.com,,"San Francisco, CA",https://linkedin.com/in/sarahchenResponse Codes
| 200 | CSV file returned |
| 404 | List not found |
| 401 | Unauthorized |
Start Email Finding
/api/leads/lists/:id/enrich-emailsStart background email finding for a list. Every lead that has a LinkedIn URL, no email yet, and has never been looked up before is checked against the email enrichment provider. Each lead is only ever looked up once, re-running the endpoint never re-checks leads that were already looked up. Poll the GET endpoint below for progress.
curl --location --request POST 'https://outreach.weezly.com/api/leads/lists/:id/enrich-emails' \
--header 'X-API-KEY: sk_live_YOUR_API_KEY'{
"started": true,
"pending": 42
}Response Codes
| 200 | Run started (started: true) or nothing left to check (started: false, pending: 0) |
| 404 | List not found |
| 503 | Background jobs are temporarily unavailable, try again shortly |
Email Finding Progress
/api/leads/lists/:id/enrich-emailsProgress counts for background email finding on a list. active is true while a run is working the list (lookups recorded in the last 90 seconds and leads still pending).
curl --location --request GET 'https://outreach.weezly.com/api/leads/lists/:id/enrich-emails' \
--header 'X-API-KEY: sk_live_YOUR_API_KEY'{
"withEmail": 120,
"pending": 30,
"checkedNoEmail": 55,
"recentlyChecked": 12,
"active": true
}Response Fields
| Parameter | Type | Description |
|---|---|---|
withEmail | number | Leads in the list that have an email |
pending | number | Leads with a LinkedIn URL, no email, and no lookup yet |
checkedNoEmail | number | Leads that were looked up but no email was found |
recentlyChecked | number | Leads looked up in the last 90 seconds |
active | boolean | Whether a run is currently working this list |
Response Codes
| 200 | Progress returned |
| 404 | List not found |
Import LinkedIn Post Reactions
/api/leads/lists/:id/import-postImport the people who reacted to a LinkedIn post into the list, one page (around 50 reactors) per call. The first call (page 1) also fetches the post itself and stores it on the list. Send increasing page values until page exceeds totalPages. Only person profiles are imported (company pages that reacted are skipped), deduplicated by LinkedIn URL.
Request Body
| Parameter | Type | Description |
|---|---|---|
urlrequired | string | The LinkedIn post URL (contains linkedin.com/posts/ or linkedin.com/feed/) |
page | number | Page number (default: 1) |
curl --location --request POST 'https://outreach.weezly.com/api/leads/lists/:id/import-post' \
--header 'X-API-KEY: sk_live_YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"url": "https://www.linkedin.com/posts/janedoe_activity-7231...",
"page": 1
}'{
"imported": 48,
"page": 1,
"totalPages": 4,
"total": 187,
"post": {
"url": "https://www.linkedin.com/posts/janedoe_activity-7231...",
"text": "Excited to announce...",
"authorName": "Jane Doe"
}
}Response Codes
| 200 | Page imported (post is only returned on page 1) |
| 400 | Missing or invalid LinkedIn post URL |
| 404 | List not found |
| 503 | Post import is not available on this deployment |
Update Lead
/api/leads/:leadIdUpdate a lead's fields. Name fields are kept consistent: providing only fullName derives first/last name, and vice versa.
Request Body
| Parameter | Type | Description |
|---|---|---|
firstName | string | First name |
lastName | string | Last name |
fullName | string | Full name |
headline | string | LinkedIn headline |
jobTitle | string | Job title |
company | string | Company name |
email | string | Email address |
phone | string | Phone number |
location | string | Location |
linkedinUrl | string|null | LinkedIn profile URL (normalized; null or empty string clears it) |
curl --location --request PATCH 'https://outreach.weezly.com/api/leads/:leadId' \
--header 'X-API-KEY: sk_live_YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"email": "sarah@newemail.com",
"jobTitle": "Founder & CEO"
}'{
"lead": {
"id": "cm3lead_001",
"firstName": "Sarah",
"lastName": "Chen",
"email": "sarah@newemail.com",
"jobTitle": "Founder & CEO",
"updatedAt": "2026-08-18T10:05:00.000Z"
}
}Response Codes
| 200 | Lead updated |
| 404 | Lead not found |
| 401 | Unauthorized |
Lead List Folders
Organize lead lists into folders. Move a list into a folder with PATCH /api/leads/lists/:id and the folderId field. Deleting a folder never deletes its lists, they just become unfiled.
List Folders
/api/lead-list-foldersRetrieve all lead list folders for the authenticated user, in display order.
curl --location --request GET 'https://outreach.weezly.com/api/lead-list-folders' \
--header 'X-API-KEY: sk_live_YOUR_API_KEY'{
"folders": [
{
"id": "cm3folder123",
"name": "Outbound Q3",
"emoji": "🚀",
"position": 0,
"_count": { "leadLists": 4 }
}
]
}Response Codes
| 200 | Folders returned |
| 401 | Unauthorized |
Create Folder
/api/lead-list-foldersCreate a new lead list folder. Folder names must be unique per user.
Request Body
| Parameter | Type | Description |
|---|---|---|
namerequired | string | Folder name |
emoji | string | Folder emoji (defaults to 📁) |
curl --location --request POST 'https://outreach.weezly.com/api/lead-list-folders' \
--header 'X-API-KEY: sk_live_YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"name": "Outbound Q3",
"emoji": "🚀"
}'{
"folder": {
"id": "cm3folder123",
"name": "Outbound Q3",
"emoji": "🚀",
"position": 0,
"_count": { "leadLists": 0 }
}
}Response Codes
| 201 | Folder created |
| 400 | Folder name is required |
| 409 | A folder with this name already exists |
Update Folder
/api/lead-list-folders/:idRename a folder or change its emoji.
Request Body
| Parameter | Type | Description |
|---|---|---|
name | string | New folder name |
emoji | string | New folder emoji |
curl --location --request PATCH 'https://outreach.weezly.com/api/lead-list-folders/:id' \
--header 'X-API-KEY: sk_live_YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"name": "Outbound Q4"
}'{ "success": true }Response Codes
| 200 | Folder updated |
| 404 | Folder not found |
| 409 | A folder with this name already exists |
Delete Folder
/api/lead-list-folders/:idDelete a folder. The lists inside it are not deleted, they become unfiled.
curl --location --request DELETE 'https://outreach.weezly.com/api/lead-list-folders/:id' \
--header 'X-API-KEY: sk_live_YOUR_API_KEY'{ "success": true }Response Codes
| 200 | Folder deleted |
| 404 | Folder not found |