New: API Reference docs are live — integrate Cleanlist enrichment into your apps. View API docs →
Guides
Troubleshooting

TL;DR: Check the API key, check the credit balance, check the request shape, then check GET /public/webhooks/deliveries if you're using webhooks. Most issues fall into one of those four buckets.

Troubleshooting

If something isn't working, run through this list before opening a support ticket. Most issues are one of these.

"I'm getting a 401 Unauthorized"

What it means: Cleanlist couldn't authenticate the request.

Checklist:

  1. Confirm the header is exactly Authorization: Bearer clapi_...
    • Not X-API-Key
    • Not basic auth
    • The word Bearer is required, with a space before the key
  2. Confirm the key starts with clapi_
  3. Run a sanity check:
    curl https://api.cleanlist.ai/api/v1/public/auth/validate-key \
      -H "Authorization: Bearer $CLEANLIST_API_KEY"
  4. If valid: false or 401: open the portal → Settings → API Keys and confirm the key is still active
  5. If the key was rotated, generate a fresh one

"I'm getting a 402 Payment Required"

What it means: Your organization is out of credits.

Fix: Top up in the portal (opens in a new tab) under Settings → Billing. New credits land within seconds of the Stripe payment.

curl https://api.cleanlist.ai/api/v1/public/credits/balance \
  -H "Authorization: Bearer $CLEANLIST_API_KEY"

Failed enrichments cost 0 credits, so retrying after a top-up is safe — you won't be double-charged for the rows that already succeeded.

"I'm getting a 422 Validation Error"

What it means: One or more contacts didn't pass Pydantic validation. Usually a missing field combo.

Fix: Each contact must include either:

  • linkedin_url, or
  • first_name + last_name + (company_domain or company_name)

The detail array tells you which contact index is bad:

{
  "detail": [
    {
      "loc": ["body", "contacts", 7],
      "msg": "Each contact must include linkedin_url OR ..."
    }
  ]
}

In this example, fix contacts[7].

"My bulk request is failing with 'Bulk enrichment supports up to 250 contacts per request'"

What it means: You sent more than 250 contacts.

Fix: Split the input client-side:

def chunked(iterable, size):
    for i in range(0, len(iterable), size):
        yield iterable[i:i + size]
 
for batch in chunked(all_contacts, 250):
    submit_batch(batch)

You can submit batches in parallel, but watch the rate limit.

"I submitted a workflow but never got the webhook"

What it means: Webhook delivery may have failed.

Checklist:

  1. Confirm your webhook_url is HTTPS, publicly reachable, and ACKs with 2xx within 10 seconds
  2. Query the delivery log:
    curl "https://api.cleanlist.ai/api/v1/public/webhooks/deliveries?workflow_id=$WORKFLOW_ID" \
      -H "Authorization: Bearer $CLEANLIST_API_KEY"
  3. Look at the attempt_number, status, response_status_code, and error_message fields
  4. Common reasons for failure:
    • Endpoint returned 5xx (your server bug)
    • Endpoint returned 4xx (your auth or routing rule rejected the payload)
    • Connection timed out (your endpoint took longer than 10s)
    • DNS / TLS error (URL or cert issue)
  5. Fix the endpoint and re-submit the workflow

If all 5 attempts failed, the result is still available via GET /api/v1/public/enrich/status?workflow_id=....

"My enrichment came back empty"

What it means: The waterfall ran but no provider found verified data.

Why it happens:

  • The contact is at a stealth-mode company
  • The contact is too new (LinkedIn / databases haven't indexed them yet)
  • The company domain doesn't match the contact's actual employer
  • The linkedin_url is malformed or points to a deactivated profile

Fix:

  • Try sending with a different identifier (name + company instead of LinkedIn URL, or vice versa)
  • If you're using partial, try full to engage phone providers as a backup signal
  • Check email_statusrisky results often have a working email even if it's not marked reliable

You're not charged for empty results, so retrying is free.

"I'm getting 429 Too Many Requests"

What it means: You hit a per-organization, per-endpoint rate limit.

Fix: Back off with exponential backoff + jitter:

import time, random, requests
 
def call_with_backoff(method, url, **kwargs):
    for attempt in range(6):
        r = requests.request(method, url, **kwargs)
        if r.status_code != 429:
            return r
        time.sleep(2 ** attempt + random.random())
    r.raise_for_status()

If you're hitting 429s during normal use, contact us — your plan may need a higher rate limit.

"I created an API key but I lost the secret"

What it means: Cleanlist only shows the secret once at creation, by design.

Fix: Revoke the key and generate a new one. Use a secret manager next time so you don't lose it.

# Revoke
curl -X POST "https://api.cleanlist.ai/api/v1/api-keys/$KEY_ID/revoke" \
  -H "Authorization: Bearer $CLERK_SESSION_JWT"

Or use the portal: Settings → API Keys → Revoke.

"I hit the 'maximum API keys' limit"

What it means: You already have 10 active keys and tried to create an 11th.

Fix: Revoke an unused key first (POST /api/v1/api-keys/{key_id}/revoke) or use revoke-all if you want to start fresh.

"Smart Columns are stuck on 'pending'"

What it means: The smart-columns Temporal queue is processing your job but hasn't reached your row yet.

Checklist:

  1. Open the column header menu — does it show progress (e.g., "120 / 500 done")?
  2. If progress is moving, just wait
  3. If progress is 0 and it's been more than a few minutes, refresh the page (the live update may be stuck)
  4. If still stuck after a refresh, contact support with the column id

"My Public API enrichments don't show up in any lead list"

What it means: They are in your DEFAULT lead list — you may not have noticed it.

Fix: Open the portal → Lead Lists → look for a list named DEFAULT. Every Public API enrichment lands there. See Lead Lists for the full explanation.

"My CRM push isn't working"

Checklist:

  1. Open Settings → Integrations and confirm the connection is healthy
  2. Check the field mapping for the destination object
  3. Look at the Action Column's per-row error messages — they include the destination's response
  4. Most CRM failures are auth-token expiration or required-field validation; both are visible in the error message

When to reach out to support

If you've worked through this list and you're still stuck, email support with:

  • The endpoint or feature you're using
  • The exact error message and status code
  • The workflow_id (or key_id, or column_id) involved
  • A sample request body (with secrets redacted)

We respond within one business day.

Related