Reference
Lead capture
The door a person comes in through when they raise their hand (U1-1).
Capture a lead
Records that a person raised their hand, whether or not you have ever seen them before. Send what you have; the CRM decides what it means.
POST
/api/leads
This endpoint never rejects a returning person. Post the same email
twice and you get the same contact back, with contact_created: false —
where POST /api/contacts would answer 422 and drop everything you
sent. Use this one for forms, ad callbacks and automations; use
/api/contacts when you are deliberately writing a record.
Nothing you send creates schema. A key in custom_field_values that
does not match an existing custom field is not an error and does not
create a field: it is kept on the touch and listed back to you in
unmapped_keys, so a typo can never become a permanent column.
Existing data is not overwritten. Each field applies its own write
rule — most fill only when empty, attribution fields are written once and
locked. Anything refused comes back in skipped with the reason, so you
never have to guess whether your value landed.
Repeat submissions of the same form by the same person, for the same
thing, within 30 minutes count as one arrival. Send an Idempotency-Key
header to make that guarantee explicit and unbounded in time — see
Idempotency.
Body parameters
-
emailstringThe person's email. Required unless
phoneis given.Example:
ana.lopez@example.com -
phonestringThe person's phone. Required unless
emailis given. E.164 with the country code —+525555555555. A local number is only accepted together withphone_country; without either the request is rejected.Example:
+525555555555 -
phone_countrystringISO-3166-1 alpha-2, e.g.
MX. Only needed whenphonehas no+country code; ignored when it does.Example:
MX -
first_namestringExample:
Jonathan -
last_namestringExample:
Zapata -
company_namestringExample:
Klozzo -
timezonestringIANA timezone.
Example:
America/Mexico_City -
sourcestringHow they reached you, recorded once and never overwritten.
Example:
landing-verano -
intereststringWhat they asked for, in their own words. Stored as text; matched to a product only if one by that name already exists.
Example:
Paquete de firmas -
landing_pagestringThe page they arrived on.
Example:
https://klozzo.com/producto-b -
referrerstringThe referring URL.
Example:
https://example.com/blog/precios -
utmobjectCampaign parameters. Also accepted flat at the top level.
-
utm_sourcestringExample:
adwords -
utm_mediumstringExample:
ppc -
utm_campaignstringExample:
verano -
utm_termstringMust not be greater than 150 characters.
Example:
y -
utm_contentstringMust not be greater than 150 characters.
Example:
k -
gclidstringExample:
Cj0KCQjw -
fbclidstringMust not be greater than 255 characters.
Example:
m -
msclkidstringMust not be greater than 255 characters.
Example:
y
-
-
custom_field_valuesobjectValues keyed by custom field
key. Unknown keys are kept, not created.Example:
[]
curl --request POST \
"https://klozzo.com/api/leads" \
--header "Authorization: Bearer {YOUR_API_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"email\": \"ana.lopez@example.com\",
\"phone\": \"+525555555555\",
\"phone_country\": \"MX\",
\"first_name\": \"Jonathan\",
\"last_name\": \"Zapata\",
\"company_name\": \"Klozzo\",
\"timezone\": \"America\\/Mexico_City\",
\"source\": \"landing-verano\",
\"interest\": \"Paquete de firmas\",
\"landing_page\": \"https:\\/\\/klozzo.com\\/producto-b\",
\"referrer\": \"https:\\/\\/example.com\\/blog\\/precios\",
\"utm\": {
\"utm_source\": \"adwords\",
\"utm_medium\": \"ppc\",
\"utm_campaign\": \"verano\",
\"utm_term\": \"y\",
\"utm_content\": \"k\",
\"gclid\": \"Cj0KCQjw\",
\"fbclid\": \"m\",
\"msclkid\": \"y\"
},
\"custom_field_values\": []
}"
const url = new URL(
"https://klozzo.com/api/leads"
);
const headers = {
"Authorization": "Bearer {YOUR_API_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"email": "ana.lopez@example.com",
"phone": "+525555555555",
"phone_country": "MX",
"first_name": "Jonathan",
"last_name": "Zapata",
"company_name": "Klozzo",
"timezone": "America\/Mexico_City",
"source": "landing-verano",
"interest": "Paquete de firmas",
"landing_page": "https:\/\/klozzo.com\/producto-b",
"referrer": "https:\/\/example.com\/blog\/precios",
"utm": {
"utm_source": "adwords",
"utm_medium": "ppc",
"utm_campaign": "verano",
"utm_term": "y",
"utm_content": "k",
"gclid": "Cj0KCQjw",
"fbclid": "m",
"msclkid": "y"
},
"custom_field_values": []
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://klozzo.com/api/leads';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_API_TOKEN}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'json' => [
'email' => 'ana.lopez@example.com',
'phone' => '+525555555555',
'phone_country' => 'MX',
'first_name' => 'Jonathan',
'last_name' => 'Zapata',
'company_name' => 'Klozzo',
'timezone' => 'America/Mexico_City',
'source' => 'landing-verano',
'interest' => 'Paquete de firmas',
'landing_page' => 'https://klozzo.com/producto-b',
'referrer' => 'https://example.com/blog/precios',
'utm' => ['utm_source' => 'adwords', 'utm_medium' => 'ppc', 'utm_campaign' => 'verano', 'utm_term' => 'y', 'utm_content' => 'k', 'gclid' => 'Cj0KCQjw', 'fbclid' => 'm', 'msclkid' => 'y'],
'custom_field_values' => [],
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'https://klozzo.com/api/leads'
payload = {
"email": "ana.lopez@example.com",
"phone": "+525555555555",
"phone_country": "MX",
"first_name": "Jonathan",
"last_name": "Zapata",
"company_name": "Klozzo",
"timezone": "America\/Mexico_City",
"source": "landing-verano",
"interest": "Paquete de firmas",
"landing_page": "https:\/\/klozzo.com\/producto-b",
"referrer": "https:\/\/example.com\/blog\/precios",
"utm": {
"utm_source": "adwords",
"utm_medium": "ppc",
"utm_campaign": "verano",
"utm_term": "y",
"utm_content": "k",
"gclid": "Cj0KCQjw",
"fbclid": "m",
"msclkid": "y"
},
"custom_field_values": []
}
headers = {
'Authorization': 'Bearer {YOUR_API_TOKEN}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('POST', url, headers=headers, json=payload)
response.json()
{
"data": {
"contact": {
"id": "01KZ2P...",
"first_name": "Jonathan"
},
"contact_created": false,
"touch_id": "01KZ2Q...",
"applied": {
"last_name": "Zapata"
},
"skipped": {
"source": "immutable"
},
"unmapped_keys": [
"presupuesto_mensual"
]
}
}
-
dataobject-
contactobject-
idstring -
first_namestring
-
-
contact_createdboolean -
touch_idstring -
appliedobject-
last_namestring
-
-
skippedobject-
sourcestring
-
-
unmapped_keysstring[]
-
{
"message": "Hace falta al menos un correo electrónico o un teléfono para poder identificar a la persona.",
"errors": {
"email": [
"Hace falta al menos un correo electrónico o un teléfono para poder identificar a la persona."
]
}
}
Every error shares the same shape — message and errors.
See Errors.