Skip to content

Leads

Base URL: https://api.klozeo.com/api/v1 Auth: X-API-Key: sk_live_... required on all requests.

Lead IDs use the prefix cl_ (e.g., cl_01234567-89ab-cdef-0123-456789abcdef). Always include the full ID with the prefix in API requests.

FieldTypeNotes
idstringFormat: cl_<uuid>. Read-only.
namestringRequired
sourcestringRequired
emailstringOptional
phonestringOptional
citystringOptional
websitestringOptional
ratingnumberOptional. Useful in scoring expressions.
tagsstring[]Optional array
scorenumber0–100. Computed via scoring rules.
source_idstringOptional. External ID used for deduplication.
created_atintegerUnix seconds. Read-only.
updated_atintegerUnix seconds. Updated only when a structural field changes.
last_interaction_atintegerUnix seconds. Updated on every push or merge.

All timestamps are Unix seconds (not milliseconds). For JavaScript: new Date(timestamp * 1000).


GET /leads
ParameterTypeDefaultDescription
filterstringRepeatable. Format: logic.operator.field.value. Example: filter=and.eq.city.Paris. See Filtering guide →
sort_bystringField to sort by
sort_orderstringASCASC or DESC
limitinteger50Max results (max: 1000)
cursorstringOpaque pagination token from previous response

Response 200 OK:

{
"leads": [{ "id": "cl_...", "name": "Acme", "source": "website", "score": 87, "..." }],
"next_cursor": "eyJpZCI6ImNsXzAxMjM...",
"has_more": true,
"count": 50
}

POST /leads

Required fields: name, source. All other fields are optional.

{
"name": "Acme Corporation",
"source": "website",
"email": "contact@acme.com",
"city": "San Francisco",
"rating": 4.5,
"tags": ["enterprise"],
"attributes": [
{ "name": "industry", "type": "text", "value": "Software" },
{ "name": "employees", "type": "number", "value": 500 }
]
}

Automatic deduplication runs before every insert. The response varies depending on the outcome:

// New lead created (201 Created)
{ "id": "cl_...", "message": "Lead created successfully", "created_at": 1703520000 }
// Duplicate detected and merged (200 OK)
{ "id": "cl_existing...", "message": "Duplicate detected, existing lead updated", "created_at": 1703520000, "duplicate": true }
// Low-confidence match — new lead created with a hint (201 Created)
{ "id": "cl_new...", "message": "Lead created successfully", "potential_duplicate_id": "cl_similar..." }

Deduplication priority:

PriorityCriterionConfidenceAction
1email match (case-insensitive)HighMerge → 200 + "duplicate": true
2source_id match (exact)HighMerge → 200 + "duplicate": true
3phone + name similarity > 80%MediumMerge → 200 + "duplicate": true
4name + city matchLowCreate + "potential_duplicate_id"

Merge strategy: Last Touch Wins — non-empty incoming fields overwrite existing. last_interaction_at is always bumped.

Error 403 when the free plan lead limit (100) is reached.


GET /leads/{id}

Response 200 OK: Full lead object (see schema above).

Error 404 if the lead does not exist or belongs to a different account.


PUT /leads/{id}

Partial update — only include fields to change. Returns the updated lead.

{ "rating": 4.8, "city": "New York", "tags": ["enterprise", "updated"] }

Error 404 if the lead does not exist or belongs to a different account.


DELETE /leads/{id}

Response 204 No Content.

Error 404 if the lead does not exist or belongs to a different account.


POST /leads/batch

⚠️ Deduplication not included Batch create skips duplicate detection for performance. If you need deduplication, use POST /leads individually or pre-deduplicate your dataset before importing.

Up to 100 leads (Free) or 500 leads (Pro) per request. Exceeding the limit returns 400 Bad Request — the entire request is rejected and no leads are created.

{
"leads": [
{ "name": "Lead 1", "source": "import", "city": "Athens" },
{ "name": "Lead 2", "source": "import", "city": "London" }
]
}

Response 201 Created (all succeeded) or 207 Multi-Status (partial failure):

207 Multi-Status means at least one lead failed. Always check the errors array, even when the request returned 207 and not a 4xx/5xx. Entries in created were saved successfully.

{
"created": [{ "index": 0, "id": "cl_...", "created_at": 1703520000 }],
"errors": [{ "index": 1, "message": "Duplicate source_id" }],
"total": 2, "success": 1, "failed": 1
}

PUT /leads/batch

Apply the same partial update to multiple leads:

{
"ids": ["cl_aaa...", "cl_bbb..."],
"data": { "category": "Technology" }
}

DELETE /leads/batch
{ "ids": ["cl_aaa...", "cl_bbb..."] }

POST /leads/{id}/score

Recalculates and persists the score for a single lead based on current scoring rules.


POST /leads/score/batch

Recalculates scores for all leads in your account.


GET /leads/export?format=csv

See the Export reference for full details.


StatusCodeDescription
400bad_requestInvalid request body or parameters (e.g., missing required fields, batch limit exceeded)
401unauthorizedMissing or invalid API key
403leads_limit_reachedFree plan lead limit reached — upgrade to Pro
404not_foundLead not found or belongs to a different account
429rate_limit_exceededRate limit exceeded — see Rate Limits
500internal_errorInternal server error