New: API Reference docs are live — integrate Cleanlist enrichment into your apps. View API docs →
MCP API
Credits & Quotes

TL;DR: GET /credits/balance returns an integer balance. Paid bulk operations need a signed quote_id from POST /credits/estimate (5-minute TTL). Running short returns 400 insufficient_credits with exact shortfall. GET /usage reports spend over time. Reads and status polls are free.

Credits

Cleanlist bills enrichment and sync work in credits. This page covers the three credit endpoints and the full cost table.

Balance

GET /credits/balance

Scope: credits:read · Cost: free

curl https://api.cleanlist.ai/api/v1/public/credits/balance \
  -H "Authorization: Bearer clapi_your_api_key"
{
  "organization_id": "org_2xyz...",
  "credits": 4820,
  "timestamp_ms": 1717430400000,
  "agent_instructions": "You have 4820 credits remaining."
}

credits is a plain integer — the credits available to your whole organization.

Estimates & the quote model

POST /credits/estimate

Scope: credits:read · Cost: free

Pre-flight a paid operation. Returns a quote_id bound (via HMAC-SHA256) to the exact request shape — tool, list/filters, scope, row count, and your org. The quote has a 5-minute TTL. Paid bulk endpoints accept (and in some cases require) this quote_id; at execution time the server recomputes the real cost and rejects with spend_cap_exceeded if it would exceed the quote.

When you pass a list_id, the row count is always derived from the list — your row_count is ignored, so you can't under-quote a large list.

Request body

FieldTypeNotes
toolstringRequired. The operation to price (see the cost table below)
list_idstringFor list-scoped tools; row count is read from the list
row_countintegerFor non-list tools (e.g. by-task / CSV) — ignored when list_id is set
scopestringFor enrich_list: partial | full | phone-only
enrichment_typestringFor bulk_import_csv: partial | phone_only | full
agent_typestringFor run_smart_agent: e.g. custom_ai, cold_intro_email
include_phonebooleanLegacy flag for person pricing
providerstringFor sync tools
sub_actionstringFor sync_to_crm composite syncs (e.g. contacts+companies)

Response

{
  "quote_id": "qte_v1_1717430400_3f2c...e9",
  "expires_at": 1717430700,
  "estimated_cost": 110,
  "tool": "enrich_list",
  "row_count": 10,
  "filter_hash": "a1b2c3d4e5f6a7b8",
  "available_credits": 4820,
  "sufficient": true
}
FieldMeaning
quote_idPass this to the paid endpoint. Single-use within its TTL
expires_atUnix seconds; the quote is invalid after this
estimated_costCredits the operation will cost (the spend cap)
row_countRows the quote was priced for
available_creditsYour current balance
sufficienttrue if available_credits >= estimated_cost
curl -X POST https://api.cleanlist.ai/api/v1/public/credits/estimate \
  -H "Authorization: Bearer clapi_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"tool": "enrich_list", "list_id": "LIST_ID", "scope": "full"}'

Quote lifecycle

  1. Estimate → mint a quote_id for the request shape.
  2. Execute → pass quote_id to the paid endpoint. The server verifies the signature and recomputes cost.
  3. Single use → a quote can't be redeemed twice (quote_already_redeemed).
  4. Expiry → after ~5 minutes the quote is rejected (quote_expired); just re-estimate.
  5. Drift → if the actual cost exceeds the quote, you get spend_cap_exceeded — re-estimate against the current shape.

Insufficient credits

Paid operations check your balance up front. If you can't cover the cost, you get HTTP 400 with code insufficient_credits (not 402):

{
  "error": {
    "code": "insufficient_credits",
    "problem": "This enrich_person call requires 11 credits; organization has 4.",
    "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_...",
    "estimated_cost_credits": 11,
    "available_credits": 4,
    "shortfall_credits": 7
  }
}

The estimated_cost_credits, available_credits, and shortfall_credits fields tell you exactly how much to add.

Usage reports

GET /usage

Scope: admin:api_keys · Cost: free

Aggregate your organization's API request log over a window.

Query paramDefaultRange / values
days71365
group_bytooltool | key | day | error
curl "https://api.cleanlist.ai/api/v1/public/usage?days=30&group_by=tool" \
  -H "Authorization: Bearer clapi_your_api_key"
{
  "days": 30,
  "group_by": "tool",
  "total_calls": 1820,
  "total_credits_spent": 0,
  "total_errors": 12,
  "rows": [
    { "group": "/api/v1/public/enrichment/bulk", "calls": 240, "credits_spent": 0, "errors": 3 },
    { "group": "/api/v1/public/search/people", "calls": 980, "credits_spent": 0, "errors": 1 }
  ]
}

The usage log currently buckets group_by="tool" by request path, and credits_spent is reported as 0 (the request log does not yet carry a per-row credit cost). Track real spend by reading GET /credits/balance over time.

Credit cost table

Costs are computed per request and rounded up (ceiling). Reads are always free.

OperationTool name (for estimate)Cost
People searchsearch_people0.5 / lead (deferred to enrich/save)
Company searchsearch_companies0.5 / lead (deferred to enrich/save)
Similar companiesfind_similar_companies1 / call
Person enrichment — email onlyenrich_person (partial)1
Person enrichment — phone onlyenrich_person (phone_only)10
Person enrichment — fullenrich_person (full)11
Company enrichmentenrich_company1
Bulk list enrichment — partialenrich_list (partial)1 / lead
Bulk list enrichment — fullenrich_list (full)11 / lead
Bulk list enrichment — phone onlyenrich_list (phone-only)10 / lead
CSV importbulk_import_csv0 import + per-lead enrich (partial 1 / phone_only 10 / full 11)
Smart agent — custom AIrun_smart_agent (custom_ai)1 / lead
Smart agent — cold intro emailrun_smart_agent (cold_intro_email)3 / lead
Sync to CRMsync_to_crm0.2 / lead
Sync to sequencersync_to_sequencer0.2 / lead
whoami, balance, estimate, list reads, status polls, exportsfree

Failed enrichments are not charged for data that wasn't found. Async enrichments reserve the estimated credits up front and refund the unused portion when the workflow settles — see Enrichment for the reservation model.

Learn more