API público e webhooks
A API REST permite que seu CRM, o back-end do site ou seu próprio bot trabalhem com leads e diálogos do cenaly.com da mesma forma que o painel faz: ler fichas, alterar propriedades, enviar eventos, responder em diálogos. Os webhooks, por sua vez, avisam o seu servidor sobre novos leads, eventos e mensagens.
O que é necessário para começar#
| O quê | Onde |
|---|---|
| Papel | proprietário da conta — a chave age em nome dele; os funcionários não veem as chaves |
| Seção | chat habilitado (leads e diálogos ficam nele) |
| Chave | Integrações → API e webhooks → Chaves → Criar chave |
| Endereço da API | https://api.cenaly.com/public-api/v1 |
| Referência de métodos | api.cenaly.com/public-api/v1/docs |
| OpenAPI 3.1 | api.cenaly.com/public-api/v1/openapi.json |
Passo 1. Chave e permissões#
- Abra Integrações e clique em API e webhooks no topo da página.
- Na aba Chaves, clique em Criar chave e digite um nome ("CRM", "Back-end do site", "Bot do Telegram").
- Escolha um conjunto de permissões ou marque as permissões uma a uma; se houver várias unidades, indique a quais unidades a chave tem acesso, e o prazo.
- Copie o segredo
cnk_…. Ele é exibido uma única vez: guardamos apenas a sua impressão digital (SHA-256).
| Permissão | O que permite |
|---|---|
contacts:read |
lista, busca e ficha do lead, propriedades |
contacts:write |
alterar propriedades e tags, mesclar, excluir a pedido do titular |
events:read |
feed de eventos do lead |
events:write |
enviar eventos (compra, cadastro, qualquer evento seu) |
conversations:read |
diálogos e mensagens |
conversations:write |
resposta do operador, nota, status, responsável, etiquetas |
messages:send |
mensagem ao lead no último diálogo dele |
segments:read |
segmentos salvos e seus participantes |
Conjuntos: CRM / back-end (leads, propriedades, eventos, leitura de diálogos e segmentos), Bot próprio (lê leads, responde em diálogos, escreve para leads), Somente leitura, Tudo.
- Permissões alteram as permissões e as unidades da chave em tempo real — a integração continua funcionando.
- Reemitir gera um novo segredo; o antigo deixa de funcionar imediatamente, as permissões e o histórico permanecem.
- Revogar — imediatamente e para sempre; a próxima requisição receberá
401.
A chave é enviada no cabeçalho Authorization: Bearer cnk_… (ou X-Api-Key: cnk_…). Guarde-a apenas no servidor — não no navegador nem no aplicativo móvel.
Passo 2. Primeiras requisições#
KEY=cnk_seu_chave
API=https://api.cenaly.com/public-api/v1
# o que a chave pode fazer: permissões, unidades, limite
curl -H "Authorization: Bearer $KEY" "$API/me"
# leads, mais recentes primeiro (20 por página)
curl -H "Authorization: Bearer $KEY" "$API/contacts?limit=20"
# busca por nome, e-mail ou telefone
curl -H "Authorization: Bearer $KEY" "$API/contacts?q=anna"
A resposta é sempre um envelope:
{
"meta": { "status": 200, "requestId": "…", "nextCursor": "WyIyMDI2LTEwLTA0…" },
"data": { "total": 128, "contacts": [ { "id": "…", "status": "lead", "name": "Анна", "updatedAt": "2026-10-04T09:12:00Z" } ] }
}
A próxima página é a mesma requisição com cursor=<meta.nextCursor>; sem nextCursor — não há mais páginas. Erro — {"meta": {...}, "error": {"code": "…"}}.
Unidade. Se a chave tem acesso a uma única unidade, não é preciso indicá-la. Se houver várias — adicione location=<id da unidade> (lista — GET /v1/locations), caso contrário a resposta será 400 location_required.
Propriedades e eventos pelo seu user_id. Não é obrigatório guardar o nosso id do lead: adicione ?by=user_id e o endereço passará a ser o seu identificador de usuário. Se ainda não houver um lead com esse user_id — nós o criaremos.
# propriedades: operações 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"
# eventos em lote (até 100), repetição com o mesmo id é contada uma única vez
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"
# resposta em um diálogo e mudança de status
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"
A gravação passa pela mesma fila que as edições do painel: as alterações são aplicadas em segundos, e a resposta a uma gravação por user_id é 202 com pending. Na ficha do lead, o autor da edição aparece como "API:
Métodos#
| Método | O que faz | Permissão |
|---|---|---|
GET /v1/me, GET /v1/locations |
chave, permissões, unidades | — |
GET /v1/contacts |
leads: status (anon, lead, user), q, limit, cursor |
contacts:read |
GET /v1/contacts/{id} |
ficha: propriedades, tags, resumo de eventos | contacts:read |
POST /v1/contacts/{id}/props |
propriedades por operações (até 250) ou {"props":{…}} |
contacts:write |
POST / DELETE /v1/contacts/{id}/tags |
tags do lead | contacts:write |
POST /v1/contacts/merge |
fusão de duas fichas: prévia, depois "apply": true |
contacts:write |
POST /v1/contacts/{id}/erase |
exclusão a pedido do titular ("confirm": true) |
contacts:write |
GET /v1/contacts/{id}/events |
feed de eventos do lead | events:read |
POST /v1/contacts/{id}/events, POST /v1/events |
eventos (até 100 por vez) | events:write |
GET /v1/contacts/{id}/conversations |
conversas do lead | conversations:read |
POST /v1/contacts/{id}/messages |
escrever para o lead na última conversa dele | messages:send |
GET /v1/conversations, /{id}, /{id}/messages |
conversas e mensagens | conversations:read |
POST /v1/conversations/{id}/reply |
resposta do operador ou nota ("type": "note") |
conversations:write |
POST /v1/conversations/{id}/status, /assign, /tags |
status, responsável, marcadores | conversations:write |
GET /v1/segments, GET /v1/segments/{id}/contacts |
segmentos e seus participantes | segments:read |
Campos, exemplos e códigos de erro de cada método estão no guia de referência.
Etapa 3. Webhooks#
Os webhooks são configurados na unidade: Chat → Configurações → Webhooks — endereço https, eventos e segredo de assinatura. Aos eventos de conversa (nova conversa, nova mensagem, status, avaliação, marcadores) somaram-se os eventos de lead:
| Evento | Quando chega |
|---|---|
lead.created |
surgiu um novo lead (contato deixado no chat, no formulário ou criado via API) |
lead.props_changed |
as propriedades do lead mudaram — lista de chaves em changedProps |
lead.event_tracked |
o lead tem um evento; por padrão, todos os seus eventos sem os do sistema ($…), a lista de nomes é definida pelo campo "Quais eventos enviar" |
message.goal_reached |
o lead atingiu a meta da mensagem (pop-up, disparo) |
{
"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 } }
}
O nome, o e-mail e o telefone do lead entram no corpo somente se o webhook tiver a opção "Transmitir contatos do cliente" marcada. A verificação da assinatura é feita com HMAC-SHA256 do corpo usando o segredo do webhook:
# заголовок X-Meni-Signature: sha256=<hex>
echo -n "$BODY" | openssl dgst -sha256 -hmac "$SECRET"
Responda 2xx em 5 segundos — caso contrário, a entrega será repetida; após uma longa série de falhas, o webhook é desativado, e isso fica visível nas configurações. Filtre duplicatas pelo deliveryId.
Limitações#
- 60 requisições por minuto por chave; acima disso —
429com o cabeçalhoRetry-After. O restante fica emX-RateLimit-*. - Até 200 registros por página (50 por padrão), até 100 eventos por lote, até 250 operações com propriedades por requisição, até 30 tags por vez.
- Até 20 chaves ativas por conta.
- O log de chamadas da chave é mantido por 30 dias: hora, método, modelo de caminho (sem id e sem corpo), código de resposta, duração.
- Eventos enviados via API entram na ficha do lead (feed, resumo, segmentos), mas não no log bruto de análise de visitas.
- Só é possível escrever para o lead em uma conversa existente: sem conversa — resposta
409 no_conversation.
Solução de problemas#
| Resposta | O que significa | O que fazer |
|---|---|---|
401 api_key_missing / api_key_invalid |
a chave não está na requisição, ou está incorreta, revogada ou expirada | verifique o cabeçalho; se necessário, emita a chave novamente |
403 scope_required |
a chave não tem a permissão necessária | Permissões da chave — adicione a permissão |
400 location_required |
a chave tem acesso a várias unidades | adicione location=<id> |
404 location_not_found |
a unidade não está entre as unidades da chave | confira com GET /v1/locations |
404 not_found |
o lead ou a conversa não existe | para seus próprios ids, use ?by=user_id |
429 rate_limited |
mais de 60 requisições por minuto | aguarde Retry-After segundos, agrupe eventos em lotes |
502 upstream_error |
falha temporária | repita a requisição mais tarde |
Cada requisição aparece na aba Log de chamadas — com o código de resposta e o nome da chave.
Perguntas frequentes#
É possível chamar a API pelo navegador? Não: a chave dá acesso a todos os leads da unidade. Chame a API do seu servidor.
Qual é a diferença entre user_id e o id do lead? O id do lead é o nosso identificador da ficha. O user_id é o seu identificador de usuário (número no CRM, id da conta no site); com ?by=user_id a ficha pode ser endereçada por ele.
O que acontece ao reenviar um evento? Um evento com o mesmo id é contado uma única vez — pode repetir a requisição sem medo em caso de erro de rede.
É necessária uma chave separada para cada unidade? Não: uma chave pode trabalhar com várias unidades, a unidade é escolhida pelo parâmetro location.
Seções relacionadas#
- Chat com clientes — conversas, leads e configurações de webhooks
- Solicitações — fluxo de entrada unificado
- API e MCP do seu PABX — API de telefonia separada
- Integrações