C cenaly.com
Commencer gratuitement

API public et webhooks

Clés avec autorisations, API REST pour prospects, propriétés, événements, conversations et segments, webhooks pour nouveaux prospects et événements — avec exemples curl

On this page 9

API public et webhooks

L'API REST permet à votre CRM, au backend de votre site ou à votre propre bot de travailler avec les leads et les dialogues cenaly.com comme le fait le panneau : lire les fiches, modifier les propriétés, envoyer des événements, répondre dans les dialogues. Les webhooks, à l'inverse, informent votre serveur des nouveaux leads, événements et messages.

Ce qu'il faut pour démarrer#

Quoi Où
Rôle propriétaire du compte — la clé agit en son nom ; les employés ne voient pas les clés
Section chat activé (les leads et les dialogues y vivent)
Clé Intégrations → API et webhooks → Clés → Créer une clé
Adresse de l'API https://api.cenaly.com/public-api/v1
Référence des méthodes api.cenaly.com/public-api/v1/docs
OpenAPI 3.1 api.cenaly.com/public-api/v1/openapi.json

Étape 1. Clé et droits#

  1. Ouvrez Intégrations et cliquez sur API et webhooks en haut de la page.
  2. Dans l'onglet Clés, cliquez sur Créer une clé, saisissez un nom (« CRM », « Backend du site », « Bot Telegram »).
  3. Choisissez un ensemble de droits ou cochez les droits un par un, et en cas de plusieurs établissements — à quels établissements la clé est autorisée, ainsi que la durée.
  4. Copiez le secret cnk_…. Il n'est affiché qu'une fois : nous ne conservons que son empreinte (SHA-256).
Droit Ce qu'il permet
contacts:read liste, recherche et fiche du lead, propriétés
contacts:write modifier les propriétés et les tags, fusionner, supprimer sur demande de la personne concernée
events:read fil des événements du lead
events:write envoyer des événements (achat, inscription, tout événement qui vous est propre)
conversations:read dialogues et messages
conversations:write réponse d'un opérateur, note, statut, responsable, libellés
messages:send message au lead dans son dernier dialogue
segments:read segments enregistrés et leurs participants

Ensembles : CRM / backend (leads, propriétés, événements, lecture des dialogues et des segments), Votre bot (lit les leads, répond dans les dialogues, écrit aux leads), Lecture seule, Tout.

  • Droits modifie à la volée les droits et les établissements de la clé — l'intégration continue de fonctionner.
  • Réémettre délivre un nouveau secret ; l'ancien cesse de fonctionner immédiatement, les droits et le journal restent.
  • Révoquer — immédiatement et définitivement, la requête suivante recevra 401.

La clé est transmise par l'en-tête Authorization: Bearer cnk_… (ou X-Api-Key: cnk_…). Conservez-la uniquement sur le serveur — pas dans le navigateur ni dans l'application mobile.

Étape 2. Premières requêtes#

KEY=cnk_ваш_ключ
API=https://api.cenaly.com/public-api/v1

# ce que la clé permet : droits, établissements, limite
curl -H "Authorization: Bearer $KEY" "$API/me"

# leads, les plus récents en premier (20 par page)
curl -H "Authorization: Bearer $KEY" "$API/contacts?limit=20"

# recherche par nom, e-mail ou téléphone
curl -H "Authorization: Bearer $KEY" "$API/contacts?q=anna"

La réponse est toujours une enveloppe :

{
  "meta": { "status": 200, "requestId": "…", "nextCursor": "WyIyMDI2LTEwLTA0…" },
  "data": { "total": 128, "contacts": [ { "id": "…", "status": "lead", "name": "Анна", "updatedAt": "2026-10-04T09:12:00Z" } ] }
}

La page suivante — la même requête avec cursor=<meta.nextCursor> ; pas de nextCursor — il n'y a plus de pages. Erreur — {"meta": {...}, "error": {"code": "…"}}.

Établissement. Si un seul établissement est accessible à la clé, il n'est pas nécessaire de l'indiquer. S'il y en a plusieurs — ajoutez location=<id de l'établissement> (liste — GET /v1/locations), sinon la réponse sera 400 location_required.

Propriétés et événements selon votre user_id. Il n'est pas obligatoire de conserver notre id de lead : ajoutez ?by=user_id, et l'adresse deviendra votre identifiant utilisateur. S'il n'y a pas encore de lead avec un tel user_id — nous le créerons.

# propriétés : opérations update_or_create, set_once, add, delete, append, union, exclude
curl -X POST -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"ops":[{"op":"update_or_create","key":"$email","value":"anna@example.com"},
              {"op":"add","key":"orders","value":1},
              {"op":"union","key":"interests","value":"yoga"}]}' \
  "$API/contacts/u-1001/props?by=user_id"

# événements par lots (jusqu'à 100), une répétition avec le même id n'est comptée qu'une fois
curl -X POST -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"events":[{"id":"ord-5531","userId":"u-1001","name":"order_paid","props":{"sum":45,"currency":"GEL"}}]}' \
  "$API/events"

# réponse dans un dialogue et changement de statut
curl -X POST -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"text":"Здравствуйте! Заказ передан курьеру."}' "$API/conversations/<id>/reply"
curl -X POST -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"status":"resolved"}' "$API/conversations/<id>/status"

L'écriture passe par la même file d'attente que les modifications depuis le panneau : les changements sont appliqués en quelques secondes, et la réponse à une écriture par user_id — 202 avec pending. Dans la fiche du lead, l'auteur de la modification apparaît comme « API : <nom de la clé> ».

Méthodes#

Méthode Ce qu'elle fait Droit
GET /v1/me, GET /v1/locations clé, droits, établissements —
GET /v1/contacts prospects : status (anon, lead, user), q, limit, cursor contacts:read
GET /v1/contacts/{id} fiche : propriétés, tags, synthèse des événements contacts:read
POST /v1/contacts/{id}/props propriétés par opérations (jusqu'à 250) ou {"props":{…}} contacts:write
POST / DELETE /v1/contacts/{id}/tags tags du prospect contacts:write
POST /v1/contacts/merge fusion de deux fiches : aperçu, puis "apply": true contacts:write
POST /v1/contacts/{id}/erase suppression sur demande de la personne concernée ("confirm": true) contacts:write
GET /v1/contacts/{id}/events fil des événements du prospect events:read
POST /v1/contacts/{id}/events, POST /v1/events événements (jusqu'à 100 à la fois) events:write
GET /v1/contacts/{id}/conversations conversations du prospect conversations:read
POST /v1/contacts/{id}/messages écrire au prospect dans sa dernière conversation messages:send
GET /v1/conversations, /{id}, /{id}/messages conversations et messages conversations:read
POST /v1/conversations/{id}/reply réponse d'un opérateur ou note ("type": "note") conversations:write
POST /v1/conversations/{id}/status, /assign, /tags statut, responsable, libellés conversations:write
GET /v1/segments, GET /v1/segments/{id}/contacts segments et leurs membres segments:read

Les champs, exemples et codes d'erreur de chaque méthode se trouvent dans le référentiel.

Étape 3. Webhooks#

Les webhooks se configurent au niveau de l'établissement : Chat → Paramètres → Webhooks — adresse https, événements et secret de signature. Aux événements de conversation (nouvelle conversation, nouveau message, statut, évaluation, libellés) se sont ajoutés les événements de prospect :

Événement Quand il arrive
lead.created un nouveau prospect est apparu (contact laissé dans le chat, un formulaire, ou créé via l'API)
lead.props_changed les propriétés du prospect ont changé — liste des clés dans changedProps
lead.event_tracked le prospect a un événement ; par défaut tous vos événements sans les événements système ($…), la liste des noms est définie par le champ « Quels événements envoyer »
message.goal_reached le prospect a atteint l'objectif du message (pop-up, envoi groupé)
{
  "event": "lead.event_tracked",
  "deliveryId": "WD…",
  "at": "2026-10-04T09:12:03Z",
  "webhookId": "…",
  "locationId": "…",
  "contact": { "id": "…", "status": "user", "userId": "u-1001", "props": { "orders": 3 }, "tags": ["vip"] },
  "leadEvent": { "name": "order_paid", "at": "2026-10-04T09:12:00Z", "props": { "sum": 45 } }
}

Le nom, l'e-mail et le téléphone du prospect ne figurent dans le corps que si la case « Transmettre les contacts du client » est cochée pour le webhook. Vérification de la signature — HMAC-SHA256 du corps avec le secret du webhook :

# заголовок X-Meni-Signature: sha256=<hex>
echo -n "$BODY" | openssl dgst -sha256 -hmac "$SECRET"

Répondez 2xx en 5 secondes — sinon la livraison sera répétée ; après une longue série d'échecs, le webhook est désactivé, et cela se voit dans les paramètres. Filtrez les doublons par deliveryId.

Limites#

  • 60 requêtes par minute par clé ; au-delà — 429 avec l'en-tête Retry-After. Le reste — dans X-RateLimit-*.
  • Jusqu'à 200 enregistrements par page (50 par défaut), jusqu'à 100 événements par lot, jusqu'à 250 opérations sur les propriétés par requête, jusqu'à 30 tags à la fois.
  • Jusqu'à 20 clés actives par compte.
  • Le journal des appels de la clé est conservé 30 jours : heure, méthode, modèle de chemin (sans id ni corps), code de réponse, durée.
  • Les événements envoyés via l'API sont enregistrés dans la fiche du prospect (fil, synthèse, segments), mais pas dans le journal brut de l'analyse des visites.
  • On ne peut écrire à un prospect que dans une conversation existante : pas de conversation — réponse 409 no_conversation.

Dépannage#

Réponse Ce que cela signifie Que faire
401 api_key_missing / api_key_invalid la clé est absente de la requête, ou elle est incorrecte, révoquée ou expirée vérifiez l'en-tête ; si nécessaire, réémettez la clé
403 scope_required la clé n'a pas le droit nécessaire Droits de la clé — ajoutez le droit
400 location_required plusieurs établissements sont accessibles à la clé ajoutez location=<id>
404 location_not_found l'établissement ne fait pas partie de ceux de la clé vérifiez avec GET /v1/locations
404 not_found le prospect ou la conversation n'existe pas pour vos propres id, utilisez ?by=user_id
429 rate_limited plus de 60 requêtes par minute attendez Retry-After secondes, regroupez les événements par lots
502 upstream_error panne temporaire répétez la requête plus tard

Chaque requête est visible dans l'onglet Journal des appels — avec le code de réponse et le nom de la clé.

Questions fréquentes#

Peut-on appeler l'API depuis un navigateur ? Non : la clé donne accès à tous les prospects de l'établissement. Appelez l'API depuis votre serveur.

Quelle est la différence entre user_id et l'id du prospect ? L'id du prospect est notre identifiant de fiche. user_id est votre identifiant utilisateur (numéro dans le CRM, id du compte sur le site) ; avec ?by=user_id, la fiche peut être adressée par celui-ci.

Que se passe-t-il en cas d'envoi répété d'un événement ? Un événement avec le même id n'est compté qu'une fois — vous pouvez répéter la requête sans crainte en cas d'erreur réseau.

Faut-il une clé distincte pour chaque établissement ? Non : une seule clé peut fonctionner avec plusieurs établissements, l'établissement est choisi par le paramètre location.

Sections liées#

Was this article helpful?