Référence de l'API
Avis
Avis de clients et les demandes d'en écrire un. La lecture est complète ; créer un avis soi-même n'est volontairement pas possible — il doit venir du client.
Endpoints
-
GET
/reviewsLister les avis -
GET
/reviews/{review}Obtenir un avis -
GET
/review-requestsLister les demandes d'avis -
POST
/review-requestsEnvoyer une demande d'avis
Lister les avis
/api/v1/reviews
Une liste d'avis, du plus récent au plus ancien. Filtrez par statut, source, note, client ou date de modification. Avec filter[status]=published vous obtenez ce qui est public.
- Scope
-
reviews.read— Lire les avis et les demandes d'avis - Fonctionnalité requise
reviews
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 trie par ordre décroissant. l'une des valeurs : -reviewed_at, reviewed_at, -created_at, created_at, -updated_at, updated_at · par défaut : -reviewed_at |
filter[status]
|
string | Uniquement les avis avec ce statut : published (public) ou hidden (masqué). l'une des valeurs : published, hidden |
filter[source]
|
string | Uniquement les avis de cette source : request (via une demande d'avis), manual (saisi par l'entreprise), configurator ou google. l'une des valeurs : request, manual, configurator, google |
filter[rating]
|
integer | Uniquement les avis avec cette note (1 à 5). de 1 à 5 |
filter[customer_id]
|
string (uuid) | Uniquement ce qui appartient à ce client. |
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/reviews?filter[status]=published&sort=-reviewed_at" \
-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', 'reviews', [
'query' => [
'filter[status]' => 'published',
'sort' => '-reviewed_at',
],
]);
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/reviews?filter[status]=published&sort=-reviewed_at', {
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/reviews",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
params={
"filter[status]": "published",
"sort": "-reviewed_at"
},
)
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": "review",
"id": "9d3f9c34-8d9e-4f01-9123-c4d5e6f7a8b3",
"status": "published",
"hidden_reason": null,
"source": "request",
"rating": 5,
"comment": "Strakke veranda, netjes geplaatst en goed opgeruimd.",
"author": {
"name": "Jan de Vries",
"city": "Utrecht"
},
"customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"language": "nl",
"is_verified": true,
"consent_publish": true,
"reply": null,
"replied_at": null,
"reviewed_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.
Obtenir un avis
/api/v1/reviews/{review}
Un avis par id, avec la note, le texte, l'auteur et la réponse de l'entreprise.
- Scope
-
reviews.read— Lire les avis et les demandes d'avis - Fonctionnalité requise
reviews
Paramètres de chemin
| Nom | Type | Description |
|---|---|---|
review obligatoire |
string (uuid) | L'id (UUID) de l'avis. |
Exemple de requête
curl "https://app.klantly.com/api/v1/reviews/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', 'reviews/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70');
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/reviews/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/reviews/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
)
data = response.json()["data"]Réponse 200
{
"data": {
"object": "review",
"id": "9d3f9c34-8d9e-4f01-9123-c4d5e6f7a8b3",
"status": "published",
"hidden_reason": null,
"source": "request",
"rating": 5,
"comment": "Strakke veranda, netjes geplaatst en goed opgeruimd.",
"author": {
"name": "Jan de Vries",
"city": "Utrecht"
},
"customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"language": "nl",
"is_verified": true,
"consent_publish": true,
"reply": null,
"replied_at": null,
"reviewed_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.
Lister les demandes d'avis
/api/v1/review-requests
Les demandes d'avis envoyées et en cours, du plus récent au plus ancien, avec leur statut et le lien pour le client.
- Scope
-
reviews.read— Lire les avis et les demandes d'avis - Fonctionnalité requise
reviews
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[status]
|
string | Uniquement les demandes avec ce statut : scheduled, sent, opened, completed, failed, cancelled ou expired. l'une des valeurs : scheduled, sent, opened, completed, failed, cancelled, expired |
filter[customer_id]
|
string (uuid) | Uniquement ce qui appartient à ce client. |
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/review-requests" \
-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', 'review-requests');
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/review-requests', {
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/review-requests",
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": "review_request",
"id": "9d3f9d45-9e0f-4012-a234-d5e6f7a8b9c4",
"status": "sent",
"channel": "email",
"trigger": "manual",
"customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"recipient": {
"name": "Jan de Vries",
"email": "jan@example.com",
"phone": null
},
"language": "nl",
"url": "https://app.klantly.com/review/Xk2p9Qm4Rt7vB1nC8dE5fG3hJ6kL0mN2pQ4rS7tU",
"review_id": null,
"scheduled_at": null,
"sent_at": null,
"opened_at": null,
"completed_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.
Envoyer une demande d'avis
/api/v1/review-requests
Demande un avis à un client. Avec channel=email ou whatsapp, Klantly envoie le message avec le modèle de l'entreprise ; avec channel=link, vous créez seulement le lien et le partagez vous-même. Indiquez customer_id, ou name plus email ou phone. Les mêmes règles qu'à l'écran : pas de deuxième demande ouverte au même client, le délai d'attente de l'entreprise, et personne qui s'est désabonné — sinon vous obtenez 409 conflict.
- Scope
-
reviews.write— Envoyer des demandes d'avis aux clients (créer un avis soi-même n'est pas possible) - Fonctionnalité requise
reviews
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
facultatif
|
string (uuid) | Le client qui reçoit la demande. |
name
facultatif
|
string | Nom du destinataire. Requis si vous ne transmettez pas de customer_id. au maximum 120 caractères |
email
facultatif
|
string (email) | Adresse e-mail du destinataire. Requise pour channel=email. au maximum 255 caractères |
phone
facultatif
|
string | Numéro de téléphone du destinataire. Requis pour channel=whatsapp. au maximum 50 caractères |
channel
facultatif
|
string | Comment la demande atteint le client : email, whatsapp ou link (Klantly n'envoie alors rien). l'une des valeurs : email, whatsapp, link |
language
facultatif
|
string | La langue du message au client. l'une des valeurs : nl, en, de, fr |
Exemple de requête
curl -X POST "https://app.klantly.com/api/v1/review-requests" \
-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",
"channel": "email"
}'$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('POST', 'review-requests', [
'headers' => [
'Idempotency-Key' => '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
],
'json' => [
'customer_id' => '9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70',
'channel' => 'email',
],
]);
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/review-requests', {
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",
"channel": "email"
}),
});
const { data } = await response.json();import os
import requests
response = requests.post(
"https://app.klantly.com/api/v1/review-requests",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
"Idempotency-Key": "6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
},
json={
"customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"channel": "email"
},
)
data = response.json()["data"]Réponse 201
{
"data": {
"object": "review_request",
"id": "9d3f9d45-9e0f-4012-a234-d5e6f7a8b9c4",
"status": "sent",
"channel": "email",
"trigger": "manual",
"customer_id": "9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
"recipient": {
"name": "Jan de Vries",
"email": "jan@example.com",
"phone": null
},
"language": "nl",
"url": "https://app.klantly.com/review/Xk2p9Qm4Rt7vB1nC8dE5fG3hJ6kL0mN2pQ4rS7tU",
"review_id": null,
"scheduled_at": null,
"sent_at": null,
"opened_at": null,
"completed_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.
L'objet
Tous les champs sont toujours présents ; un champ sans valeur vaut null.
| Champ | Type | Description |
|---|---|---|
object |
string | Toujours "review". |
id |
string (uuid) | Id de l'avis. |
status |
string | published (public) ou hidden (masqué). l'une des valeurs : published, hidden |
hidden_reason |
string | Pourquoi l'avis est masqué, le cas échéant. peut être vide (null) · l'une des valeurs : spam, offensive, not_a_customer, privacy, duplicate, other |
source |
string | D'où vient l'avis : request, manual, configurator ou google. l'une des valeurs : request, manual, configurator, google |
rating |
integer | La note, de 1 à 5. de 1 à 5 |
comment |
string | Ce que le client a écrit. peut être vide (null) |
author |
object | L'auteur, tel qu'il est affiché publiquement. |
author.name |
string | Nom de l'auteur. peut être vide (null) |
author.city |
string | Ville de l'auteur. peut être vide (null) |
customer_id |
string (uuid) | Le client qui a écrit l'avis, s'il est connu. peut être vide (null) |
language |
string | La langue dans laquelle l'avis a été écrit. peut être vide (null) · l'une des valeurs : nl, en, de, fr |
is_verified |
boolean | True si l'avis a été rempli via une demande d'avis de Klantly : l'auteur est alors démontrablement client. |
consent_publish |
boolean | Si l'auteur a donné son accord pour afficher l'avis. |
reply |
string | La réponse de l'entreprise à cet avis. peut être vide (null) |
replied_at |
string (date-time) | Quand l'entreprise a répondu. peut être vide (null) |
reviewed_at |
string (date-time) | Quand l'avis a été écrit. peut être vide (null) |
created_at |
string (date-time) | Quand l'avis est arrivé dans Klantly. |
updated_at |
string (date-time) | Quand l'avis a changé pour la dernière fois. |