/openapi.yaml
#
Cette spécification
public, sans jeton
Réponses
- 200 Spécification OpenAPI 3.1 (YAML)
curl "https://clientzen.fr/api/v1/openapi.yaml" \
-H "Accept: application/json"Développeurs
Branchez ClientZen sur votre site, votre boutique ou vos outils internes : clients, catalogue, devis, factures (création et émission), encaissements, rendez-vous et webhooks signés. L'API applique exactement les règles de l'interface — validation, quotas de l'offre, numérotation figée des factures.
https://clientzen.fr/api/v1
GET /me renvoie votre espace et les portées du jeton. L'espace est déduit du jeton : aucun identifiant d'espace à transmettre.curl "https://clientzen.fr/api/v1/me" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json"<?php
require 'ClientZenClient.php';
$cz = new ClientZenClient(getenv('CLIENTZEN_TOKEN'));
$me = $cz->get('/me');
echo $me['data']['tenant']['name'];// Node 18+ (fetch natif)
import { ClientZen } from './clientzen.mjs';
const cz = new ClientZen(process.env.CLIENTZEN_TOKEN);
const { data } = await cz.get('/me');
console.log(data.tenant.name, data.token.scopes);import os
from clientzen import ClientZen
cz = ClientZen(os.environ["CLIENTZEN_TOKEN"])
me = cz.get("/me")
print(me["data"]["tenant"]["name"])Chaque requête porte l'en-tête Authorization: Bearer czk_…. Le jeton est haché chez nous, révocable et expirable depuis votre espace ; créez un jeton par intégration et nommez-le. Une portée manquante renvoie 403 avec le champ required_scope.
| Portée | Autorise |
|---|---|
customers:read | Lire les clients |
customers:write | Créer et modifier des clients |
products:read | Lire le catalogue |
quotes:read | Lire les devis |
invoices:read | Lire les factures (dont PDF) |
invoices:write | Créer des brouillons de facture et les émettre |
payments:read | Lire les encaissements |
appointments:read | Lire les services, disponibilités et rendez-vous |
appointments:write | Créer et annuler des rendez-vous |
knowledge:read | Lire les articles publiés de la base de connaissance |
chat:read | Lire les conversations du tchat |
chat:write | Répondre aux visiteurs du tchat et clore une conversation |
webhooks:manage | Abonner Zapier, Make ou n8n aux événements (webhooks gérés par ce jeton) |
/api/* pour les outils de développement, pas pour exposer un jeton.
Entiers en centimes (total_incl_cents: 12000 = 120,00 €), avec le code devise. Aucun nombre à virgule flottante.
ISO 8601. Horodatages en UTC (2026-09-28T10:00:00+00:00), dates métier sans heure (2026-09-28).
ULID de 26 caractères, non prévisibles. Une ressource d'un autre espace répond 404, jamais 403.
page et per_page (≤ 100). Réponse { data, meta: { page, per_page, total, last_page }, links: { next, prev } }.
Sur les créations, envoyez Idempotency-Key (≤ 128 caractères). Une réémission renvoie la première réponse avec Idempotent-Replayed: true : aucun doublon, même après une coupure réseau.
120 requêtes par minute et par jeton (en-têtes X-RateLimit-Limit et X-RateLimit-Remaining ; au-delà, 429 et Retry-After). X-Request-Id est renvoyé dans chaque réponse : citez-le au support.
Toutes les erreurs sont en application/problem+json (RFC 9457).
| Code | Signification |
|---|---|
401 | Jeton absent, invalide, révoqué ou expiré. |
403 | Portée manquante, ou module API non inclus dans l'offre de l'espace. |
404 | Ressource inexistante — ou appartenant à un autre espace. |
409 | Règle métier : quota atteint, facture déjà émise, créneau déjà pris, chronologie de numérotation. |
422 | Données invalides ; le détail par champ est dans errors. |
429 | Débit dépassé ; attendez la durée de Retry-After. |
500 | Erreur de notre côté, sans trace technique ; citez request_id. |
{
"type": "https://clientzen.fr/developpeurs#erreurs",
"title": "Données invalides",
"status": 422,
"detail": "Le champ name est obligatoire.",
"request_id": "7f3c2a9e-5b1d-4c8e-9a2f-0e1d2c3b4a59",
"errors": {
"name": [
"Le champ name est obligatoire."
]
},
"required_scope": "customers:write",
"required_permission": "chat.reply"
}Vérifier le jeton et l'espace auquel il donne accès.
/openapi.yaml
#
public, sans jeton
curl "https://clientzen.fr/api/v1/openapi.yaml" \
-H "Accept: application/json"/me
#
Le moyen le plus simple de vérifier un jeton : renvoie l'espace et les portées accordées.
curl "https://clientzen.fr/api/v1/me" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json"{
"data": {
"tenant": {
"id": "01k2m7q9x4v8b3n6c1d5f0g2h7",
"name": "Atelier Martin",
"slug": "atelier-martin"
},
"token": {
"id": "01k2m8a1b2c3d4e5f6g7h8j9k0",
"name": "Site vitrine",
"scopes": [
"customers:read",
"customers:write"
],
"expires_at": null
}
}
}Clients et prospects de l'espace : lecture, recherche, création, modification.
/customers
#
portée customers:read
Recherche par nom, e-mail ou SIREN (`q`) ; `updated_since` pour une synchronisation incrémentale.
| Nom | Où | Type | Description |
|---|---|---|---|
page | requête | integer | Numéro de page (1 par défaut) |
per_page | requête | integer | Éléments par page (25 par défaut, 100 au plus) |
q | requête | string | Recherche (nom, e-mail, SIREN) |
updated_since | requête | string (date-time) | Modifiés depuis (ISO 8601) |
curl "https://clientzen.fr/api/v1/customers" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json"{
"data": [
{
"id": "01k2m9c3d4e5f6g7h8j9k0m1n2",
"type": "company",
"name": "Boulangerie Petit",
"siren": "552100554",
"vat_number": "FR40552100554",
"vat_status": "taxable",
"email": "contact@boulangerie-petit.fr",
"phone": "+33 3 88 00 00 00",
"website": "https://boulangerie-petit.fr",
"is_prospect": false,
"is_supplier": false,
"tags": [
"site-web"
],
"custom_fields": [],
"addresses": [
{
"kind": "billing",
"line1": "12 rue des Fours",
"line2": null,
"postal_code": "67000",
"city": "Strasbourg",
"country": "FR",
"is_default": true
}
],
"created_at": "2026-09-28T10:00:00+00:00",
"updated_at": "2026-09-28T10:00:00+00:00"
}
],
"meta": {
"page": 1,
"per_page": 25,
"total": 42,
"last_page": 2
},
"links": {
"next": "https://clientzen.fr/api/v1/customers?page=2",
"prev": null
}
}/customers
#
portée customers:write Idempotency-Key
Idempotent avec `Idempotency-Key`. Le quota de clients de l'offre s'applique (409 s'il est atteint).
| Nom | Où | Type | Description |
|---|---|---|---|
Idempotency-Key | en-tête | string | Clé propre à votre opération : la première réponse est rejouée à l'identique |
| Champ | Type | Description |
|---|---|---|
type* | string | Valeurs : company, individual |
name* | string | ex. Boulangerie Petit |
siren | string | 9 chiffres, clé de Luhn vérifiée ex. 552100554 |
vat_number | string | ex. FR40552100554 |
vat_status | string | Valeurs : taxable, non_taxable, public |
email | string (email) | ex. contact@boulangerie-petit.fr |
phone | string | ex. +33 3 88 00 00 00 |
website | string (uri) | ex. https://boulangerie-petit.fr |
is_prospect | boolean | ex. true |
is_supplier | boolean | ex. false |
tags | array<string> | |
notes | string | ex. Demande reçue par le formulaire du site. |
address | object | |
address.line1 | string | ex. 12 rue des Fours |
address.line2 | string | |
address.postal_code | string | ex. 67000 |
address.city | string | ex. Strasbourg |
address.country | string | ex. FR |
curl -X POST "https://clientzen.fr/api/v1/customers" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"type":"company","name":"Boulangerie Petit","siren":"552100554","vat_number":"FR40552100554","email":"contact@boulangerie-petit.fr","phone":"+33 3 88 00 00 00","website":"https://boulangerie-petit.fr","is_prospect":true,"is_supplier":false,"tags":["site-web"],"notes":"Demande reçue par le formulaire du site.","address":{"line1":"12 rue des Fours","postal_code":"67000","city":"Strasbourg","country":"FR"}}'{
"data": {
"id": "01k2m9c3d4e5f6g7h8j9k0m1n2",
"type": "company",
"name": "Boulangerie Petit",
"siren": "552100554",
"vat_number": "FR40552100554",
"vat_status": "taxable",
"email": "contact@boulangerie-petit.fr",
"phone": "+33 3 88 00 00 00",
"website": "https://boulangerie-petit.fr",
"is_prospect": false,
"is_supplier": false,
"tags": [
"site-web"
],
"custom_fields": [],
"addresses": [
{
"kind": "billing",
"line1": "12 rue des Fours",
"line2": null,
"postal_code": "67000",
"city": "Strasbourg",
"country": "FR",
"is_default": true
}
],
"created_at": "2026-09-28T10:00:00+00:00",
"updated_at": "2026-09-28T10:00:00+00:00"
}
}/customers/{id}
#
portée customers:read
| Nom | Où | Type | Description |
|---|---|---|---|
id* | chemin | string | Identifiant (ULID) |
curl "https://clientzen.fr/api/v1/customers/01k2md6h7j8k9m0n1p2q3r4s5t" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json"{
"data": {
"id": "01k2m9c3d4e5f6g7h8j9k0m1n2",
"type": "company",
"name": "Boulangerie Petit",
"siren": "552100554",
"vat_number": "FR40552100554",
"vat_status": "taxable",
"email": "contact@boulangerie-petit.fr",
"phone": "+33 3 88 00 00 00",
"website": "https://boulangerie-petit.fr",
"is_prospect": false,
"is_supplier": false,
"tags": [
"site-web"
],
"custom_fields": [],
"addresses": [
{
"kind": "billing",
"line1": "12 rue des Fours",
"line2": null,
"postal_code": "67000",
"city": "Strasbourg",
"country": "FR",
"is_default": true
}
],
"created_at": "2026-09-28T10:00:00+00:00",
"updated_at": "2026-09-28T10:00:00+00:00"
}
}/customers/{id}
#
portée customers:write
Seuls les champs envoyés sont modifiés.
| Nom | Où | Type | Description |
|---|---|---|---|
id* | chemin | string | Identifiant (ULID) |
| Champ | Type | Description |
|---|---|---|
type* | string | Valeurs : company, individual |
name* | string | ex. Boulangerie Petit |
siren | string | 9 chiffres, clé de Luhn vérifiée ex. 552100554 |
vat_number | string | ex. FR40552100554 |
vat_status | string | Valeurs : taxable, non_taxable, public |
email | string (email) | ex. contact@boulangerie-petit.fr |
phone | string | ex. +33 3 88 00 00 00 |
website | string (uri) | ex. https://boulangerie-petit.fr |
is_prospect | boolean | ex. true |
is_supplier | boolean | ex. false |
tags | array<string> | |
notes | string | ex. Demande reçue par le formulaire du site. |
address | object | |
address.line1 | string | ex. 12 rue des Fours |
address.line2 | string | |
address.postal_code | string | ex. 67000 |
address.city | string | ex. Strasbourg |
address.country | string | ex. FR |
curl -X PATCH "https://clientzen.fr/api/v1/customers/01k2md6h7j8k9m0n1p2q3r4s5t" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"type":"company","name":"Boulangerie Petit","siren":"552100554","vat_number":"FR40552100554","email":"contact@boulangerie-petit.fr","phone":"+33 3 88 00 00 00","website":"https://boulangerie-petit.fr","is_prospect":true,"is_supplier":false,"tags":["site-web"],"notes":"Demande reçue par le formulaire du site.","address":{"line1":"12 rue des Fours","postal_code":"67000","city":"Strasbourg","country":"FR"}}'{
"data": {
"id": "01k2m9c3d4e5f6g7h8j9k0m1n2",
"type": "company",
"name": "Boulangerie Petit",
"siren": "552100554",
"vat_number": "FR40552100554",
"vat_status": "taxable",
"email": "contact@boulangerie-petit.fr",
"phone": "+33 3 88 00 00 00",
"website": "https://boulangerie-petit.fr",
"is_prospect": false,
"is_supplier": false,
"tags": [
"site-web"
],
"custom_fields": [],
"addresses": [
{
"kind": "billing",
"line1": "12 rue des Fours",
"line2": null,
"postal_code": "67000",
"city": "Strasbourg",
"country": "FR",
"is_default": true
}
],
"created_at": "2026-09-28T10:00:00+00:00",
"updated_at": "2026-09-28T10:00:00+00:00"
}
}Produits et prestations, avec leur prix hors taxe et leur code de TVA.
/products
#
portée products:read
| Nom | Où | Type | Description |
|---|---|---|---|
page | requête | integer | Numéro de page (1 par défaut) |
per_page | requête | integer | Éléments par page (25 par défaut, 100 au plus) |
curl "https://clientzen.fr/api/v1/products" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json"{
"data": [
{
"id": "01k2mb4f5g6h7j8k9m0n1p2q3r",
"sku": "POSE-01",
"name": "Pose de parquet",
"description": "Pose flottante, fournitures non comprises.",
"type": "goods",
"unit_code": "m2",
"unit_price": "45.000000",
"currency": "EUR",
"tax_code": "FR_STANDARD",
"updated_at": "2026-09-28T10:00:00+00:00"
}
],
"meta": {
"page": 1,
"per_page": 25,
"total": 42,
"last_page": 2
},
"links": {
"next": "https://clientzen.fr/api/v1/customers?page=2",
"prev": null
}
}/products/{id}
#
portée products:read
| Nom | Où | Type | Description |
|---|---|---|---|
id* | chemin | string | Identifiant (ULID) |
curl "https://clientzen.fr/api/v1/products/01k2md6h7j8k9m0n1p2q3r4s5t" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json"{
"data": {
"id": "01k2mb4f5g6h7j8k9m0n1p2q3r",
"sku": "POSE-01",
"name": "Pose de parquet",
"description": "Pose flottante, fournitures non comprises.",
"type": "goods",
"unit_code": "m2",
"unit_price": "45.000000",
"currency": "EUR",
"tax_code": "FR_STANDARD",
"updated_at": "2026-09-28T10:00:00+00:00"
}
}/customers/{id}/prices
#
portée products:read
Tarif négocié applicable (groupe du client, règle propre au client, palier de quantité, à la date demandée), ou prix du catalogue s'il n'y en a pas. Le prix catalogue est conservé ; la remise est donnée en % (`discount_percent_e2`) ou en montant de ligne (`discount_amount_cents`), exactement comme sur une ligne de facture.
| Nom | Où | Type | Description |
|---|---|---|---|
id* | chemin | string | Identifiant (ULID) |
product_id* | requête | string | |
quantity | requête | string | |
date | requête | string (date) |
curl "https://clientzen.fr/api/v1/customers/01k2md6h7j8k9m0n1p2q3r4s5t/prices?product_id=VALEUR" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json"{
"data": {
"customer_id": "texte",
"product_id": "texte",
"quantity": "10",
"catalog_unit_price": "49",
"unit_price": "49",
"net_unit_price": "41.65",
"discount_percent_e2": 1500,
"discount_amount_cents": 0,
"rule_id": "texte",
"label": "Tarif Revendeurs : −15 %"
}
}Devis de l'espace, en lecture.
/quotes
#
portée quotes:read
| Nom | Où | Type | Description |
|---|---|---|---|
page | requête | integer | Numéro de page (1 par défaut) |
per_page | requête | integer | Éléments par page (25 par défaut, 100 au plus) |
status | requête | string | |
customer_id | requête | string |
curl "https://clientzen.fr/api/v1/quotes" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json"{
"data": [
{
"id": "01k2mc5g6h7j8k9m0n1p2q3r4s",
"number": "DEV-2026-0042",
"status": "draft",
"customer_id": "texte",
"customer_name": "Boulangerie Petit",
"title": "Rénovation de la boutique",
"total_excl_cents": 250000,
"total_tax_cents": 50000,
"total_incl_cents": 300000,
"currency": "EUR",
"valid_until": "2026-10-28",
"created_at": "2026-09-28T10:00:00+00:00"
}
],
"meta": {
"page": 1,
"per_page": 25,
"total": 42,
"last_page": 2
},
"links": {
"next": "https://clientzen.fr/api/v1/customers?page=2",
"prev": null
}
}/quotes/{id}
#
portée quotes:read
| Nom | Où | Type | Description |
|---|---|---|---|
id* | chemin | string | Identifiant (ULID) |
curl "https://clientzen.fr/api/v1/quotes/01k2md6h7j8k9m0n1p2q3r4s5t" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json"{
"data": {
"id": "01k2mc5g6h7j8k9m0n1p2q3r4s",
"number": "DEV-2026-0042",
"status": "draft",
"customer_id": "texte",
"customer_name": "Boulangerie Petit",
"title": "Rénovation de la boutique",
"total_excl_cents": 250000,
"total_tax_cents": 50000,
"total_incl_cents": 300000,
"currency": "EUR",
"valid_until": "2026-10-28",
"created_at": "2026-09-28T10:00:00+00:00"
}
}Brouillons, émission (numéro définitif, irréversible), PDF. Mêmes règles que l'interface : validation, quotas, numérotation.
/companies
#
portée invoices:read
Avec le code de TVA à utiliser par défaut pour chacune (`default_tax_code`) : FRANCHISE_293B pour une société en franchise en base (art. 293 B du CGI), FR_STANDARD sinon.
curl "https://clientzen.fr/api/v1/companies" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json"{
"data": [
{
"id": "texte",
"name": "Atelier Martin",
"siren": "texte",
"vat_number": "texte",
"vat_regime": "normal",
"is_default": false,
"default_tax_code": "FRANCHISE_293B"
}
]
}/tax-codes
#
portée invoices:read
Les valeurs admises dans `tax_code`, avec leur taux du jour.
curl "https://clientzen.fr/api/v1/tax-codes" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json"{
"data": [
{
"code": "FR_STANDARD",
"label": "TVA 20 %",
"rate": "20.00",
"category": "texte",
"valid_from": "2026-09-28"
}
]
}/invoices
#
portée invoices:read
| Nom | Où | Type | Description |
|---|---|---|---|
page | requête | integer | Numéro de page (1 par défaut) |
per_page | requête | integer | Éléments par page (25 par défaut, 100 au plus) |
status | requête | string | |
payment_status | requête | string | |
customer_id | requête | string | |
issued_from | requête | string (date) | Émises à partir de (AAAA-MM-JJ) |
curl "https://clientzen.fr/api/v1/invoices" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json"{
"data": [
{
"id": "01k2md6h7j8k9m0n1p2q3r4s5t",
"number": "F-2026-00128",
"type": "invoice",
"status": "draft",
"payment_status": "unpaid",
"transmission_status": "none",
"customer_id": "texte",
"customer_name": "Boulangerie Petit",
"legal_entity_id": "texte",
"title": "Rénovation de la boutique — solde",
"issue_date": "2026-09-28",
"due_date": "2026-10-28",
"currency": "EUR",
"total_excl_cents": 250000,
"total_tax_cents": 50000,
"total_incl_cents": 300000,
"amount_due_cents": 300000,
"amount_paid_cents": 0,
"remaining_cents": 300000,
"vat_treatment": "domestic",
"pdf_sha256": "9f2c…",
"payment_url": "https://clientzen.fr/portail/01k2…/factures/Xy9…",
"created_at": "2026-09-28T10:00:00+00:00",
"snapshot": {}
}
],
"meta": {
"page": 1,
"per_page": 25,
"total": 42,
"last_page": 2
},
"links": {
"next": "https://clientzen.fr/api/v1/customers?page=2",
"prev": null
}
}/invoices
#
portée invoices:write Idempotency-Key
Le brouillon n'a pas de numéro. Avec `issue: true`, la facture est émise dans la foulée : numéro définitif attribué, contenu figé, irréversible (une correction passe par un avoir).
| Nom | Où | Type | Description |
|---|---|---|---|
Idempotency-Key | en-tête | string | Clé propre à votre opération : la première réponse est rejouée à l'identique |
| Champ | Type | Description |
|---|---|---|
legal_entity_id | string | Société émettrice (GET /companies). Absent : la société par défaut de l'espace. ex. 01k2m7r0y5w9c4p7d2f6g1h3j8 |
customer_id* | string | ex. 01k2m9c3d4e5f6g7h8j9k0m1n2 |
title | string | ex. Rénovation de la boutique |
operation_category* | string | Valeurs : goods, services, mixed ex. services |
vat_treatment | string | Doit être admissible pour le client (proposition serveur sinon) ex. domestic |
service_date_from | string (date) | |
service_date_to | string (date) | |
due_date | string (date) | ex. 2026-10-28 |
payment_terms | string | ex. Paiement à 30 jours. |
notes | string | |
issue | boolean | true = émission immédiate (numéro définitif, irréversible) ex. false |
send | boolean | Avec `issue: true` : envoyer aussitôt la facture au client (PDF et lien de paiement). Absent : le réglage de l'espace « Envoyer au client chaque facture émise par l'API ». Un échec d'envoi n'annule pas l'émission (voir `meta.email`). ex. true |
apply_customer_prices | boolean | true = les lignes portant un `product_id` reçoivent le tarif négocié du client (prix catalogue + remise), à la place du prix et de la remise envoyés ex. false |
lines* | array<object> |
curl -X POST "https://clientzen.fr/api/v1/invoices" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"legal_entity_id":"01k2m7r0y5w9c4p7d2f6g1h3j8","customer_id":"01k2m9c3d4e5f6g7h8j9k0m1n2","title":"Rénovation de la boutique","operation_category":"services","vat_treatment":"domestic","due_date":"2026-10-28","payment_terms":"Paiement à 30 jours.","issue":false,"send":true,"apply_customer_prices":false,"lines":[{"kind":"line","description":"Pose de parquet","quantity":"2.5","unit_code":"m2","unit_price":"45.00","discount_percent_e2":0,"tax_code":"FR_STANDARD"}]}'{
"data": {
"id": "01k2md6h7j8k9m0n1p2q3r4s5t",
"number": "F-2026-00128",
"type": "invoice",
"status": "draft",
"payment_status": "unpaid",
"transmission_status": "none",
"customer_id": "texte",
"customer_name": "Boulangerie Petit",
"legal_entity_id": "texte",
"title": "Rénovation de la boutique — solde",
"issue_date": "2026-09-28",
"due_date": "2026-10-28",
"currency": "EUR",
"total_excl_cents": 250000,
"total_tax_cents": 50000,
"total_incl_cents": 300000,
"amount_due_cents": 300000,
"amount_paid_cents": 0,
"remaining_cents": 300000,
"vat_treatment": "domestic",
"pdf_sha256": "9f2c…",
"payment_url": "https://clientzen.fr/portail/01k2…/factures/Xy9…",
"created_at": "2026-09-28T10:00:00+00:00",
"snapshot": {}
},
"meta": {
"email": {
"sent": false,
"to": "compta@client.fr",
"error": "Adresse e-mail du destinataire absente ou invalide."
}
}
}/invoices/{id}
#
portée invoices:read
| Nom | Où | Type | Description |
|---|---|---|---|
id* | chemin | string | Identifiant (ULID) |
curl "https://clientzen.fr/api/v1/invoices/01k2md6h7j8k9m0n1p2q3r4s5t" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json"{
"data": {
"id": "01k2md6h7j8k9m0n1p2q3r4s5t",
"number": "F-2026-00128",
"type": "invoice",
"status": "draft",
"payment_status": "unpaid",
"transmission_status": "none",
"customer_id": "texte",
"customer_name": "Boulangerie Petit",
"legal_entity_id": "texte",
"title": "Rénovation de la boutique — solde",
"issue_date": "2026-09-28",
"due_date": "2026-10-28",
"currency": "EUR",
"total_excl_cents": 250000,
"total_tax_cents": 50000,
"total_incl_cents": 300000,
"amount_due_cents": 300000,
"amount_paid_cents": 0,
"remaining_cents": 300000,
"vat_treatment": "domestic",
"pdf_sha256": "9f2c…",
"payment_url": "https://clientzen.fr/portail/01k2…/factures/Xy9…",
"created_at": "2026-09-28T10:00:00+00:00",
"snapshot": {}
}
}/invoices/{id}/pdf
#
portée invoices:read
Le PDF archivé à l'émission (son empreinte est `pdf_sha256`).
| Nom | Où | Type | Description |
|---|---|---|---|
id* | chemin | string | Identifiant (ULID) |
curl "https://clientzen.fr/api/v1/invoices/01k2md6h7j8k9m0n1p2q3r4s5t/pdf" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json"/invoices/{id}/issue
#
portée invoices:write Idempotency-Key
Numéro définitif, contenu figé, irréversible. Idempotent. `send: true` dans le corps envoie aussitôt la facture au client (voir `meta.email`).
| Nom | Où | Type | Description |
|---|---|---|---|
id* | chemin | string | Identifiant (ULID) |
Idempotency-Key | en-tête | string | Clé propre à votre opération : la première réponse est rejouée à l'identique |
| Champ | Type | Description |
|---|---|---|
issue_date | string (date) | |
send | boolean |
curl -X POST "https://clientzen.fr/api/v1/invoices/01k2md6h7j8k9m0n1p2q3r4s5t/issue" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{}'{
"data": {
"id": "01k2md6h7j8k9m0n1p2q3r4s5t",
"number": "F-2026-00128",
"type": "invoice",
"status": "draft",
"payment_status": "unpaid",
"transmission_status": "none",
"customer_id": "texte",
"customer_name": "Boulangerie Petit",
"legal_entity_id": "texte",
"title": "Rénovation de la boutique — solde",
"issue_date": "2026-09-28",
"due_date": "2026-10-28",
"currency": "EUR",
"total_excl_cents": 250000,
"total_tax_cents": 50000,
"total_incl_cents": 300000,
"amount_due_cents": 300000,
"amount_paid_cents": 0,
"remaining_cents": 300000,
"vat_treatment": "domestic",
"pdf_sha256": "9f2c…",
"payment_url": "https://clientzen.fr/portail/01k2…/factures/Xy9…",
"created_at": "2026-09-28T10:00:00+00:00",
"snapshot": {}
},
"meta": {
"email": {
"sent": false,
"to": "compta@client.fr",
"error": "Adresse e-mail du destinataire absente ou invalide."
}
}
}/invoices/{id}/send
#
portée invoices:write Idempotency-Key
E-mail avec le PDF et le lien de paiement en ligne (`payment_url`), comme le bouton « Envoyer au client ». Rejouer avec la même `Idempotency-Key` n'envoie pas un second e-mail. Sans `to`, l'adresse de la fiche client. 409 si la facture n'est pas émise ou si aucune adresse n'est connue.
| Nom | Où | Type | Description |
|---|---|---|---|
id* | chemin | string | Identifiant (ULID) |
Idempotency-Key | en-tête | string | Clé propre à votre opération : la première réponse est rejouée à l'identique |
| Champ | Type | Description |
|---|---|---|
to | string (email) | ex. compta@client.fr |
message | string | ex. Merci pour votre commande. |
curl -X POST "https://clientzen.fr/api/v1/invoices/01k2md6h7j8k9m0n1p2q3r4s5t/send" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"to":"compta@client.fr","message":"Merci pour votre commande."}'{
"data": {
"id": "01k2md6h7j8k9m0n1p2q3r4s5t",
"number": "F-2026-00128",
"type": "invoice",
"status": "draft",
"payment_status": "unpaid",
"transmission_status": "none",
"customer_id": "texte",
"customer_name": "Boulangerie Petit",
"legal_entity_id": "texte",
"title": "Rénovation de la boutique — solde",
"issue_date": "2026-09-28",
"due_date": "2026-10-28",
"currency": "EUR",
"total_excl_cents": 250000,
"total_tax_cents": 50000,
"total_incl_cents": 300000,
"amount_due_cents": 300000,
"amount_paid_cents": 0,
"remaining_cents": 300000,
"vat_treatment": "domestic",
"pdf_sha256": "9f2c…",
"payment_url": "https://clientzen.fr/portail/01k2…/factures/Xy9…",
"created_at": "2026-09-28T10:00:00+00:00",
"snapshot": {}
},
"meta": {
"email": {
"sent": false,
"to": "compta@client.fr",
"error": "Adresse e-mail du destinataire absente ou invalide."
}
}
}Paiements reçus et leur affectation aux factures.
/payments
#
portée payments:read
| Nom | Où | Type | Description |
|---|---|---|---|
page | requête | integer | Numéro de page (1 par défaut) |
per_page | requête | integer | Éléments par page (25 par défaut, 100 au plus) |
from | requête | string (date) | |
to | requête | string (date) |
curl "https://clientzen.fr/api/v1/payments" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json"{
"data": [
{
"id": "01k2mf7j8k9m0n1p2q3r4s5t6v",
"customer_id": "texte",
"method": "transfer",
"amount_cents": 300000,
"currency": "EUR",
"received_at": "2026-10-02",
"reference": "VIR F-2026-00128",
"status": "recorded",
"unallocated_cents": 0,
"allocations": [
{
"invoice_id": "texte",
"amount_cents": 300000
}
]
}
],
"meta": {
"page": 1,
"per_page": 25,
"total": 42,
"last_page": 2
},
"links": {
"next": "https://clientzen.fr/api/v1/customers?page=2",
"prev": null
}
}Services réservables, disponibilités calculées par le serveur, réservations et annulations (module Rendez-vous).
/booking/services
#
portée appointments:read
Avec leurs ressources (intervenants, salles). Module Rendez-vous requis.
curl "https://clientzen.fr/api/v1/booking/services" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json"{
"data": [
{
"id": "texte",
"slug": "consultation",
"name": "Consultation (1 h)",
"category": "Conseil",
"description": "texte",
"duration_min": 60,
"buffer_before_min": 0,
"buffer_after_min": 15,
"capacity": 1,
"price_excl_cents": 8000,
"tax_code": "FR_STANDARD",
"deposit_excl_cents": 4000,
"location_mode": "onsite",
"is_public": true,
"resources": [
{
"id": "texte",
"name": "Salle 1",
"kind": "room"
}
]
}
]
}/booking/availability
#
portée appointments:read
Calculés par le serveur (plages, indisponibilités, capacité, délais), dans le fuseau de l'espace.
| Nom | Où | Type | Description |
|---|---|---|---|
service_id* | requête | string | |
day* | requête | string (date) | |
resource_id | requête | string | |
seats | requête | integer |
curl "https://clientzen.fr/api/v1/booking/availability?service_id=VALEUR&day=2026-10-05" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json"{
"data": [
{
"starts_at": "2026-10-05T09:00:00+02:00",
"ends_at": "2026-10-05T10:00:00+02:00",
"resource_id": "texte",
"resource_name": "Salle 1",
"remaining": 1
}
],
"meta": {
"timezone": "Europe/Paris",
"day": "2026-10-05"
}
}/appointments
#
portée appointments:read
| Nom | Où | Type | Description |
|---|---|---|---|
page | requête | integer | Numéro de page (1 par défaut) |
per_page | requête | integer | Éléments par page (25 par défaut, 100 au plus) |
from | requête | string (date-time) | |
to | requête | string (date-time) | |
status | requête | string | |
resource_id | requête | string | |
customer_id | requête | string |
curl "https://clientzen.fr/api/v1/appointments" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json"{
"data": [
{
"id": "texte",
"reference": "RDV-A1B2C3D4",
"status": "pending_payment",
"source": "api",
"service": {
"id": "texte",
"name": "Consultation (1 h)"
},
"resource": {
"id": "texte",
"name": "Salle 1"
},
"customer": {
"id": "texte",
"name": "Marie Durand",
"email": "marie.durand@exemple.fr",
"phone": "texte"
},
"starts_at": "2026-09-28T10:00:00+00:00",
"ends_at": "2026-09-28T10:00:00+00:00",
"timezone": "Europe/Paris",
"seats": 1,
"message": "texte",
"deposit_invoice_id": "texte",
"final_invoice_id": "texte",
"hold_expires_at": "2026-09-28T10:00:00+00:00",
"cancel_reason": "texte",
"created_at": "2026-09-28T10:00:00+00:00",
"manage_url": "texte",
"payment_url": "texte"
}
],
"meta": {
"page": 1,
"per_page": 25,
"total": 42,
"last_page": 2
},
"links": {
"next": "https://clientzen.fr/api/v1/customers?page=2",
"prev": null
}
}/appointments
#
portée appointments:write Idempotency-Key
Mêmes règles que le mini-site (délai, horizon, plages, capacité). Service avec acompte : facture d'acompte créée et `payment_url` renvoyé.
| Nom | Où | Type | Description |
|---|---|---|---|
Idempotency-Key | en-tête | string | Clé propre à votre opération : la première réponse est rejouée à l'identique |
| Champ | Type | Description |
|---|---|---|
service_id* | string | |
resource_id | string | null | Absent = première ressource disponible |
starts_at* | string (date-time) | ex. 2026-10-05T09:00:00+02:00 |
seats | integer | ex. 1 |
customer* | object | |
customer.id | string | |
customer.name | string | ex. Marie Durand |
customer.email | string | ex. marie.durand@exemple.fr |
customer.phone | string | |
customer.address | object | Requise si un acompte est facturé |
message | string | |
reminders_consent | boolean | ex. true |
source | string | Valeurs : api, widget, site |
curl -X POST "https://clientzen.fr/api/v1/appointments" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"service_id":"texte","starts_at":"2026-10-05T09:00:00+02:00","seats":1,"customer":{"name":"Marie Durand","email":"marie.durand@exemple.fr","address":{}},"reminders_consent":true}'{
"data": {
"id": "texte",
"reference": "RDV-A1B2C3D4",
"status": "pending_payment",
"source": "api",
"service": {
"id": "texte",
"name": "Consultation (1 h)"
},
"resource": {
"id": "texte",
"name": "Salle 1"
},
"customer": {
"id": "texte",
"name": "Marie Durand",
"email": "marie.durand@exemple.fr",
"phone": "texte"
},
"starts_at": "2026-09-28T10:00:00+00:00",
"ends_at": "2026-09-28T10:00:00+00:00",
"timezone": "Europe/Paris",
"seats": 1,
"message": "texte",
"deposit_invoice_id": "texte",
"final_invoice_id": "texte",
"hold_expires_at": "2026-09-28T10:00:00+00:00",
"cancel_reason": "texte",
"created_at": "2026-09-28T10:00:00+00:00",
"manage_url": "texte",
"payment_url": "texte"
}
}/appointments/{id}
#
portée appointments:read
| Nom | Où | Type | Description |
|---|---|---|---|
id* | chemin | string | Identifiant (ULID) |
curl "https://clientzen.fr/api/v1/appointments/01k2md6h7j8k9m0n1p2q3r4s5t" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json"{
"data": {
"id": "texte",
"reference": "RDV-A1B2C3D4",
"status": "pending_payment",
"source": "api",
"service": {
"id": "texte",
"name": "Consultation (1 h)"
},
"resource": {
"id": "texte",
"name": "Salle 1"
},
"customer": {
"id": "texte",
"name": "Marie Durand",
"email": "marie.durand@exemple.fr",
"phone": "texte"
},
"starts_at": "2026-09-28T10:00:00+00:00",
"ends_at": "2026-09-28T10:00:00+00:00",
"timezone": "Europe/Paris",
"seats": 1,
"message": "texte",
"deposit_invoice_id": "texte",
"final_invoice_id": "texte",
"hold_expires_at": "2026-09-28T10:00:00+00:00",
"cancel_reason": "texte",
"created_at": "2026-09-28T10:00:00+00:00",
"manage_url": "texte",
"payment_url": "texte"
}
}/appointments/{id}/cancel
#
portée appointments:write
`by_customer: true` applique le délai d'annulation libre du client.
| Nom | Où | Type | Description |
|---|---|---|---|
id* | chemin | string | Identifiant (ULID) |
| Champ | Type | Description |
|---|---|---|
reason | string | ex. Empêchement |
by_customer | boolean | ex. true |
curl -X POST "https://clientzen.fr/api/v1/appointments/01k2md6h7j8k9m0n1p2q3r4s5t/cancel" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"reason":"Empêchement","by_customer":true}'{
"data": {
"id": "texte",
"reference": "RDV-A1B2C3D4",
"status": "pending_payment",
"source": "api",
"service": {
"id": "texte",
"name": "Consultation (1 h)"
},
"resource": {
"id": "texte",
"name": "Salle 1"
},
"customer": {
"id": "texte",
"name": "Marie Durand",
"email": "marie.durand@exemple.fr",
"phone": "texte"
},
"starts_at": "2026-09-28T10:00:00+00:00",
"ends_at": "2026-09-28T10:00:00+00:00",
"timezone": "Europe/Paris",
"seats": 1,
"message": "texte",
"deposit_invoice_id": "texte",
"final_invoice_id": "texte",
"hold_expires_at": "2026-09-28T10:00:00+00:00",
"cancel_reason": "texte",
"created_at": "2026-09-28T10:00:00+00:00",
"manage_url": "texte",
"payment_url": "texte"
}
}Articles publiés de la base de connaissance, conversations du tchat, réponse et clôture au nom du membre qui a créé le jeton (module Base de connaissance).
/knowledge/articles
#
portée knowledge:read
Les brouillons ne sortent jamais. Module Base de connaissance requis.
| Nom | Où | Type | Description |
|---|---|---|---|
page | requête | integer | Numéro de page (1 par défaut) |
per_page | requête | integer | Éléments par page (25 par défaut, 100 au plus) |
q | requête | string | Recherche dans le titre |
category | requête | string | |
updated_since | requête | string (date-time) |
curl "https://clientzen.fr/api/v1/knowledge/articles" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json"{
"data": [
{
"id": "texte",
"title": "Horaires d'ouverture",
"slug": "horaires-d-ouverture",
"category": "Pratique",
"source_type": "article",
"source_url": "texte",
"version": 3,
"published_at": "2026-09-28T10:00:00+00:00",
"updated_at": "2026-09-28T10:00:00+00:00",
"body": "texte"
}
],
"meta": {
"page": 1,
"per_page": 25,
"total": 42,
"last_page": 2
},
"links": {
"next": "https://clientzen.fr/api/v1/customers?page=2",
"prev": null
}
}/knowledge/articles/{id}
#
portée knowledge:read
| Nom | Où | Type | Description |
|---|---|---|---|
id* | chemin | string | Identifiant (ULID) |
curl "https://clientzen.fr/api/v1/knowledge/articles/01k2md6h7j8k9m0n1p2q3r4s5t" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json"{
"data": {
"id": "texte",
"title": "Horaires d'ouverture",
"slug": "horaires-d-ouverture",
"category": "Pratique",
"source_type": "article",
"source_url": "texte",
"version": 3,
"published_at": "2026-09-28T10:00:00+00:00",
"updated_at": "2026-09-28T10:00:00+00:00",
"body": "texte"
}
}/chat/conversations
#
portée chat:read
Les plus récentes d'abord. Filtrez sur `waiting` pour retrouver les visiteurs qui attendent l'équipe.
| Nom | Où | Type | Description |
|---|---|---|---|
page | requête | integer | Numéro de page (1 par défaut) |
per_page | requête | integer | Éléments par page (25 par défaut, 100 au plus) |
status | requête | string | |
widget_id | requête | string | |
updated_since | requête | string (date-time) |
curl "https://clientzen.fr/api/v1/chat/conversations" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json"{
"data": [
{
"id": "texte",
"status": "bot",
"widget_id": "texte",
"widget_name": "Site principal",
"origin_host": "www.exemple.fr",
"page_url": "texte",
"visitor": {
"name": "texte",
"email": "texte",
"phone": "texte",
"consent_at": "2026-09-28T10:00:00+00:00"
},
"customer_id": "texte",
"assigned_user_id": "texte",
"rating": 0,
"visitor_messages": 0,
"bot_answers": 0,
"abstentions": 0,
"escalated_at": "2026-09-28T10:00:00+00:00",
"first_agent_reply_at": "2026-09-28T10:00:00+00:00",
"closed_at": "2026-09-28T10:00:00+00:00",
"last_message_at": "2026-09-28T10:00:00+00:00",
"created_at": "2026-09-28T10:00:00+00:00",
"updated_at": "2026-09-28T10:00:00+00:00",
"messages": [
{
"id": "texte",
"author": "visitor",
"user_id": "texte",
"body": "Êtes-vous ouverts le samedi ?",
"abstained": false,
"sources": [
null
],
"created_at": "2026-09-28T10:00:00+00:00"
}
]
}
],
"meta": {
"page": 1,
"per_page": 25,
"total": 42,
"last_page": 2
},
"links": {
"next": "https://clientzen.fr/api/v1/customers?page=2",
"prev": null
}
}/chat/conversations/{id}
#
portée chat:read
| Nom | Où | Type | Description |
|---|---|---|---|
id* | chemin | string | Identifiant (ULID) |
curl "https://clientzen.fr/api/v1/chat/conversations/01k2md6h7j8k9m0n1p2q3r4s5t" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json"{
"data": {
"id": "texte",
"status": "bot",
"widget_id": "texte",
"widget_name": "Site principal",
"origin_host": "www.exemple.fr",
"page_url": "texte",
"visitor": {
"name": "texte",
"email": "texte",
"phone": "texte",
"consent_at": "2026-09-28T10:00:00+00:00"
},
"customer_id": "texte",
"assigned_user_id": "texte",
"rating": 0,
"visitor_messages": 0,
"bot_answers": 0,
"abstentions": 0,
"escalated_at": "2026-09-28T10:00:00+00:00",
"first_agent_reply_at": "2026-09-28T10:00:00+00:00",
"closed_at": "2026-09-28T10:00:00+00:00",
"last_message_at": "2026-09-28T10:00:00+00:00",
"created_at": "2026-09-28T10:00:00+00:00",
"updated_at": "2026-09-28T10:00:00+00:00",
"messages": [
{
"id": "texte",
"author": "visitor",
"user_id": "texte",
"body": "Êtes-vous ouverts le samedi ?",
"abstained": false,
"sources": [
{
"article_id": null,
"title": null
}
],
"created_at": "2026-09-28T10:00:00+00:00"
}
]
}
}/chat/conversations/{id}/reply
#
portée chat:write Idempotency-Key
Au nom du membre qui a créé le jeton, s'il a toujours le droit de répondre au tchat (403 sinon). Le visiteur parti depuis plus de 90 s et ayant laissé son adresse avec son accord reçoit aussi la réponse par e-mail.
| Nom | Où | Type | Description |
|---|---|---|---|
id* | chemin | string | Identifiant (ULID) |
Idempotency-Key | en-tête | string | Clé propre à votre opération : la première réponse est rejouée à l'identique |
| Champ | Type | Description |
|---|---|---|
body* | string | ex. Oui, de 9 h à 12 h. |
curl -X POST "https://clientzen.fr/api/v1/chat/conversations/01k2md6h7j8k9m0n1p2q3r4s5t/reply" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"body":"Oui, de 9 h à 12 h."}'{
"data": {
"id": "texte",
"status": "bot",
"widget_id": "texte",
"widget_name": "Site principal",
"origin_host": "www.exemple.fr",
"page_url": "texte",
"visitor": {
"name": "texte",
"email": "texte",
"phone": "texte",
"consent_at": "2026-09-28T10:00:00+00:00"
},
"customer_id": "texte",
"assigned_user_id": "texte",
"rating": 0,
"visitor_messages": 0,
"bot_answers": 0,
"abstentions": 0,
"escalated_at": "2026-09-28T10:00:00+00:00",
"first_agent_reply_at": "2026-09-28T10:00:00+00:00",
"closed_at": "2026-09-28T10:00:00+00:00",
"last_message_at": "2026-09-28T10:00:00+00:00",
"created_at": "2026-09-28T10:00:00+00:00",
"updated_at": "2026-09-28T10:00:00+00:00",
"messages": [
{
"id": "texte",
"author": "visitor",
"user_id": "texte",
"body": "Êtes-vous ouverts le samedi ?",
"abstained": false,
"sources": [
{
"article_id": null,
"title": null
}
],
"created_at": "2026-09-28T10:00:00+00:00"
}
]
}
}/chat/conversations/{id}/close
#
portée chat:write
Sans effet sur une conversation déjà close.
| Nom | Où | Type | Description |
|---|---|---|---|
id* | chemin | string | Identifiant (ULID) |
curl -X POST "https://clientzen.fr/api/v1/chat/conversations/01k2md6h7j8k9m0n1p2q3r4s5t/close" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json"{
"data": {
"id": "texte",
"status": "bot",
"widget_id": "texte",
"widget_name": "Site principal",
"origin_host": "www.exemple.fr",
"page_url": "texte",
"visitor": {
"name": "texte",
"email": "texte",
"phone": "texte",
"consent_at": "2026-09-28T10:00:00+00:00"
},
"customer_id": "texte",
"assigned_user_id": "texte",
"rating": 0,
"visitor_messages": 0,
"bot_answers": 0,
"abstentions": 0,
"escalated_at": "2026-09-28T10:00:00+00:00",
"first_agent_reply_at": "2026-09-28T10:00:00+00:00",
"closed_at": "2026-09-28T10:00:00+00:00",
"last_message_at": "2026-09-28T10:00:00+00:00",
"created_at": "2026-09-28T10:00:00+00:00",
"updated_at": "2026-09-28T10:00:00+00:00",
"messages": [
{
"id": "texte",
"author": "visitor",
"user_id": "texte",
"body": "Êtes-vous ouverts le samedi ?",
"abstained": false,
"sources": [
{
"article_id": null,
"title": null
}
],
"created_at": "2026-09-28T10:00:00+00:00"
}
]
}
}« REST hooks » pour Zapier, Make ou n8n : l'outil s'abonne lui-même aux événements quand un scénario est activé (`POST /webhooks`), et se désabonne quand il est coupé (`DELETE /webhooks/{id}`). Chaque jeton ne voit et ne supprime que ses abonnements ; révoquer le jeton les désactive. Répondre 410 à une livraison désactive l'abonnement.
/webhooks/events
#
portée webhooks:manage
curl "https://clientzen.fr/api/v1/webhooks/events" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json"{
"data": [
{
"event": "invoice.paid",
"label": "Facture réglée"
}
]
}/webhooks/sample/{event}
#
portée webhooks:manage
Même forme que la charge réellement envoyée (avec `sample: true`), pour proposer les champs avant le premier événement réel.
| Nom | Où | Type | Description |
|---|---|---|---|
event* | chemin | string |
curl "https://clientzen.fr/api/v1/webhooks/sample/{event}" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json"{
"data": [
{
"event": "texte",
"resource_type": "Invoice",
"resource_id": "texte",
"occurred_at": "2026-09-28T10:00:00+00:00",
"correlation_id": "texte",
"sample": false
}
]
}/webhooks
#
portée webhooks:manage
curl "https://clientzen.fr/api/v1/webhooks" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json"{
"data": [
{
"id": "texte",
"target_url": "texte",
"events": [
"texte"
],
"label": "texte",
"is_active": false,
"created_at": "2026-09-28T10:00:00+00:00"
}
]
}/webhooks
#
portée webhooks:manage Idempotency-Key
`target_url` (ou `targetUrl`) en https, adresse publique. `events` (liste) ou `event` (un seul, forme Zapier). Le `secret` de signature n'est rendu qu'ici, une seule fois. Idempotent avec `Idempotency-Key`.
| Nom | Où | Type | Description |
|---|---|---|---|
Idempotency-Key | en-tête | string | Clé propre à votre opération : la première réponse est rejouée à l'identique |
| Champ | Type | Description |
|---|---|---|
target_url* | string (uri) | ex. https://hooks.zapier.com/hooks/standard/123/abc |
events | array<string> | |
event | string | ex. invoice.paid |
label | string | ex. Zap : facture réglée → Google Sheets |
curl -X POST "https://clientzen.fr/api/v1/webhooks" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"target_url":"https://hooks.zapier.com/hooks/standard/123/abc","events":["invoice.paid"],"event":"invoice.paid","label":"Zap : facture réglée → Google Sheets"}'{
"data": {
"id": "texte",
"target_url": "texte",
"events": [
"texte"
],
"label": "texte",
"is_active": false,
"created_at": "2026-09-28T10:00:00+00:00",
"secret": "czs_…"
}
}/webhooks/{id}
#
portée webhooks:manage
Seulement un abonnement créé par ce jeton (404 sinon).
| Nom | Où | Type | Description |
|---|---|---|---|
id* | chemin | string | Identifiant (ULID) |
curl -X DELETE "https://clientzen.fr/api/v1/webhooks/01k2md6h7j8k9m0n1p2q3r4s5t" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json"Appelée par le module d'une boutique (WooCommerce, ou votre propre intégration) avec le jeton créé dans Ventes › Boutiques en ligne (portée `shop:sync`) : la boutique est déduite du jeton. Une commande payée devient une facture émise par ClientZen ; ce qui ne se facture pas juste (devise, hors de France, TVA inconnue, article absent, total différent) est mis à examiner.
/shop/handshake
#
portée shop:sync
Renvoie la boutique, la société qui facture et qui fait foi pour le catalogue et pour le stock (`clientzen` ou `shop`).
curl "https://clientzen.fr/api/v1/shop/handshake" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json"{
"data": {
"shop": {
"id": "texte",
"name": "Boutique Miel",
"platform": "woocommerce",
"store_url": "texte"
},
"company": {
"name": "texte",
"siren": "texte",
"vat_regime": "texte"
},
"catalog_master": "clientzen",
"stock_master": "clientzen",
"auto_invoice": false,
"currency": "EUR",
"server_time": "2026-09-28T10:00:00+00:00"
}
}/shop/catalog
#
portée shop:sync
Articles vendables ayant une référence (SKU), prix hors taxe et taux de TVA, stock disponible de la société pour les articles suivis, textes de vente et de référencement.
| Nom | Où | Type | Description |
|---|---|---|---|
updated_since | requête | string (date-time) |
curl "https://clientzen.fr/api/v1/shop/catalog" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json"{
"data": [
{
"sku": "MIEL-500",
"name": "texte",
"description": "texte",
"web_description": "texte",
"short_description": "texte",
"seo_title": "texte",
"seo_description": "texte",
"price_excl": "10.000000",
"tax_rate": "5.50",
"track_stock": false,
"stock": "12",
"active": false
}
]
}/shop/orders
#
portée shop:sync
Idempotent par `external_id`. Payée (`paid: true`) et pas encore facturée : la facture est émise et l'encaissement enregistré, une seule fois. Montants en décimal, taux de TVA lu dans la règle de la boutique.
| Champ | Type | Description |
|---|---|---|
external_id* | string | ex. 1042 |
number | string | |
currency | string | ex. EUR |
paid | boolean | |
paid_at | string (date-time) | null | |
customer | object | |
customer.email | string | |
customer.first_name | string | |
customer.last_name | string | |
customer.company | string | |
customer.phone | string | |
shipping_country | string | ex. FR |
lines* | array<object> | |
shipping | array<object> | |
total_incl* | string | ex. 51.10 |
curl -X POST "https://clientzen.fr/api/v1/shop/orders" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"external_id":"1042","currency":"EUR","customer":{},"shipping_country":"FR","lines":[{"quantity":"2","total_excl":"20.00","tax_rate":"5.50"}],"total_incl":"51.10"}'{
"data": {
"external_id": "texte",
"number": "texte",
"handling": "recorded",
"review_reason": "texte",
"payment_state": "texte",
"invoice_number": "texte"
}
}/shop/orders/{external_id}/refunds
#
portée shop:sync
Idempotent par `external_id` du remboursement. Commande facturée : un avoir est émis et le trop-perçu remboursé.
| Nom | Où | Type | Description |
|---|---|---|---|
external_id* | chemin | string |
| Champ | Type | Description |
|---|---|---|
external_id* | string | |
amount* | string | ex. 51.10 |
reason | string |
curl -X POST "https://clientzen.fr/api/v1/shop/orders/{external_id}/refunds" \
-H "Authorization: Bearer $CLIENTZEN_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"external_id":"texte","amount":"51.10"}'{
"data": {
"external_id": "texte",
"handling": "recorded",
"review_reason": "texte",
"amount_cents": 0
}
}Aucune opération ne correspond à cette recherche.
Déclarez une URL https dans Paramètres › API et webhooks et choisissez les événements. Nous envoyons un POST JSON une fois l'opération enregistrée. La charge utile ne contient aucune donnée personnelle : relisez la ressource par l'API avec son identifiant.
| Événement | Déclenché quand |
|---|---|
customer.created | Client créé |
customer.updated | Client modifié |
quote.sent | Devis transmis |
quote.accepted | Devis accepté |
quote.refused | Devis refusé |
invoice.issued | Facture émise |
invoice.paid | Facture réglée |
payment.recorded | Encaissement enregistré |
pos.ticket_issued | Ticket de caisse émis |
appointment.created | Rendez-vous créé |
appointment.confirmed | Rendez-vous confirmé |
appointment.rescheduled | Rendez-vous reprogrammé |
appointment.cancelled | Rendez-vous annulé |
chat.conversation_escalated | Conversation du tchat transmise à l'équipe |
chat.conversation_closed | Conversation du tchat close |
{
"event": "invoice.paid",
"resource_type": "Invoice",
"resource_id": "01k2md6h7j8k9m0n1p2q3r4s5t",
"occurred_at": "2026-10-02T08:14:03+00:00",
"correlation_id": "texte"
}Content-Type: application/json
User-Agent: ClientZen-Webhooks/1
X-ClientZen-Event: invoice.paid
X-ClientZen-Delivery: 01k2md6h7j8k9m0n1p2q3r4s5t
X-ClientZen-Signature: t=1790589600,v1=5f2b…2xx en moins de 8 secondes ; traitez le reste en arrière-plan. Les redirections ne sont pas suivies.X-ClientZen-Delivery.v1 est le HMAC-SHA256, en hexadécimal, de t + "." + corps brut avec le secret du webhook. Calculez-le sur le corps tel que reçu (pas un JSON réencodé), comparez en temps constant et refusez un horodatage de plus de 5 minutes.
$raw = file_get_contents('php://input');
$secret = getenv('CLIENTZEN_WEBHOOK_SECRET');
if (! preg_match('/^t=(\d+),v1=([a-f0-9]{64})$/', $_SERVER['HTTP_X_CLIENTZEN_SIGNATURE'] ?? '', $m)
|| abs(time() - (int) $m[1]) > 300
|| ! hash_equals(hash_hmac('sha256', $m[1].'.'.$raw, $secret), $m[2])) {
http_response_code(401);
exit;
}
$event = json_decode($raw, true); // ex. invoice.paid → GET /invoices/{resource_id}
http_response_code(204);import express from 'express';
import { createHmac, timingSafeEqual } from 'node:crypto';
import { verifyWebhookSignature } from './clientzen.mjs';
const app = express();
app.post('/webhooks/clientzen', express.raw({ type: 'application/json' }), (req, res) => {
const ok = verifyWebhookSignature(req.body.toString('utf8'), req.get('X-ClientZen-Signature'),
process.env.CLIENTZEN_WEBHOOK_SECRET, { createHmac, timingSafeEqual });
if (!ok) return res.sendStatus(401);
const event = JSON.parse(req.body);
res.sendStatus(204);
});import os
from flask import Flask, request, abort
from clientzen import verify_webhook_signature
app = Flask(__name__)
@app.post("/webhooks/clientzen")
def clientzen_webhook():
if not verify_webhook_signature(request.get_data(), request.headers.get("X-ClientZen-Signature", ""),
os.environ["CLIENTZEN_WEBHOOK_SECRET"]):
abort(401)
event = request.get_json()
return "", 204Un fichier, aucune dépendance. Chaque SDK gère le jeton, l'idempotence, la pagination (each), le téléchargement des PDF et convertit les erreurs RFC 9457 en exceptions.
const { data: invoice } = await cz.post('/invoices', {
legal_entity_id: 'ID_SOCIETE', customer_id: 'ID_CLIENT', operation_category: 'services',
title: 'Maintenance mensuelle', issue: true,
lines: [{ kind: 'line', description: 'Maintenance', quantity: '1', unit_price: '90.00', tax_code: 'FR_STANDARD' }],
}, { idempotencyKey: 'commande-2026-0042' });
console.log(invoice.number, invoice.total_incl_cents / 100, '€ TTC');
const pdf = await cz.download(`/invoices/${invoice.id}/pdf`);Les champs marqués * sont toujours présents (réponses) ou obligatoires (requêtes).
WebhookSubscription 6 champs| Champ | Type | Description |
|---|---|---|
id | string | |
target_url | string (uri) | |
events | array<string> | |
label | string | null | |
is_active | boolean | |
created_at | string (date-time) | null |
WebhookSubscriptionCreated 7 champs| Champ | Type | Description |
|---|---|---|
id | string | |
target_url | string (uri) | |
events | array<string> | |
label | string | null | |
is_active | boolean | |
created_at | string (date-time) | null | |
secret | string | ex. czs_… |
Problem 8 champs| Champ | Type | Description |
|---|---|---|
type | string | ex. https://clientzen.fr/developpeurs#erreurs |
title | string | ex. Données invalides |
status | integer | ex. 422 |
detail | string | ex. Le champ name est obligatoire. |
request_id | string | ex. 7f3c2a9e-5b1d-4c8e-9a2f-0e1d2c3b4a59 |
errors | object | Champs invalides (422 uniquement) |
required_scope | string | Portée manquante (403 d'un jeton sans la portée) ex. customers:write |
required_permission | string | Droit que le membre auteur du jeton n'a pas (403) ex. chat.reply |
Meta 4 champs| Champ | Type | Description |
|---|---|---|
page | integer | ex. 1 |
per_page | integer | ex. 25 |
total | integer | ex. 42 |
last_page | integer | ex. 2 |
Links 2 champs| Champ | Type | Description |
|---|---|---|
next | string | null | ex. https://clientzen.fr/api/v1/customers?page=2 |
prev | string | null |
Me 9 champs| Champ | Type | Description |
|---|---|---|
tenant | object | |
tenant.id | string | ex. 01k2m7q9x4v8b3n6c1d5f0g2h7 |
tenant.name | string | ex. Atelier Martin |
tenant.slug | string | ex. atelier-martin |
token | object | |
token.id | string | ex. 01k2m8a1b2c3d4e5f6g7h8j9k0 |
token.name | string | ex. Site vitrine |
token.scopes | array<string> | |
token.expires_at | string (date-time) | null |
Customer 16 champs| Champ | Type | Description |
|---|---|---|
id | string | ex. 01k2m9c3d4e5f6g7h8j9k0m1n2 |
type | string | Valeurs : company, individual |
name | string | ex. Boulangerie Petit |
siren | string | null | ex. 552100554 |
vat_number | string | null | ex. FR40552100554 |
vat_status | string | null | Valeurs : taxable, non_taxable, public, null |
email | string | null | ex. contact@boulangerie-petit.fr |
phone | string | null | ex. +33 3 88 00 00 00 |
website | string | null | ex. https://boulangerie-petit.fr |
is_prospect | boolean | ex. false |
is_supplier | boolean | ex. false |
tags | array<string> | |
custom_fields | object | |
addresses | array<object> | null | |
created_at | string (date-time) | |
updated_at | string (date-time) |
Address 7 champs| Champ | Type | Description |
|---|---|---|
kind | string | ex. billing |
line1 | string | ex. 12 rue des Fours |
line2 | string | null | |
postal_code | string | ex. 67000 |
city | string | ex. Strasbourg |
country | string | ex. FR |
is_default | boolean | ex. true |
CustomerInput 18 champs| Champ | Type | Description |
|---|---|---|
type* | string | Valeurs : company, individual |
name* | string | ex. Boulangerie Petit |
siren | string | 9 chiffres, clé de Luhn vérifiée ex. 552100554 |
vat_number | string | ex. FR40552100554 |
vat_status | string | Valeurs : taxable, non_taxable, public |
email | string (email) | ex. contact@boulangerie-petit.fr |
phone | string | ex. +33 3 88 00 00 00 |
website | string (uri) | ex. https://boulangerie-petit.fr |
is_prospect | boolean | ex. true |
is_supplier | boolean | ex. false |
tags | array<string> | |
notes | string | ex. Demande reçue par le formulaire du site. |
address | object | |
address.line1 | string | ex. 12 rue des Fours |
address.line2 | string | |
address.postal_code | string | ex. 67000 |
address.city | string | ex. Strasbourg |
address.country | string | ex. FR |
Product 10 champs| Champ | Type | Description |
|---|---|---|
id | string | ex. 01k2mb4f5g6h7j8k9m0n1p2q3r |
sku | string | null | ex. POSE-01 |
name | string | ex. Pose de parquet |
description | string | null | ex. Pose flottante, fournitures non comprises. |
type | string | Valeurs : goods, service |
unit_code | string | ex. m2 |
unit_price | string | HT, 6 décimales max ex. 45.000000 |
currency | string | ex. EUR |
tax_code | string | null | ex. FR_STANDARD |
updated_at | string (date-time) |
CustomerPrice 10 champs| Champ | Type | Description |
|---|---|---|
customer_id | string | |
product_id | string | |
quantity | string | ex. 10 |
catalog_unit_price | string | Prix HT du catalogue ex. 49 |
unit_price | string | Prix unitaire HT à porter sur la ligne (le prix du catalogue, sauf prix négocié supérieur) ex. 49 |
net_unit_price | string | Prix unitaire HT après remise ex. 41.65 |
discount_percent_e2 | integer | Remise en centièmes de % ex. 1500 |
discount_amount_cents | integer | Remise de ligne en centimes, quand le prix négocié ne tombe pas juste en % ex. 0 |
rule_id | string | null | |
label | string | null | ex. Tarif Revendeurs : −15 % |
Quote 12 champs| Champ | Type | Description |
|---|---|---|
id | string | ex. 01k2mc5g6h7j8k9m0n1p2q3r4s |
number | string | null | ex. DEV-2026-0042 |
status | string | Valeurs : draft, pending_approval, sent, viewed, accepted, refused, expired, superseded |
customer_id | string | |
customer_name | string | null | ex. Boulangerie Petit |
title | string | null | ex. Rénovation de la boutique |
total_excl_cents | integer | ex. 250000 |
total_tax_cents | integer | ex. 50000 |
total_incl_cents | integer | ex. 300000 |
currency | string | ex. EUR |
valid_until | string (date) | null | ex. 2026-10-28 |
created_at | string (date-time) |
Invoice 24 champs| Champ | Type | Description |
|---|---|---|
id | string | ex. 01k2md6h7j8k9m0n1p2q3r4s5t |
number | string | null | null tant que le brouillon n'est pas émis ex. F-2026-00128 |
type | string | Valeurs : invoice, deposit, balance, credit_note, proforma |
status | string | Valeurs : draft, issued |
payment_status | string | Valeurs : unpaid, partial, paid, overpaid |
transmission_status | string | null | ex. none |
customer_id | string | |
customer_name | string | null | ex. Boulangerie Petit |
legal_entity_id | string | |
title | string | null | ex. Rénovation de la boutique — solde |
issue_date | string (date) | null | ex. 2026-09-28 |
due_date | string (date) | null | ex. 2026-10-28 |
currency | string | ex. EUR |
total_excl_cents | integer | ex. 250000 |
total_tax_cents | integer | ex. 50000 |
total_incl_cents | integer | ex. 300000 |
amount_due_cents | integer | ex. 300000 |
amount_paid_cents | integer | ex. 0 |
remaining_cents | integer | ex. 300000 |
vat_treatment | string | null | ex. domestic |
pdf_sha256 | string | null | ex. 9f2c… |
payment_url | string (uri) | null | Facture en ligne (consultation et paiement par vos moyens de paiement) : stable, non devinable, le même lien que dans les e-mails. Seulement sur le détail d'une facture émise (ni avoir ni pro forma), espace client actif. ex. https://clientzen.fr/portail/01k2…/factures/Xy9… |
created_at | string (date-time) | |
snapshot | object | Contenu figé à l'émission (détail uniquement) |
EmailResult 3 champs| Champ | Type | Description |
|---|---|---|
sent | boolean | |
to | string | null | ex. compta@client.fr |
error | string | null | ex. Adresse e-mail du destinataire absente ou invalide. |
InvoiceInput 14 champs| Champ | Type | Description |
|---|---|---|
legal_entity_id | string | Société émettrice (GET /companies). Absent : la société par défaut de l'espace. ex. 01k2m7r0y5w9c4p7d2f6g1h3j8 |
customer_id* | string | ex. 01k2m9c3d4e5f6g7h8j9k0m1n2 |
title | string | ex. Rénovation de la boutique |
operation_category* | string | Valeurs : goods, services, mixed ex. services |
vat_treatment | string | Doit être admissible pour le client (proposition serveur sinon) ex. domestic |
service_date_from | string (date) | |
service_date_to | string (date) | |
due_date | string (date) | ex. 2026-10-28 |
payment_terms | string | ex. Paiement à 30 jours. |
notes | string | |
issue | boolean | true = émission immédiate (numéro définitif, irréversible) ex. false |
send | boolean | Avec `issue: true` : envoyer aussitôt la facture au client (PDF et lien de paiement). Absent : le réglage de l'espace « Envoyer au client chaque facture émise par l'API ». Un échec d'envoi n'annule pas l'émission (voir `meta.email`). ex. true |
apply_customer_prices | boolean | true = les lignes portant un `product_id` reçoivent le tarif négocié du client (prix catalogue + remise), à la place du prix et de la remise envoyés ex. false |
lines* | array<object> |
Payment 10 champs| Champ | Type | Description |
|---|---|---|
id | string | ex. 01k2mf7j8k9m0n1p2q3r4s5t6v |
customer_id | string | null | |
method | string | ex. transfer |
amount_cents | integer | ex. 300000 |
currency | string | ex. EUR |
received_at | string (date) | ex. 2026-10-02 |
reference | string | null | ex. VIR F-2026-00128 |
status | string | Valeurs : recorded, pending, rejected, cancelled |
unallocated_cents | integer | ex. 0 |
allocations | array<object> |
Service 15 champs| Champ | Type | Description |
|---|---|---|
id | string | |
slug | string | ex. consultation |
name | string | ex. Consultation (1 h) |
category | string | null | ex. Conseil |
description | string | null | |
duration_min | integer | ex. 60 |
buffer_before_min | integer | ex. 0 |
buffer_after_min | integer | ex. 15 |
capacity | integer | ex. 1 |
price_excl_cents | integer | null | ex. 8000 |
tax_code | string | null | ex. FR_STANDARD |
deposit_excl_cents | integer | ex. 4000 |
location_mode | string | ex. onsite |
is_public | boolean | ex. true |
resources | array<object> |
Slot 5 champs| Champ | Type | Description |
|---|---|---|
starts_at | string (date-time) | ex. 2026-10-05T09:00:00+02:00 |
ends_at | string (date-time) | ex. 2026-10-05T10:00:00+02:00 |
resource_id | string | |
resource_name | string | ex. Salle 1 |
remaining | integer | ex. 1 |
Appointment 27 champs| Champ | Type | Description |
|---|---|---|
id | string | |
reference | string | ex. RDV-A1B2C3D4 |
status | string | Valeurs : pending_payment, confirmed, cancelled_customer, cancelled_staff, no_show, done |
source | string | ex. api |
service | object | |
service.id | string | |
service.name | string | ex. Consultation (1 h) |
resource | object | |
resource.id | string | |
resource.name | string | ex. Salle 1 |
customer | object | |
customer.id | string | null | |
customer.name | string | ex. Marie Durand |
customer.email | string | null | ex. marie.durand@exemple.fr |
customer.phone | string | null | |
starts_at | string (date-time) | |
ends_at | string (date-time) | |
timezone | string | ex. Europe/Paris |
seats | integer | ex. 1 |
message | string | null | |
deposit_invoice_id | string | null | |
final_invoice_id | string | null | |
hold_expires_at | string (date-time) | null | |
cancel_reason | string | null | |
created_at | string (date-time) | |
manage_url | string | Page client (reprogrammer, annuler, ICS) — à la création seulement |
payment_url | string | null | Lien de paiement de l'acompte — à la création seulement |
AppointmentInput 13 champs| Champ | Type | Description |
|---|---|---|
service_id* | string | |
resource_id | string | null | Absent = première ressource disponible |
starts_at* | string (date-time) | ex. 2026-10-05T09:00:00+02:00 |
seats | integer | ex. 1 |
customer* | object | |
customer.id | string | |
customer.name | string | ex. Marie Durand |
customer.email | string | ex. marie.durand@exemple.fr |
customer.phone | string | |
customer.address | object | Requise si un acompte est facturé |
message | string | |
reminders_consent | boolean | ex. true |
source | string | Valeurs : api, widget, site |
KbArticle 10 champs| Champ | Type | Description |
|---|---|---|
id | string | |
title | string | ex. Horaires d'ouverture |
slug | string | ex. horaires-d-ouverture |
category | string | null | ex. Pratique |
source_type | string | Valeurs : article, faq, web, file |
source_url | string | null | |
version | integer | ex. 3 |
published_at | string (date-time) | null | |
updated_at | string (date-time) | |
body | string | Texte Markdown — sur le détail seulement |
ChatMessage 7 champs| Champ | Type | Description |
|---|---|---|
id | string | |
author | string | Valeurs : visitor, bot, agent, system |
user_id | string | null | Membre auteur (réponse de l'équipe) |
body | string | ex. Êtes-vous ouverts le samedi ? |
abstained | boolean | L'assistant n'a pas trouvé de réponse fondée |
sources | array<object> | |
created_at | string (date-time) |
ChatConversation 24 champs| Champ | Type | Description |
|---|---|---|
id | string | |
status | string | bot : l'assistant répond ; waiting : le visiteur attend l'équipe ; human : l'équipe a répondu ; closed : close |
widget_id | string | |
widget_name | string | ex. Site principal |
origin_host | string | null | ex. www.exemple.fr |
page_url | string | null | |
visitor | object | Coordonnées données par le visiteur avec son accord ; vides sinon |
visitor.name | string | null | |
visitor.email | string | null | |
visitor.phone | string | null | |
visitor.consent_at | string (date-time) | null | |
customer_id | string | null | |
assigned_user_id | string | null | |
rating | integer | null | |
visitor_messages | integer | |
bot_answers | integer | |
abstentions | integer | |
escalated_at | string (date-time) | null | |
first_agent_reply_at | string (date-time) | null | |
closed_at | string (date-time) | null | |
last_message_at | string (date-time) | null | |
created_at | string (date-time) | |
updated_at | string (date-time) | |
messages | array<object> | Sur le détail seulement |
WebhookEvent 5 champs| Champ | Type | Description |
|---|---|---|
event | string | ex. invoice.paid |
resource_type | string | Type de la ressource (nom de classe) ex. Invoice |
resource_id | string | ex. 01k2md6h7j8k9m0n1p2q3r4s5t |
occurred_at | string (date-time) | ex. 2026-10-02T08:14:03+00:00 |
correlation_id | string | null |
v1 : un champ existant ne change ni de sens ni de type ; des champs et des événements peuvent s'ajouter — ignorez ce que vous ne connaissez pas. Une rupture ferait l'objet d'une v2, annoncée sur cette page et dans les espaces.