API pubblica e webhook
L'API REST consente al vostro CRM, al backend del sito o al vostro bot di lavorare con i lead e le conversazioni di cenaly.com come fa il pannello: leggere le schede, modificare le proprietà, inviare eventi, rispondere nelle conversazioni. I webhook, al contrario, informano direttamente il vostro server di nuovi lead, eventi e messaggi.
Cosa serve per iniziare#
| Cosa | Dove |
|---|---|
| Ruolo | proprietario dell'account — la chiave agisce a suo nome; i dipendenti non vedono le chiavi |
| Sezione | chat abilitata (lead e conversazioni vivono al suo interno) |
| Chiave | Integrazioni → API e webhook → Chiavi → Crea chiave |
| Indirizzo API | https://api.cenaly.com/public-api/v1 |
| Riferimento ai metodi | api.cenaly.com/public-api/v1/docs |
| OpenAPI 3.1 | api.cenaly.com/public-api/v1/openapi.json |
Passo 1. Chiave e permessi#
- Aprite Integrazioni e premete API e webhook nell'intestazione della pagina.
- Nella scheda Chiavi premete Crea chiave, inserite un nome («CRM», «Backend del sito», «Bot Telegram»).
- Scegliete un insieme di permessi o selezionate i permessi uno per uno, in presenza di più sedi — a quali sedi la chiave è autorizzata, e la scadenza.
- Copiate il segreto
cnk_…. Viene mostrato una sola volta: da noi è conservata solo la sua impronta (SHA-256).
| Permesso | Cosa consente |
|---|---|
contacts:read |
elenco, ricerca e scheda del lead, proprietà |
contacts:write |
modificare proprietà e tag, unire, eliminare su richiesta dell'interessato |
events:read |
flusso di eventi del lead |
events:write |
inviare eventi (acquisto, registrazione, qualsiasi evento proprio) |
conversations:read |
conversazioni e messaggi |
conversations:write |
risposta dell'operatore, nota, stato, responsabile, etichette |
messages:send |
messaggio al lead nella sua ultima conversazione |
segments:read |
segmenti salvati e i loro partecipanti |
Insiemi: CRM / backend (lead, proprietà, eventi, lettura di conversazioni e segmenti), Bot proprio (legge i lead, risponde nelle conversazioni, scrive ai lead), Solo lettura, Tutto.
- Permessi modificano al volo i permessi e le sedi della chiave — l'integrazione continua a funzionare.
- Rigenera rilascia un nuovo segreto; il vecchio smette di funzionare subito, i permessi e il registro restano.
- Revoca — subito e per sempre, la richiesta successiva riceverà
401.
La chiave viene trasmessa con l'intestazione Authorization: Bearer cnk_… (o X-Api-Key: cnk_…). Conservatela solo sul server — non nel browser e non nell'app mobile.
Passo 2. Prime richieste#
KEY=cnk_ваш_ключ
API=https://api.cenaly.com/public-api/v1
# что умеет ключ: права, точки, лимит
curl -H "Authorization: Bearer $KEY" "$API/me"
# лиды, свежие сверху (20 на страницу)
curl -H "Authorization: Bearer $KEY" "$API/contacts?limit=20"
# поиск по имени, почте или телефону
curl -H "Authorization: Bearer $KEY" "$API/contacts?q=anna"
La risposta è sempre un involucro:
{
"meta": { "status": 200, "requestId": "…", "nextCursor": "WyIyMDI2LTEwLTA0…" },
"data": { "total": 128, "contacts": [ { "id": "…", "status": "lead", "name": "Анна", "updatedAt": "2026-10-04T09:12:00Z" } ] }
}
La pagina successiva è la stessa richiesta con cursor=<meta.nextCursor>; se manca nextCursor — non ci sono altre pagine. Errore — {"meta": {...}, "error": {"code": "…"}}.
Sede. Se alla chiave è accessibile una sola sede, non è necessario indicarla. Se ce ne sono diverse — aggiungete location=<id sede> (elenco — GET /v1/locations), altrimenti la risposta sarà 400 location_required.
Proprietà ed eventi tramite il vostro user_id. Non è obbligatorio conservare il nostro id del lead: aggiungete ?by=user_id, e l'indirizzo diventerà il vostro identificatore utente. Se un lead con questo user_id non esiste ancora — lo creeremo.
# свойства: операции 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"
# события пачкой (до 100), повтор с тем же id засчитывается один раз
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"
# ответ в диалоге и смена статуса
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"
La scrittura passa attraverso la stessa coda delle modifiche dal pannello: le modifiche vengono applicate in pochi secondi, e la risposta alla scrittura tramite user_id è 202 con pending. Nella scheda del lead l'autore della modifica è visibile come «API:
Metodi#
| Metodo | Cosa fa | Autorizzazione |
|---|---|---|
GET /v1/me, GET /v1/locations |
chiave, autorizzazioni, sedi | — |
GET /v1/contacts |
lead: status (anon, lead, user), q, limit, cursor |
contacts:read |
GET /v1/contacts/{id} |
scheda: proprietà, tag, riepilogo eventi | contacts:read |
POST /v1/contacts/{id}/props |
proprietà tramite operazioni (fino a 250) oppure {"props":{…}} |
contacts:write |
POST / DELETE /v1/contacts/{id}/tags |
tag del lead | contacts:write |
POST /v1/contacts/merge |
unione di due schede: anteprima, poi "apply": true |
contacts:write |
POST /v1/contacts/{id}/erase |
cancellazione su richiesta dell'interessato ("confirm": true) |
contacts:write |
GET /v1/contacts/{id}/events |
flusso eventi del lead | events:read |
POST /v1/contacts/{id}/events, POST /v1/events |
eventi (fino a 100 alla volta) | events:write |
GET /v1/contacts/{id}/conversations |
conversazioni del lead | conversations:read |
POST /v1/contacts/{id}/messages |
scrivere al lead nella sua ultima conversazione | messages:send |
GET /v1/conversations, /{id}, /{id}/messages |
conversazioni e messaggi | conversations:read |
POST /v1/conversations/{id}/reply |
risposta dell'operatore o nota ("type": "note") |
conversations:write |
POST /v1/conversations/{id}/status, /assign, /tags |
stato, responsabile, etichette | conversations:write |
GET /v1/segments, GET /v1/segments/{id}/contacts |
segmenti e relativi partecipanti | segments:read |
Campi, esempi e codici di errore di ogni metodo sono nella documentazione di riferimento.
Passaggio 3. Webhook#
I webhook si configurano per sede: Chat → Impostazioni → Webhook — indirizzo https, eventi e segreto della firma. Agli eventi della conversazione (nuova conversazione, nuovo messaggio, stato, valutazione, etichette) si sono aggiunti gli eventi del lead:
| Evento | Quando arriva |
|---|---|
lead.created |
è comparso un nuovo lead (contatto lasciato in chat, in un modulo o creato tramite API) |
lead.props_changed |
sono cambiate le proprietà del lead — elenco delle chiavi in changedProps |
lead.event_tracked |
il lead ha un evento; per impostazione predefinita tutti i vostri eventi senza quelli di sistema ($…), l'elenco dei nomi si imposta con il campo «Quali eventi inviare» |
message.goal_reached |
il lead ha raggiunto l'obiettivo del messaggio (pop-up, invio massivo) |
{
"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 } }
}
Nome, email e telefono del lead finiscono nel corpo solo se nel webhook è attiva la casella «Trasmettere i contatti dell'ospite». Verifica della firma — HMAC-SHA256 del corpo con il segreto del webhook:
# заголовок X-Meni-Signature: sha256=<hex>
echo -n "$BODY" | openssl dgst -sha256 -hmac "$SECRET"
Rispondete 2xx entro 5 secondi — altrimenti la consegna verrà ripetuta; dopo una lunga serie di errori il webhook viene disattivato e questo è visibile nelle impostazioni. I duplicati vanno filtrati tramite deliveryId.
Limiti#
- 60 richieste al minuto per chiave; oltre tale soglia —
429con l'intestazioneRetry-After. Il residuo è inX-RateLimit-*. - Fino a 200 record per pagina (per impostazione predefinita 50), fino a 100 eventi per lotto, fino a 250 operazioni sulle proprietà per richiesta, fino a 30 tag alla volta.
- Fino a 20 chiavi attive per account.
- Il registro delle chiamate della chiave viene conservato per 30 giorni: ora, metodo, modello del percorso (senza id e corpo), codice di risposta, durata.
- Gli eventi inviati tramite API finiscono nella scheda del lead (flusso, riepilogo, segmenti), ma non nel registro grezzo dell'analisi delle visite.
- Si può scrivere al lead solo in una conversazione esistente: se non c'è una conversazione — risposta
409 no_conversation.
Risoluzione dei problemi#
| Risposta | Cosa significa | Cosa fare |
|---|---|---|
401 api_key_missing / api_key_invalid |
la chiave non è nella richiesta, oppure non è valida, è stata revocata o è scaduta | verificate l'intestazione; se necessario riemettete la chiave |
403 scope_required |
la chiave non ha l'autorizzazione necessaria | Autorizzazioni della chiave — aggiungete l'autorizzazione |
400 location_required |
alla chiave sono accessibili più sedi | aggiungete location=<id> |
404 location_not_found |
la sede non è tra le sedi della chiave | verificate con GET /v1/locations |
404 not_found |
il lead o la conversazione non esiste | per i vostri id usate ?by=user_id |
429 rate_limited |
più di 60 richieste al minuto | attendete Retry-After secondi, raggruppate gli eventi in lotti |
502 upstream_error |
guasto temporaneo | ripetete la richiesta più tardi |
Ogni richiesta è visibile nella scheda Registro delle chiamate — con il codice di risposta e il nome della chiave.
Domande frequenti#
Si può chiamare l'API dal browser? No: la chiave dà accesso a tutti i lead della sede. Chiamate l'API dal vostro server.
In cosa differisce user_id dall'id del lead? L'id del lead è il nostro identificatore della scheda. user_id è il vostro identificatore dell'utente (numero nel CRM, id dell'account sul sito); con ?by=user_id la scheda può essere indirizzata tramite esso.
Cosa succede se si invia di nuovo un evento? Un evento con lo stesso id viene conteggiato una sola volta — potete ripetere tranquillamente la richiesta in caso di errore di rete.
Serve una chiave separata per ogni sede? No: una chiave può lavorare con più sedi, la sede si sceglie con il parametro location.
Sezioni correlate#
- Chat con gli ospiti — conversazioni, lead e impostazioni dei webhook
- Richieste — flusso in entrata unificato
- API e MCP del proprio centralino — API separata per la telefonia
- Integrazioni