New: meet Clu, and send email, LinkedIn and call steps with Sequences. Watch the videos →
API Reference (v2)
Introduction
🔌

Audience: developers. API keys need a Pro or Enterprise plan (legacy Pro and Scale plans included) or an AppSumo Tier 5, 6 or 7 license, and they never work during a trial. Support agent: confirm the user's plan grants API access before giving API advice.

TL;DR: API v2 lives at api.cleanlist.ai/api/v2. Authenticate with a clapi_ Bearer key, each call checks one OAuth scope, and paid bulk work uses a signed quote_id from POST /credits/estimate. Every response uses one envelope, and errors follow the error contract. Connecting Claude instead of writing code? Use the Cleanlist MCP.

API v2

Cleanlist API v2 is the REST API at https://api.cleanlist.ai/api/v2. People and company search return credits_charged: 0, saving leads to a list is free, and enrichment costs 1 credit per work email and 10 per direct dial, charged only when found.

This is the current API. All new integrations should target v2. The older Legacy API (v1) at /api/v1/public is still supported but frozen. See API Versions & Migration for how the two relate.

With API v2 you can search for B2B contacts and companies, enrich them through waterfall enrichment, organize them into lead lists, run smart agents, push lists to your CRM or sequencer with sync, and export the results.

It is built to be agent-friendly: every response carries the same envelope, so an LLM agent always knows where to find task_id, freshness and follow-up hints, and paid operations sit behind a signed estimate so an agent can't overspend.

API v2 and the Cleanlist MCP

The Cleanlist MCP is a connector for Claude. It signs in with your Cleanlist account (no API key to paste) and calls API v2 on your behalf. It is available on more plans than API keys: Starter, Pro, Enterprise, the Pro trial and every AppSumo tier. Use the MCP to work in Claude; use API v2 with a clapi_ key from your own code.

Base URLs

SurfaceBase URLAuth
API v2https://api.cleanlist.ai/api/v2clapi_ key or Clerk session JWT
API key managementhttps://api.cleanlist.ai/api/v1/api-keysClerk session JWT only

All requests must use HTTPS.

Authentication

Send your API key as a Bearer token:

Authorization: Bearer clapi_your_api_key_here

Create a key in the app under Settings → API keys → Create API key. Beyond the token, every endpoint checks one OAuth scope (for example enrich:write to run an enrichment). The scopes granted to your credential are listed by GET /whoami. See Authentication for the 15 scopes and key management.

The response envelope

Every entity-returning endpoint wraps its payload in the same envelope. These fields sit alongside the endpoint's own payload, and any of them may be null:

FieldTypeMeaning
task_idstringA handle for chainable follow-ups (for example, enrich a search cohort by task_id)
timestamp_msintegerServer time the response was produced (freshness marker)
agent_instructionsstringA per-call nudge for agents (credits remaining, truncation, warnings)
usagestringA "what to do next" hint, typically on empty or discovery responses
messagestringA degraded-state explanation when something was skipped

Clients that ignore unknown keys keep working as fields are added.

The error envelope

Errors raised by an endpoint use the public error envelope:

{
  "error": {
    "code": "insufficient_credits",
    "problem": "This enrich_list call requires 110 credits; organization has 40.",
    "fix": "Top up at app.cleanlist.ai/billing, or reduce the scope of the call.",
    "retryable": false,
    "docs_url": "https://docs.cleanlist.ai/errors/insufficient-credits",
    "request_id": "req_4f1c2a9b3d6e7f80",
    "estimated_cost_credits": 110,
    "available_credits": 40,
    "shortfall_credits": 70
  }
}

The fix text above is returned verbatim by the API and mentions app.cleanlist.ai/billing. That page does not exist: buy credits or change plan on the Plans page at app.cleanlist.ai/plans (opens in a new tab) (Settings → Plans & billing).

Branch on code. Authentication failures (401), plan and trial blocks (403) and rate limits (429) use a shorter generic shape with an uppercase code and a message, for example {"error": {"code": "RATE_LIMITED", "message": "..."}}. See Errors & Rate Limits for both shapes and every code.

Rate limits

LimitWindowApplies to
60 requestsper minuteper organization, all keys and members combined
30 requestsper minuteper organization, for AppSumo licenses without a paid Cleanlist plan
30 requestsper minuteper clapi_ API key
60 searchesper UTC dayper organization, POST /people/find called with API keys (all keys combined)

When you exceed a limit you get a 429 with a Retry-After header (seconds) and a RATE_LIMITED error body. See Errors & Rate Limits.

Credits and the quote model

Reads (filters, list reads, status polls, exports, whoami, balance) are free, and so is search itself. Saving leads to a list is also free; enrichment is billed separately. Paid bulk operations (bulk enrichment, by-task enrichment, smart agents, CRM and sequencer sync) require a signed quote:

  1. Call POST /credits/estimate with the operation shape. You get back a quote_id (HMAC-signed, 5-minute TTL, single use) and the estimated_cost.
  2. Pass that quote_id to the paid endpoint. The server recomputes the cost and rejects the call with spend_cap_exceeded if it would exceed the quote.

Sync calls also need approved: true, set only after a person has confirmed the push. See Credits for balances, estimates, usage reporting and the full cost table.

Quick start

A complete flow: confirm a key, estimate a bulk enrichment, run it, then poll for completion.

# 1. Create a key in the app: Settings → API keys → Create API key
 
# 2. Confirm identity, scopes, and tier
curl https://api.cleanlist.ai/api/v2/whoami \
  -H "Authorization: Bearer clapi_your_api_key"
 
# 3. Estimate a bulk enrichment over an existing list
curl -X POST https://api.cleanlist.ai/api/v2/credits/estimate \
  -H "Authorization: Bearer clapi_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"tool": "enrich_list", "list_id": "LIST_ID", "scope": "partial"}'
 
# 4. Run it with the returned quote_id
curl -X POST https://api.cleanlist.ai/api/v2/enrichment/bulk \
  -H "Authorization: Bearer clapi_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"list_id": "LIST_ID", "scope": "partial", "quote_id": "qte_v1_..."}'
 
# 5. Poll until terminal
curl https://api.cleanlist.ai/api/v2/enrichment/status/WORKFLOW_ID \
  -H "Authorization: Bearer clapi_your_api_key"
🧑‍💻

Prefer code? The same flow is a few typed lines with an official SDK: workspace.credits_estimate(...) then enrichment.enrich_list(...) then enrichment.enrichment_status(...). See the SDKs for Python, TypeScript and Java.

Endpoint index

All paths below are relative to https://api.cleanlist.ai/api/v2 unless noted. The Scope column lists the OAuth scope each endpoint checks.

Workspace and identity

MethodPathScope
GET/whoaminone (any valid credential)
GET/credits/balancecredits:read
POST/credits/estimatecredits:read
GET/api-keysadmin:api_keys
GET/usageadmin:api_keys

Search

MethodPathScope
GET/people/find/filterspeople:read
POST/people/findpeople:read
POST/people/find/compilepeople:read
POST/people/find-at-companiespeople:read
GET/people/find-at-companies/status/{task_id}people:read
GET/search/companies/filterscompanies:read
POST/search/companiescompanies:read
POST/search/companies/similarcompanies:read

Search costs 0 credits. Full reference: People Finder API and Company Search API.

Lead lists

MethodPathScope
POST/lead-listslists:write
GET/lead-listslists:read
GET/lead-lists/{list_id}lists:read
PATCH/lead-lists/{list_id}lists:write
DELETE/lead-lists/{list_id}lists:write
GET/lead-lists/{list_id}/leadslists:read
POST/lead-lists/{list_id}/leadslists:write
DELETE/lead-lists/{list_id}/leadslists:write
POST/lead-lists/{list_id}/csv-importlists:write (+ enrich:write if dispatching)
POST/lead-lists/{list_id}/find-peoplelists:write
GET/lead-lists/{list_id}/find-people/status/{workflow_id}people:read

Full reference: Lead Lists.

Enrichment

MethodPathScope
POST/enrichment/personenrich:write
POST/enrichment/companyenrich:write
POST/enrichment/by-taskenrich:write
POST/enrichment/bulkenrich:write
GET/enrichment/status/{workflow_id}enrich:read

Full reference: Enrichment.

Smart agents

MethodPathScope
POST/smart-agents/runsmart_agents:write
GET/smart-agentssmart_agents:read
GET/smart-agents/{smart_agent_task_id}smart_agents:read

Smart agents run an AI instruction over the leads in a list and write the output into a column. Pricing comes from the quote. Full reference: Smart Agents.

Sync and export

MethodPathScope
POST/migrate/crmsync:write
POST/migrate/sequencersync:write
POST/export/csv/signed-urlexport:read
GET/export/jsonexport:read

Sync pushes a list to HubSpot or Salesforce (/migrate/crm) or into a Lemlist campaign (/migrate/sequencer) at 0.2 credits per lead. See CRM & Sequencer Sync and Export.

API key management (Clerk session JWT)

MethodPath
POST/api/v1/api-keys
GET/api/v1/api-keys
POST/api/v1/api-keys/{key_id}/revoke
POST/api/v1/api-keys/revoke-all
GET/api/v1/api-keys/{key_id}/requests

What the OpenAPI spec covers

The served spec at /openapi-public-v2.json lists 30 operations. A few live endpoints are callable but not in it: POST /credits/estimate, the three company search endpoints and the two sync endpoints. They are documented on this site. The Cleanlist MCP also uses some extra v2 routes (folders, moving and filtering leads, personal email, skills, CRM record reads). Those are built for the MCP, are not available to AppSumo-only workspaces, and are not covered in this reference.

whoami

The fastest way to confirm a credential works and see what it can do:

curl https://api.cleanlist.ai/api/v2/whoami \
  -H "Authorization: Bearer clapi_your_api_key"
{
  "user_email": "y***@yourcompany.com",
  "user_id": "user_2abc...",
  "user_name": "Your Name",
  "organization_id": "org_2xyz...",
  "organization_name": "Your Company",
  "auth_type": "api_key",
  "scopes": ["people:read", "companies:read", "lists:read", "lists:write", "enrich:read", "enrich:write", "credits:read"],
  "tier": "pro",
  "appsumo_tier": null,
  "features": ["api_access", "data_source_csv_upload"],
  "timestamp_ms": 1717430400000
}

tier is one of free, starter, pro or enterprise (the legacy Scale plan reads enterprise). appsumo_tier is 1 to 7 for AppSumo workspaces, else null. For api_key auth, user_email is masked so a leaked key can't reveal the creator's full address.

Learn more