Référence de l'API
Clients
Clients et prospects : créer, rechercher, modifier et convertir un prospect en client.
Endpoints
-
GET
/customersLister les clients -
GET
/customers/{customer}Récupérer un client -
POST
/customersCréer un client -
PATCH
/customers/{customer}Modifier un client -
POST
/customers/{customer}/convertConvertir un prospect en client -
GET
/customers/{customer}/activitiesHistorique d'un client
Lister les clients
/api/v1/customers
Une liste de clients et de prospects, les plus récents d'abord. Filtrez par statut, type, adresse e-mail ou date de modification, recherchez avec q et naviguez avec le curseur de meta.
- Scope
-
customers.read— Lire les clients et les prospects
Paramètres de requête
| Nom | Type | Description |
|---|---|---|
limit |
integer | Nombre de résultats par page. de 1 à 100 · par défaut : 50 |
cursor |
string | Le next_cursor ou prev_cursor de meta dans la réponse précédente. |
q |
string | Recherche dans le nom, l'adresse e-mail, le nom de l'entreprise et le numéro de téléphone. au moins 2 caractères · au maximum 100 caractères |
sort |
string | Tri par created_at ou updated_at ; un signe moins devant trie par ordre décroissant. l'une des valeurs : -created_at, created_at, -updated_at, updated_at · par défaut : -created_at |
filter[status] |
string | Uniquement les prospects ou uniquement les clients. l'une des valeurs : lead, customer |
filter[type] |
string | Uniquement les particuliers ou uniquement les entreprises. l'une des valeurs : individual, business |
filter[email] |
string (email) | Exactement cette adresse e-mail (sans tenir compte des majuscules). |
filter[updated_since] |
string (date-time) | Uniquement ce qui a changé depuis ce moment : ISO 8601 avec fuseau horaire, par exemple 2026-09-14T10:15:00Z. Pratique pour synchroniser. |
Exemple de requête
curl "https://app.klantly.com/api/v1/customers?limit=50&filter[status]=lead" \
-H "Authorization: Bearer $KLANTLY_API_KEY"$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('GET', 'customers', [
'query' => [
'limit' => 50,
'filter[status]' => 'lead',
],
]);
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/customers?limit=50&filter[status]=lead', {
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
},
});
const { data } = await response.json();import os
import requests
response = requests.get(
"https://app.klantly.com/api/v1/customers",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
params={
"limit": 50,
"filter[status]": "lead"
},
)
data = response.json()["data"]Réponse 200
La réponse est une liste avec pagination par curseur : data contient les objets, meta la pagination.
{
"data": [
{
"object": "customer",
"id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"type": "business",
"status": "lead",
"name": "Jan de Vries",
"email": "jan@example.com",
"phone": "+31 6 12345678",
"company_name": "De Vries Bouw",
"vat_number": "NL123456789B01",
"coc_number": "12345678",
"address": "Dorpsstraat 1",
"postal_code": "3511 AB",
"city": "Utrecht",
"country": "NL",
"email_unsubscribed": false,
"converted_at": null,
"last_activity_at": "2026-09-14T10:15:00Z",
"created_at": "2026-09-14T10:15:00Z",
"updated_at": "2026-09-14T10:15:00Z"
}
],
"meta": {
"limit": 50,
"next_cursor": "eyJpZCI6IjlkM2Y2YzFlIn0",
"prev_cursor": null
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
422
validation_failed— Les données saisies ne sont pas valides.
Récupérer un client
/api/v1/customers/{customer}
Un seul client par id. La réponse contient un ETag que vous pouvez envoyer dans If-Match lors d'une modification.
- Scope
-
customers.read— Lire les clients et les prospects
Paramètres de chemin
| Nom | Type | Description |
|---|---|---|
customer obligatoire |
string (uuid) | L'id (UUID) du client. |
Exemple de requête
curl "https://app.klantly.com/api/v1/customers/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70" \
-H "Authorization: Bearer $KLANTLY_API_KEY"$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('GET', 'customers/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70');
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/customers/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70', {
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
},
});
const { data } = await response.json();import os
import requests
response = requests.get(
"https://app.klantly.com/api/v1/customers/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
)
data = response.json()["data"]Réponse 200
{
"data": {
"object": "customer",
"id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"type": "business",
"status": "lead",
"name": "Jan de Vries",
"email": "jan@example.com",
"phone": "+31 6 12345678",
"company_name": "De Vries Bouw",
"vat_number": "NL123456789B01",
"coc_number": "12345678",
"address": "Dorpsstraat 1",
"postal_code": "3511 AB",
"city": "Utrecht",
"country": "NL",
"email_unsubscribed": false,
"converted_at": null,
"last_activity_at": "2026-09-14T10:15:00Z",
"created_at": "2026-09-14T10:15:00Z",
"updated_at": "2026-09-14T10:15:00Z"
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
404
not_found— Introuvable.
Créer un client
/api/v1/customers
Crée un nouveau prospect. L'adresse e-mail est obligatoire et unique au sein de votre entreprise : une adresse existante renvoie une erreur de validation. Les automatisations et l'historique client fonctionnent exactement comme lors d'une création dans Klantly.
- Scope
-
customers.write— Créer et modifier les clients et les prospects
Envoyez une Idempotency-Key : une nouvelle tentative après un délai d'attente ne crée alors jamais de doublon.
Corps (JSON)
| Champ | Type | Description |
|---|---|---|
email
obligatoire
|
string (email) | Adresse e-mail ; unique au sein de votre entreprise. au maximum 255 caractères · unique au sein de votre entreprise |
type
facultatif
|
string | individual (particulier) ou business (entreprise). l'une des valeurs : individual, business |
name
facultatif
|
string | Nom de la personne de contact. peut être vide (null) · au maximum 255 caractères |
phone
facultatif
|
string | Numéro de téléphone. peut être vide (null) · au maximum 255 caractères |
address
facultatif
|
string | Rue et numéro. peut être vide (null) · au maximum 255 caractères |
city
facultatif
|
string | Ville. peut être vide (null) · au maximum 255 caractères |
postal_code
facultatif
|
string | Code postal. peut être vide (null) · au maximum 64 caractères |
country
facultatif
|
string | Pays. peut être vide (null) · au moins 2 caractères · au maximum 2 caractères |
company_name
facultatif
|
string | Nom de l'entreprise, pour un client professionnel. peut être vide (null) · au maximum 255 caractères |
vat_number
facultatif
|
string | Numéro de TVA. peut être vide (null) · au maximum 20 caractères |
coc_number
facultatif
|
string | Numéro d'immatriculation (registre du commerce). peut être vide (null) · au maximum 30 caractères |
Exemple de requête
curl -X POST "https://app.klantly.com/api/v1/customers" \
-H "Authorization: Bearer $KLANTLY_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f" \
-d '{
"email": "jan@example.com",
"name": "Jan de Vries",
"type": "business",
"company_name": "De Vries Bouw",
"city": "Utrecht"
}'$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('POST', 'customers', [
'headers' => [
'Idempotency-Key' => '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
],
'json' => [
'email' => 'jan@example.com',
'name' => 'Jan de Vries',
'type' => 'business',
'company_name' => 'De Vries Bouw',
'city' => 'Utrecht',
],
]);
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/customers', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
},
body: JSON.stringify({
"email": "jan@example.com",
"name": "Jan de Vries",
"type": "business",
"company_name": "De Vries Bouw",
"city": "Utrecht"
}),
});
const { data } = await response.json();import os
import requests
response = requests.post(
"https://app.klantly.com/api/v1/customers",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
"Idempotency-Key": "6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
},
json={
"email": "jan@example.com",
"name": "Jan de Vries",
"type": "business",
"company_name": "De Vries Bouw",
"city": "Utrecht"
},
)
data = response.json()["data"]Réponse 201
{
"data": {
"object": "customer",
"id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"type": "business",
"status": "lead",
"name": "Jan de Vries",
"email": "jan@example.com",
"phone": "+31 6 12345678",
"company_name": "De Vries Bouw",
"vat_number": "NL123456789B01",
"coc_number": "12345678",
"address": "Dorpsstraat 1",
"postal_code": "3511 AB",
"city": "Utrecht",
"country": "NL",
"email_unsubscribed": false,
"converted_at": null,
"last_activity_at": "2026-09-14T10:15:00Z",
"created_at": "2026-09-14T10:15:00Z",
"updated_at": "2026-09-14T10:15:00Z"
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
422
validation_failed— Les données saisies ne sont pas valides. -
422
unknown_field— Les données contiennent un champ inconnu. -
415
unsupported_media_type— Ce format n'est pas pris en charge. -
413
payload_too_large— Le corps de la requête est trop volumineux. -
403
limit_reached— La limite de l'abonnement est atteinte. -
422
idempotency_key_reused— Cette Idempotency-Key a déjà été utilisée pour une autre requête. -
409
idempotency_in_progress— Une requête avec cette Idempotency-Key est encore en cours.
Modifier un client
/api/v1/customers/{customer}
Modifie uniquement les champs que vous envoyez. Le statut ne change pas via cet endpoint ; utilisez pour cela « Convertir un prospect en client ».
- Scope
-
customers.write— Créer et modifier les clients et les prospects
Envoyez l'ETag dans If-Match : vous n'écraserez jamais par erreur une version plus récente.
Paramètres de chemin
| Nom | Type | Description |
|---|---|---|
customer obligatoire |
string (uuid) | L'id (UUID) du client. |
Corps (JSON)
| Champ | Type | Description |
|---|---|---|
email
facultatif
|
string (email) | Adresse e-mail ; unique au sein de votre entreprise. au maximum 255 caractères · unique au sein de votre entreprise |
type
facultatif
|
string | individual (particulier) ou business (entreprise). l'une des valeurs : individual, business |
name
facultatif
|
string | Nom de la personne de contact. peut être vide (null) · au maximum 255 caractères |
phone
facultatif
|
string | Numéro de téléphone. peut être vide (null) · au maximum 255 caractères |
address
facultatif
|
string | Rue et numéro. peut être vide (null) · au maximum 255 caractères |
city
facultatif
|
string | Ville. peut être vide (null) · au maximum 255 caractères |
postal_code
facultatif
|
string | Code postal. peut être vide (null) · au maximum 64 caractères |
country
facultatif
|
string | Pays. peut être vide (null) · au moins 2 caractères · au maximum 2 caractères |
company_name
facultatif
|
string | Nom de l'entreprise, pour un client professionnel. peut être vide (null) · au maximum 255 caractères |
vat_number
facultatif
|
string | Numéro de TVA. peut être vide (null) · au maximum 20 caractères |
coc_number
facultatif
|
string | Numéro d'immatriculation (registre du commerce). peut être vide (null) · au maximum 30 caractères |
Exemple de requête
curl -X PATCH "https://app.klantly.com/api/v1/customers/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70" \
-H "Authorization: Bearer $KLANTLY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"phone": "+31 6 12345678",
"city": "Amersfoort"
}'$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('PATCH', 'customers/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70', [
'json' => [
'phone' => '+31 6 12345678',
'city' => 'Amersfoort',
],
]);
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/customers/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"phone": "+31 6 12345678",
"city": "Amersfoort"
}),
});
const { data } = await response.json();import os
import requests
response = requests.patch(
"https://app.klantly.com/api/v1/customers/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
json={
"phone": "+31 6 12345678",
"city": "Amersfoort"
},
)
data = response.json()["data"]Réponse 200
{
"data": {
"object": "customer",
"id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"type": "business",
"status": "lead",
"name": "Jan de Vries",
"email": "jan@example.com",
"phone": "+31 6 12345678",
"company_name": "De Vries Bouw",
"vat_number": "NL123456789B01",
"coc_number": "12345678",
"address": "Dorpsstraat 1",
"postal_code": "3511 AB",
"city": "Utrecht",
"country": "NL",
"email_unsubscribed": false,
"converted_at": null,
"last_activity_at": "2026-09-14T10:15:00Z",
"created_at": "2026-09-14T10:15:00Z",
"updated_at": "2026-09-14T10:15:00Z"
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
422
validation_failed— Les données saisies ne sont pas valides. -
422
unknown_field— Les données contiennent un champ inconnu. -
415
unsupported_media_type— Ce format n'est pas pris en charge. -
413
payload_too_large— Le corps de la requête est trop volumineux. -
404
not_found— Introuvable. -
412
precondition_failed— L'enregistrement a été modifié entre-temps.
Convertir un prospect en client
/api/v1/customers/{customer}/convert
Convertit un prospect en client. S'il est déjà client, rien ne change et vous récupérez simplement le client.
- Scope
-
customers.write— Créer et modifier les clients et les prospects
Envoyez une Idempotency-Key : une nouvelle tentative après un délai d'attente ne crée alors jamais de doublon.
Paramètres de chemin
| Nom | Type | Description |
|---|---|---|
customer obligatoire |
string (uuid) | L'id (UUID) du client. |
Exemple de requête
curl -X POST "https://app.klantly.com/api/v1/customers/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/convert" \
-H "Authorization: Bearer $KLANTLY_API_KEY" \
-H "Idempotency-Key: 6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f"$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('POST', 'customers/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/convert', [
'headers' => [
'Idempotency-Key' => '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
],
]);
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/customers/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/convert', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
'Idempotency-Key': '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
},
});
const { data } = await response.json();import os
import requests
response = requests.post(
"https://app.klantly.com/api/v1/customers/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/convert",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
"Idempotency-Key": "6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
},
)
data = response.json()["data"]Réponse 200
{
"data": {
"object": "customer",
"id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"type": "business",
"status": "lead",
"name": "Jan de Vries",
"email": "jan@example.com",
"phone": "+31 6 12345678",
"company_name": "De Vries Bouw",
"vat_number": "NL123456789B01",
"coc_number": "12345678",
"address": "Dorpsstraat 1",
"postal_code": "3511 AB",
"city": "Utrecht",
"country": "NL",
"email_unsubscribed": false,
"converted_at": null,
"last_activity_at": "2026-09-14T10:15:00Z",
"created_at": "2026-09-14T10:15:00Z",
"updated_at": "2026-09-14T10:15:00Z"
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
404
not_found— Introuvable. -
422
idempotency_key_reused— Cette Idempotency-Key a déjà été utilisée pour une autre requête. -
409
idempotency_in_progress— Une requête avec cette Idempotency-Key est encore en cours.
Historique d'un client
/api/v1/customers/{customer}/activities
L'historique d'un client, le plus récent en premier : devis, factures, rendez-vous, e-mails et plus encore. Les références aux enregistrements liés figurent sous related.
- Scope
-
customers.read— Lire les clients et les prospects
Paramètres de chemin
| Nom | Type | Description |
|---|---|---|
customer obligatoire |
string (uuid) | L'id (UUID) du client. |
Paramètres de requête
| Nom | Type | Description |
|---|---|---|
limit |
integer | Nombre de résultats par page. de 1 à 100 · par défaut : 50 |
cursor |
string | Le next_cursor ou prev_cursor de meta dans la réponse précédente. |
filter[type] |
string | Uniquement les activités de ce type, par exemple quote_sent ou invoice_created. au maximum 40 caractères |
Exemple de requête
curl "https://app.klantly.com/api/v1/customers/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/activities" \
-H "Authorization: Bearer $KLANTLY_API_KEY"$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('GET', 'customers/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/activities');
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/customers/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/activities', {
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
},
});
const { data } = await response.json();import os
import requests
response = requests.get(
"https://app.klantly.com/api/v1/customers/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/activities",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
)
data = response.json()["data"]Réponse 200
La réponse est une liste avec pagination par curseur : data contient les objets, meta la pagination.
{
"data": [
{
"object": "customer_activity",
"id": "9d3f7c62-3e7a-4f9d-8c4b-5a6e7f8a9ba3",
"customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"type": "quote_sent",
"title": null,
"description": null,
"related": {
"quote_id": null,
"invoice_id": null,
"appointment_id": null,
"work_order_id": null,
"task_id": null,
"deal_id": null,
"order_id": null,
"conversation_id": null
},
"happened_at": "2026-09-14T10:15:00Z",
"created_at": "2026-09-14T10:15:00Z"
}
],
"meta": {
"limit": 50,
"next_cursor": "eyJpZCI6IjlkM2Y2YzFlIn0",
"prev_cursor": null
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
404
not_found— Introuvable. -
422
validation_failed— Les données saisies ne sont pas valides.
L'objet
Tous les champs sont toujours présents ; un champ sans valeur vaut null.
| Champ | Type | Description |
|---|---|---|
object |
string | Toujours « customer ». |
id |
string (uuid) | Id unique (UUID). |
type |
string | individual (particulier) ou business (entreprise). l'une des valeurs : individual, business |
status |
string | lead (prospect) ou customer (client). l'une des valeurs : lead, customer |
name |
string | Nom de la personne de contact. peut être vide (null) |
email |
string (email) | Adresse e-mail ; unique au sein de votre entreprise. |
phone |
string | Numéro de téléphone. peut être vide (null) |
company_name |
string | Nom de l'entreprise, pour un client professionnel. peut être vide (null) |
vat_number |
string | Numéro de TVA. peut être vide (null) |
coc_number |
string | Numéro d'immatriculation (registre du commerce). peut être vide (null) |
address |
string | Rue et numéro. peut être vide (null) |
postal_code |
string | Code postal. peut être vide (null) |
city |
string | Ville. peut être vide (null) |
country |
string | Pays. peut être vide (null) |
email_unsubscribed |
boolean | S'est désabonné des e-mails. |
converted_at |
string (date-time) | Date à laquelle le prospect est devenu client. peut être vide (null) |
last_activity_at |
string (date-time) | Dernière activité dans Klantly. peut être vide (null) |
created_at |
string (date-time) | Créé le (UTC). |
updated_at |
string (date-time) | Dernière modification le (UTC). |