Référence de l'API
Deals
Les cartes de votre tableau de pipeline : créer, modifier, déplacer vers une autre étape, gagner, perdre et archiver.
Endpoints
-
GET
/dealsLister les deals -
GET
/deals/{deal}Récupérer un deal -
POST
/dealsCréer un deal -
PATCH
/deals/{deal}Modifier un deal -
POST
/deals/{deal}/moveDéplacer un deal -
POST
/deals/{deal}/winGagner un deal -
POST
/deals/{deal}/losePerdre un deal -
POST
/deals/{deal}/archiveArchiver un deal -
POST
/deals/{deal}/unarchiveRestaurer un deal -
POST
/deals/{deal}/labelsModifier les étiquettes d’une affaire
Lister les deals
/api/v1/deals
Une liste de deals, le plus récent en premier. Les deals archivés sont exclus par défaut ; utilisez filter[archived] pour les inclure. Filtrez par statut, étape, client, responsable ou date de modification.
- Scope
-
deals.read— Lire les affaires et les étapes du pipeline - Fonctionnalité requise
pipeline
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. |
sort
|
string | Tri par created_at ou updated_at ; un signe moins devant signifie décroissant. l'une des valeurs : -created_at, created_at, -updated_at, updated_at · par défaut : -created_at |
filter[status]
|
string | Uniquement les deals ouverts, gagnés ou perdus. l'une des valeurs : open, won, lost |
filter[stage_id]
|
string | Uniquement les deals de cette étape (l'id vient de Lister les étapes du pipeline). |
filter[customer_id]
|
string (uuid) | Uniquement ce qui appartient à ce client. |
filter[assigned_user_id]
|
string | Uniquement ce qui est assigné à cet utilisateur (l’id de Lister les utilisateurs). |
filter[archived]
|
string | false (par défaut) affiche uniquement les deals du tableau, true uniquement les deals archivés, all les deux. l'une des valeurs : false, true, all · par défaut : false |
filter[label_id]
|
string (uuid) | Uniquement les affaires avec cette étiquette (id de Lister les étiquettes). |
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. Prévoyez un chevauchement de quelques minutes avec votre moment précédent, car l'horloge de votre système et celle de Klantly ne sont pas exactement synchronisées, et car une modification juste après votre moment précédent tomberait sinon de justesse en dehors. La limite est inclusive : un élément modifié exactement à cet instant est inclus. |
Exemple de requête
curl "https://app.klantly.com/api/v1/deals?filter[status]=open" \
-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', 'deals', [
'query' => [
'filter[status]' => 'open',
],
]);
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/deals?filter[status]=open', {
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/deals",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
params={
"filter[status]": "open"
},
)
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": "deal",
"id": "9d3f7a20-1c5e-4d7b-8a2f-3e4c5d6f7a81",
"title": "Veranda 5x3 m",
"description": null,
"status": "open",
"value": "8450.00",
"currency": "EUR",
"value_source": "manual",
"stage": {
"object": "pipeline_stage",
"id": "stg_0q8v4n61h9x0zc"
},
"customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"assigned_user_id": "usr_0k3j9x21m4zq8p",
"source": "api",
"lost_reason": null,
"is_archived": false,
"labels": [
{
"object": "deal_label",
"id": "4b8e2c10-7d3a-4f6e-9a1b-2c3d4e5f6a70",
"name": "HEET",
"color": "#DC2626",
"group": "Urgentie"
}
],
"stage_changed_at": "2026-09-14T10:15:00Z",
"won_at": null,
"lost_at": null,
"archived_at": null,
"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 deal
/api/v1/deals/{deal}
Un deal par id. La réponse contient un ETag que vous pouvez envoyer dans If-Match lors d'une modification.
- Scope
-
deals.read— Lire les affaires et les étapes du pipeline - Fonctionnalité requise
pipeline
Paramètres de chemin
| Nom | Type | Description |
|---|---|---|
deal obligatoire |
string (uuid) | L'id (UUID) du deal. |
Exemple de requête
curl "https://app.klantly.com/api/v1/deals/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', 'deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70');
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/deals/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/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
)
data = response.json()["data"]Réponse 200
{
"data": {
"object": "deal",
"id": "9d3f7a20-1c5e-4d7b-8a2f-3e4c5d6f7a81",
"title": "Veranda 5x3 m",
"description": null,
"status": "open",
"value": "8450.00",
"currency": "EUR",
"value_source": "manual",
"stage": {
"object": "pipeline_stage",
"id": "stg_0q8v4n61h9x0zc"
},
"customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"assigned_user_id": "usr_0k3j9x21m4zq8p",
"source": "api",
"lost_reason": null,
"is_archived": false,
"labels": [
{
"object": "deal_label",
"id": "4b8e2c10-7d3a-4f6e-9a1b-2c3d4e5f6a70",
"name": "HEET",
"color": "#DC2626",
"group": "Urgentie"
}
],
"stage_changed_at": "2026-09-14T10:15:00Z",
"won_at": null,
"lost_at": null,
"archived_at": null,
"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 deal
/api/v1/deals
Place un client sur le tableau de pipeline. Un client ne peut avoir qu'un seul deal ouvert à la fois : s'il en a déjà un, vous recevez 409 avec son id dans deal_id. Sans stage_id, le deal arrive dans l'étape par défaut. Si vous envoyez value, Klantly conserve ce montant au lieu de le calculer à partir des devis.
- Scope
-
deals.write— Créer, modifier, déplacer et archiver les affaires - Fonctionnalité requise
pipeline
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 |
|---|---|---|
customer_id
obligatoire
|
string (uuid) | Le client du deal. |
title
facultatif
|
string | Titre du deal. peut être vide (null) · au maximum 255 caractères |
description
facultatif
|
string | Description. peut être vide (null) · au maximum 10000 caractères |
value
facultatif
|
number | Valeur sous forme de texte à deux décimales, par exemple « 8450.00 ». À la création et à la modification, vous pouvez aussi envoyer un nombre. peut être vide (null) · de 0 à 99999999 |
stage_id
facultatif
|
string | L'étape dans laquelle le deal arrive. Sans stage_id : l'étape par défaut. peut être vide (null) |
assigned_user_id
facultatif
|
string | L'utilisateur qui gère le deal, ou null. peut être vide (null) |
Exemple de requête
curl -X POST "https://app.klantly.com/api/v1/deals" \
-H "Authorization: Bearer $KLANTLY_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f" \
-d '{
"customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"title": "Veranda 5x3 m",
"value": "8450.00"
}'$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('POST', 'deals', [
'headers' => [
'Idempotency-Key' => '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
],
'json' => [
'customer_id' => '9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70',
'title' => 'Veranda 5x3 m',
'value' => '8450.00',
],
]);
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/deals', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
},
body: JSON.stringify({
"customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"title": "Veranda 5x3 m",
"value": "8450.00"
}),
});
const { data } = await response.json();import os
import requests
response = requests.post(
"https://app.klantly.com/api/v1/deals",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
"Idempotency-Key": "6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
},
json={
"customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"title": "Veranda 5x3 m",
"value": "8450.00"
},
)
data = response.json()["data"]Réponse 201
{
"data": {
"object": "deal",
"id": "9d3f7a20-1c5e-4d7b-8a2f-3e4c5d6f7a81",
"title": "Veranda 5x3 m",
"description": null,
"status": "open",
"value": "8450.00",
"currency": "EUR",
"value_source": "manual",
"stage": {
"object": "pipeline_stage",
"id": "stg_0q8v4n61h9x0zc"
},
"customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"assigned_user_id": "usr_0k3j9x21m4zq8p",
"source": "api",
"lost_reason": null,
"is_archived": false,
"labels": [
{
"object": "deal_label",
"id": "4b8e2c10-7d3a-4f6e-9a1b-2c3d4e5f6a70",
"name": "HEET",
"color": "#DC2626",
"group": "Urgentie"
}
],
"stage_changed_at": "2026-09-14T10:15:00Z",
"won_at": null,
"lost_at": null,
"archived_at": null,
"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. -
409
conflict— Ceci est en conflit avec l'état actuel. -
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 deal
/api/v1/deals/{deal}
Modifie uniquement les champs que vous envoyez. Pour changer d'étape, utilisez déplacer, gagner ou perdre. Envoyer value met value_source sur manual.
- Scope
-
deals.write— Créer, modifier, déplacer et archiver les affaires - Fonctionnalité requise
pipeline
Envoyez l'ETag dans If-Match : vous n'écraserez jamais par erreur une version plus récente.
Paramètres de chemin
| Nom | Type | Description |
|---|---|---|
deal obligatoire |
string (uuid) | L'id (UUID) du deal. |
Corps (JSON)
| Champ | Type | Description |
|---|---|---|
title
facultatif
|
string | Titre du deal. au maximum 255 caractères |
description
facultatif
|
string | Description. peut être vide (null) · au maximum 10000 caractères |
value
facultatif
|
number | Valeur sous forme de texte à deux décimales, par exemple « 8450.00 ». À la création et à la modification, vous pouvez aussi envoyer un nombre. de 0 à 99999999 |
assigned_user_id
facultatif
|
string | L'utilisateur qui gère le deal, ou null. peut être vide (null) |
Exemple de requête
curl -X PATCH "https://app.klantly.com/api/v1/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70" \
-H "Authorization: Bearer $KLANTLY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"value": "9100.00",
"assigned_user_id": "usr_0k3j9x21m4zq8p"
}'$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('PATCH', 'deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70', [
'json' => [
'value' => '9100.00',
'assigned_user_id' => 'usr_0k3j9x21m4zq8p',
],
]);
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"value": "9100.00",
"assigned_user_id": "usr_0k3j9x21m4zq8p"
}),
});
const { data } = await response.json();import os
import requests
response = requests.patch(
"https://app.klantly.com/api/v1/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
json={
"value": "9100.00",
"assigned_user_id": "usr_0k3j9x21m4zq8p"
},
)
data = response.json()["data"]Réponse 200
{
"data": {
"object": "deal",
"id": "9d3f7a20-1c5e-4d7b-8a2f-3e4c5d6f7a81",
"title": "Veranda 5x3 m",
"description": null,
"status": "open",
"value": "8450.00",
"currency": "EUR",
"value_source": "manual",
"stage": {
"object": "pipeline_stage",
"id": "stg_0q8v4n61h9x0zc"
},
"customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"assigned_user_id": "usr_0k3j9x21m4zq8p",
"source": "api",
"lost_reason": null,
"is_archived": false,
"labels": [
{
"object": "deal_label",
"id": "4b8e2c10-7d3a-4f6e-9a1b-2c3d4e5f6a70",
"name": "HEET",
"color": "#DC2626",
"group": "Urgentie"
}
],
"stage_changed_at": "2026-09-14T10:15:00Z",
"won_at": null,
"lost_at": null,
"archived_at": null,
"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.
Déplacer un deal
/api/v1/deals/{deal}/move
Déplace le deal vers une autre étape, exactement comme un glisser-déposer sur le tableau. S'il s'agit d'une étape gagnée ou perdue, le deal est lui aussi gagné ou perdu.
- Scope
-
deals.write— Créer, modifier, déplacer et archiver les affaires - Fonctionnalité requise
pipeline
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 |
|---|---|---|
deal obligatoire |
string (uuid) | L'id (UUID) du deal. |
Corps (JSON)
| Champ | Type | Description |
|---|---|---|
stage_id
obligatoire
|
string | L'id de l'étape vers laquelle le deal est déplacé (voir Lister les étapes du pipeline). |
notes
facultatif
|
string | Remarque facultative ; conservée avec le changement d'étape dans l'historique du deal. peut être vide (null) · au maximum 500 caractères |
Exemple de requête
curl -X POST "https://app.klantly.com/api/v1/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/move" \
-H "Authorization: Bearer $KLANTLY_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f" \
-d '{
"stage_id": "stg_0q8v4n61h9x0zc"
}'$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('POST', 'deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/move', [
'headers' => [
'Idempotency-Key' => '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
],
'json' => [
'stage_id' => 'stg_0q8v4n61h9x0zc',
],
]);
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/move', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
},
body: JSON.stringify({
"stage_id": "stg_0q8v4n61h9x0zc"
}),
});
const { data } = await response.json();import os
import requests
response = requests.post(
"https://app.klantly.com/api/v1/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/move",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
"Idempotency-Key": "6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
},
json={
"stage_id": "stg_0q8v4n61h9x0zc"
},
)
data = response.json()["data"]Réponse 200
{
"data": {
"object": "deal",
"id": "9d3f7a20-1c5e-4d7b-8a2f-3e4c5d6f7a81",
"title": "Veranda 5x3 m",
"description": null,
"status": "open",
"value": "8450.00",
"currency": "EUR",
"value_source": "manual",
"stage": {
"object": "pipeline_stage",
"id": "stg_0q8v4n61h9x0zc"
},
"customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"assigned_user_id": "usr_0k3j9x21m4zq8p",
"source": "api",
"lost_reason": null,
"is_archived": false,
"labels": [
{
"object": "deal_label",
"id": "4b8e2c10-7d3a-4f6e-9a1b-2c3d4e5f6a70",
"name": "HEET",
"color": "#DC2626",
"group": "Urgentie"
}
],
"stage_changed_at": "2026-09-14T10:15:00Z",
"won_at": null,
"lost_at": null,
"archived_at": null,
"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. -
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.
Gagner un deal
/api/v1/deals/{deal}/win
Déplace le deal vers l'étape que votre entreprise a définie comme gagnée. S'il est déjà gagné, rien ne change.
- Scope
-
deals.write— Créer, modifier, déplacer et archiver les affaires - Fonctionnalité requise
pipeline
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 |
|---|---|---|
deal obligatoire |
string (uuid) | L'id (UUID) du deal. |
Exemple de requête
curl -X POST "https://app.klantly.com/api/v1/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/win" \
-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', 'deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/win', [
'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/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/win', {
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/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/win",
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": "deal",
"id": "9d3f7a20-1c5e-4d7b-8a2f-3e4c5d6f7a81",
"title": "Veranda 5x3 m",
"description": null,
"status": "open",
"value": "8450.00",
"currency": "EUR",
"value_source": "manual",
"stage": {
"object": "pipeline_stage",
"id": "stg_0q8v4n61h9x0zc"
},
"customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"assigned_user_id": "usr_0k3j9x21m4zq8p",
"source": "api",
"lost_reason": null,
"is_archived": false,
"labels": [
{
"object": "deal_label",
"id": "4b8e2c10-7d3a-4f6e-9a1b-2c3d4e5f6a70",
"name": "HEET",
"color": "#DC2626",
"group": "Urgentie"
}
],
"stage_changed_at": "2026-09-14T10:15:00Z",
"won_at": null,
"lost_at": null,
"archived_at": null,
"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. -
409
invalid_state_transition— Cette action n'est pas possible dans le statut actuel. -
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.
Perdre un deal
/api/v1/deals/{deal}/lose
Déplace le deal vers l'étape que votre entreprise a définie comme perdue, avec une raison facultative.
- Scope
-
deals.write— Créer, modifier, déplacer et archiver les affaires - Fonctionnalité requise
pipeline
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 |
|---|---|---|
deal obligatoire |
string (uuid) | L'id (UUID) du deal. |
Corps (JSON)
| Champ | Type | Description |
|---|---|---|
lost_reason
facultatif
|
string | Pourquoi le deal a été perdu, ou null. peut être vide (null) · au maximum 255 caractères |
Exemple de requête
curl -X POST "https://app.klantly.com/api/v1/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/lose" \
-H "Authorization: Bearer $KLANTLY_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f" \
-d '{
"lost_reason": "Te duur"
}'$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('POST', 'deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/lose', [
'headers' => [
'Idempotency-Key' => '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
],
'json' => [
'lost_reason' => 'Te duur',
],
]);
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/lose', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
},
body: JSON.stringify({
"lost_reason": "Te duur"
}),
});
const { data } = await response.json();import os
import requests
response = requests.post(
"https://app.klantly.com/api/v1/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/lose",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
"Idempotency-Key": "6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
},
json={
"lost_reason": "Te duur"
},
)
data = response.json()["data"]Réponse 200
{
"data": {
"object": "deal",
"id": "9d3f7a20-1c5e-4d7b-8a2f-3e4c5d6f7a81",
"title": "Veranda 5x3 m",
"description": null,
"status": "open",
"value": "8450.00",
"currency": "EUR",
"value_source": "manual",
"stage": {
"object": "pipeline_stage",
"id": "stg_0q8v4n61h9x0zc"
},
"customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"assigned_user_id": "usr_0k3j9x21m4zq8p",
"source": "api",
"lost_reason": null,
"is_archived": false,
"labels": [
{
"object": "deal_label",
"id": "4b8e2c10-7d3a-4f6e-9a1b-2c3d4e5f6a70",
"name": "HEET",
"color": "#DC2626",
"group": "Urgentie"
}
],
"stage_changed_at": "2026-09-14T10:15:00Z",
"won_at": null,
"lost_at": null,
"archived_at": null,
"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. -
409
invalid_state_transition— Cette action n'est pas possible dans le statut actuel. -
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.
Archiver un deal
/api/v1/deals/{deal}/archive
Retire le deal du tableau sans le supprimer. Les deals ne peuvent pas être supprimés via l'API.
- Scope
-
deals.write— Créer, modifier, déplacer et archiver les affaires - Fonctionnalité requise
pipeline
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 |
|---|---|---|
deal obligatoire |
string (uuid) | L'id (UUID) du deal. |
Exemple de requête
curl -X POST "https://app.klantly.com/api/v1/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/archive" \
-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', 'deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/archive', [
'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/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/archive', {
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/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/archive",
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": "deal",
"id": "9d3f7a20-1c5e-4d7b-8a2f-3e4c5d6f7a81",
"title": "Veranda 5x3 m",
"description": null,
"status": "open",
"value": "8450.00",
"currency": "EUR",
"value_source": "manual",
"stage": {
"object": "pipeline_stage",
"id": "stg_0q8v4n61h9x0zc"
},
"customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"assigned_user_id": "usr_0k3j9x21m4zq8p",
"source": "api",
"lost_reason": null,
"is_archived": false,
"labels": [
{
"object": "deal_label",
"id": "4b8e2c10-7d3a-4f6e-9a1b-2c3d4e5f6a70",
"name": "HEET",
"color": "#DC2626",
"group": "Urgentie"
}
],
"stage_changed_at": "2026-09-14T10:15:00Z",
"won_at": null,
"lost_at": null,
"archived_at": null,
"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.
Restaurer un deal
/api/v1/deals/{deal}/unarchive
Remet un deal archivé sur le tableau.
- Scope
-
deals.write— Créer, modifier, déplacer et archiver les affaires - Fonctionnalité requise
pipeline
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 |
|---|---|---|
deal obligatoire |
string (uuid) | L'id (UUID) du deal. |
Exemple de requête
curl -X POST "https://app.klantly.com/api/v1/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/unarchive" \
-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', 'deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/unarchive', [
'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/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/unarchive', {
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/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/unarchive",
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": "deal",
"id": "9d3f7a20-1c5e-4d7b-8a2f-3e4c5d6f7a81",
"title": "Veranda 5x3 m",
"description": null,
"status": "open",
"value": "8450.00",
"currency": "EUR",
"value_source": "manual",
"stage": {
"object": "pipeline_stage",
"id": "stg_0q8v4n61h9x0zc"
},
"customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"assigned_user_id": "usr_0k3j9x21m4zq8p",
"source": "api",
"lost_reason": null,
"is_archived": false,
"labels": [
{
"object": "deal_label",
"id": "4b8e2c10-7d3a-4f6e-9a1b-2c3d4e5f6a70",
"name": "HEET",
"color": "#DC2626",
"group": "Urgentie"
}
],
"stage_changed_at": "2026-09-14T10:15:00Z",
"won_at": null,
"lost_at": null,
"archived_at": null,
"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.
Modifier les étiquettes d’une affaire
/api/v1/deals/{deal}/labels
Ajoute des étiquettes à l’affaire (add) ou les retire (remove). Les étiquettes d’un même groupe s’excluent : ajouter CHAUD retire PRINTEMPS. Une étiquette d’une autre entreprise donne not_found. Renvoie l’affaire avec ses nouvelles étiquettes.
- Scope
-
deals.write— Créer, modifier, déplacer et archiver les affaires - Fonctionnalité requise
pipeline
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 |
|---|---|---|
deal obligatoire |
string (uuid) | L'id (UUID) du deal. |
Corps (JSON)
| Champ | Type | Description |
|---|---|---|
add
facultatif
|
array | Ids des étiquettes à ajouter à l’affaire. |
remove
facultatif
|
array | Ids des étiquettes à retirer. |
Exemple de requête
curl -X POST "https://app.klantly.com/api/v1/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/labels" \
-H "Authorization: Bearer $KLANTLY_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f" \
-d '{
"add": [
"4b8e2c10-7d3a-4f6e-9a1b-2c3d4e5f6a70"
]
}'$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('POST', 'deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/labels', [
'headers' => [
'Idempotency-Key' => '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
],
'json' => [
'add' => [
0 => '4b8e2c10-7d3a-4f6e-9a1b-2c3d4e5f6a70',
],
],
]);
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/labels', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
},
body: JSON.stringify({
"add": [
"4b8e2c10-7d3a-4f6e-9a1b-2c3d4e5f6a70"
]
}),
});
const { data } = await response.json();import os
import requests
response = requests.post(
"https://app.klantly.com/api/v1/deals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/labels",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
"Idempotency-Key": "6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
},
json={
"add": [
"4b8e2c10-7d3a-4f6e-9a1b-2c3d4e5f6a70"
]
},
)
data = response.json()["data"]Réponse 200
{
"data": {
"object": "deal",
"id": "9d3f7a20-1c5e-4d7b-8a2f-3e4c5d6f7a81",
"title": "Veranda 5x3 m",
"description": null,
"status": "open",
"value": "8450.00",
"currency": "EUR",
"value_source": "manual",
"stage": {
"object": "pipeline_stage",
"id": "stg_0q8v4n61h9x0zc"
},
"customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"assigned_user_id": "usr_0k3j9x21m4zq8p",
"source": "api",
"lost_reason": null,
"is_archived": false,
"labels": [
{
"object": "deal_label",
"id": "4b8e2c10-7d3a-4f6e-9a1b-2c3d4e5f6a70",
"name": "HEET",
"color": "#DC2626",
"group": "Urgentie"
}
],
"stage_changed_at": "2026-09-14T10:15:00Z",
"won_at": null,
"lost_at": null,
"archived_at": null,
"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. -
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.
L'objet
Tous les champs sont toujours présents ; un champ sans valeur vaut null.
| Champ | Type | Description |
|---|---|---|
object |
string | Toujours « deal ». |
id |
string (uuid) | Id unique (UUID). |
title |
string | Titre du deal. |
description |
string | Description. peut être vide (null) |
status |
string | open (ouvert), won (gagné) ou lost (perdu) ; découle de l'étape. l'une des valeurs : open, won, lost |
value |
string | Valeur sous forme de texte à deux décimales, par exemple « 8450.00 ». À la création et à la modification, vous pouvez aussi envoyer un nombre. |
currency |
string | Toujours « EUR ». |
value_source |
string | quotes : la valeur découle des devis liés ; manual : définie à la main. l'une des valeurs : quotes, manual |
stage |
object | L'étape dans laquelle se trouve le deal ; les noms figurent dans Lister les étapes du pipeline. peut être vide (null) |
stage.object |
string | Toujours « pipeline_stage ». |
stage.id |
string | Id de l'étape. |
customer_id |
string (uuid) | Le client du deal. peut être vide (null) |
assigned_user_id |
string | L'utilisateur qui gère le deal, ou null. peut être vide (null) |
source |
string | D'où vient le deal ; via l'API, c'est api. peut être vide (null) |
lost_reason |
string | Pourquoi le deal a été perdu, ou null. peut être vide (null) |
is_archived |
boolean | Archivé : n'est plus sur le tableau. |
labels |
array<object> | Les étiquettes de l’affaire, comme CHAUD ou PROFESSIONNEL. |
labels.object |
string | Toujours "deal_label". |
labels.id |
string (uuid) | Id de l’étiquette. |
labels.name |
string | Nom de l’étiquette. |
labels.color |
string | Couleur (hex). |
labels.group |
string | Les étiquettes d’un même groupe s’excluent ; null = se combine avec tout. peut être vide (null) |
stage_changed_at |
string (date-time) | Quand le deal a changé d'étape pour la dernière fois. peut être vide (null) |
won_at |
string (date-time) | Quand le deal a été gagné. peut être vide (null) |
lost_at |
string (date-time) | Quand le deal a été perdu. peut être vide (null) |
archived_at |
string (date-time) | Quand le deal a été archivé. peut être vide (null) |
created_at |
string (date-time) | Créé le (UTC). |
updated_at |
string (date-time) | Dernière modification le (UTC). |