C cenaly.com
Começar grátis

API pública e webhooks

Chaves com permissões, REST API de leads, propriedades, eventos, conversas e segmentos, webhooks de novos leads e eventos — com exemplos em curl

On this page 9

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#

  1. Abra Integrações e clique em API e webhooks no topo da página.
  2. Na aba Chaves, clique em Criar chave e digite um nome ("CRM", "Back-end do site", "Bot do Telegram").
  3. 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.
  4. 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 — 429 com o cabeçalho Retry-After. O restante fica em X-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#

Was this article helpful?