TL;DR: Generate a key → confirm with /whoami → enrich a person → poll /enrichment/status/{workflow_id} → scale to bulk with an estimate quote. Copy-paste examples below.
API Quickstart
Goal: get from "no API key" to "enrichment results in hand" in under 10 minutes. The public API is base-pathed at https://api.cleanlist.ai/api/v1/public.
API access is a feature of Cleanlist's paid plans. If your plan doesn't include API access, key creation returns 403 feature_gated. (The AppSumo deal does not include API access — see the AppSumo section.)
Prerequisites
- A Cleanlist account at portal.cleanlist.ai (opens in a new tab)
- A plan that includes API access
Step 1 — Generate an API key
- Log in to portal.cleanlist.ai (opens in a new tab)
- Navigate to Settings → API Keys
- Click Generate Key, name it (e.g.
quickstart) - Copy the full key — it starts with
clapi_and is shown once
export CLEANLIST_API_KEY="clapi_your_actual_key"Step 2 — Confirm the key works
GET /whoami is free and tells you who you are, your tier, your scopes, and which features your plan includes:
curl https://api.cleanlist.ai/api/v1/public/whoami \
-H "Authorization: Bearer $CLEANLIST_API_KEY"Step 3 — Check your credit balance
curl https://api.cleanlist.ai/api/v1/public/credits/balance \
-H "Authorization: Bearer $CLEANLIST_API_KEY"Step 4 — Enrich a person
POST /enrichment/person runs asynchronously and returns a workflow_id. Identify the person with one of: email, linkedin_url, person_id, or first_name + last_name + (company_name or domain). Set enrichment_type to partial (email, 1 credit), phone_only (10 credits), or full (email + phone, 11 credits).
If you omit lead_list_id, the result lands in an auto-created per-user list named "MCP Results".
curl -X POST https://api.cleanlist.ai/api/v1/public/enrichment/person \
-H "Authorization: Bearer $CLEANLIST_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"first_name": "John",
"last_name": "Doe",
"domain": "acme.com",
"enrichment_type": "partial"
}'The response includes workflow_id, status: "pending", credits_reserved (an upfront cap — the unused portion is refunded at settle time), lead_list_id, and a poll_url.
Step 5 — Poll for the result
Poll GET /enrichment/status/{workflow_id} until the status is terminal. The response carries progress counters, the final result, and the actual credits_charged / credits_refunded.
import time
def wait_for_workflow(workflow_id, poll_seconds=5):
url = f"https://api.cleanlist.ai/api/v1/public/enrichment/status/{workflow_id}"
while True:
wf = requests.get(url, headers=HEADERS).json()
status = wf.get("status")
print(f" status={status} ({wf.get('processed', 0)}/{wf.get('total', 0)})")
if status in {"completed", "completed_with_errors", "failed"}:
return wf
time.sleep(poll_seconds)
final = wait_for_workflow(workflow_id)
print("Result:", final.get("result"))
print(f"Charged {final.get('credits_charged')}, refunded {final.get('credits_refunded')}")You're billed for results, not attempts. The credits_reserved cap is debited up front; whatever the providers don't use (e.g. no email found) is refunded when the workflow settles.
Step 6 — Scale to bulk
To enrich a whole list at once, first create/populate a list, then get a quote and run a bulk enrichment.
- Estimate the cost —
POST /credits/estimatewith{ "tool": "enrich_list", "list_id": "<id>", "scope": "partial" }returns a signedquote_id(valid ~5 minutes). - Run —
POST /enrichment/bulkwith{ "lead_list_id": "<id>", "scope": "partial", "quote_id": "<quote_id>" }. The bulk endpoint requires aquote_id. - Poll the returned
workflow_idexactly as in Step 5.
See Credits & Quotes for the estimate/quote model and Lead Lists for creating and populating lists (including CSV import).
What you've built
- ✓ A working
clapi_API key - ✓ A live identity + credit-balance check
- ✓ An async person enrichment
- ✓ A polling loop that reads results and final billing
- ✓ A path to bulk enrichment with quotes
Related
- API Reference — full endpoint reference
- Authentication & Scopes
- Polling for Results — robust async patterns
- Errors & Rate Limits
- Troubleshooting