Referência: a API pública de conversas do chat, para uma tela de Conversas no seu sistema

Esta é a referência para quem quer mostrar, dentro do próprio sistema, as conversas que uma pessoa teve com o chat: um menu "Conversas" com busca, a leitura de cada conversa e o botão de continuar de onde parou, no estilo dos assistentes de IA do mercado. Se você está começando, leia antes Chat (widget do site) e Verificação de identidade. O que a pessoa vê no widget está em Conversas anteriores.

Integrando com uma IA de programação? O guia GET /api/v1/public/chat/llms.txt?key=A-CHAVE-DO-SEU-CHAT traz esta mesma referência já preenchida com a sua chave e os seus endereços, na seção "Tela Conversas no seu sistema".

O atalho: o chat como tela inteira (mode: 'page')

Se o que você quer é um item Conversas no menu do seu sistema, não precisa montar lista nenhuma: o próprio chat tem um modo de tela inteira, no formato dos assistentes de IA do mercado. Barra lateral com as conversas da pessoa (busca por texto e Nova conversa), tela inicial com as sugestões do canal e a conversa ocupando o resto. No celular a barra vira uma gaveta.

<div id="conversas" style="height: calc(100vh - 64px)"></div>
<script src="ENDERECO-DO-CHAT/widget/chat.js"
data-key="A-CHAVE-DO-SEU-CHAT"
data-mode="page"
data-container="#conversas"
data-auth="..." data-sig="..."></script>

Ou por JavaScript: Chat.init({ key, mode: 'page', container: '#conversas', auth, sig }). Sem container, a tela ocupa a janela inteira. A identidade assinada é o que faz a lista acompanhar a pessoa em qualquer navegador; sem ela, aparecem só as conversas daquele navegador.

Dois métodos acompanham o modo, para quem prefere desenhar a lista do próprio jeito e usar o chat só para a conversa: Chat.resume(token) abre o chat já numa conversa da lista (o token é o da API abaixo) e Chat.newConversation() começa outra sem encerrar a atual.

O resto desta página é para quem quer montar a lista fora do widget, com a API.

Antes de tudo: qual API é esta

A API de atendimento tem uma listagem de conversas, GET /api/v1/tickets/conversations, mas ela é do painel da sua equipe: devolve a conta inteira, de todos os seus clientes, e inclui notas internas. Ela não serve para uma tela voltada ao usuário do seu sistema, porque cada pessoa veria a conversa das outras.

A API desta página é a pública do chat, a mesma que o widget usa. Ela não recebe chave de API: quem identifica a pessoa é a identidade assinada do seu site, e por isso ela só devolve o que é daquela pessoa.

Regras que valem para todas as chamadas

  • Endereço base: o mesmo da API, https://SEU-ENDERECO-DA-API/api/v1.
  • Sem Authorization. Chave de API é ignorada nestas rotas.
  • key (obrigatório, na query string): a chave do canal de chat, a mesma do data-key do código de instalação.
  • auth e sig (na query string, não em header): o mesmo par da Verificação de identidade. auth é o payload em base64, sig é o HMAC-SHA256 hexadecimal calculado sobre o base64, com o segredo do canal.
  • O payload precisa ter email. É por ele que a plataforma encontra o contato e as conversas dele. user_ref ou subaccount_ref sozinhos não listam nada.
  • O escopo é a pessoa, não a empresa. Dois usuários da mesma empresa não veem as conversas um do outro.
  • Identidade inválida não dá erro: a lista vem vazia, com status 200. Para a sua tela distinguir "assinatura errada" de "sem conversas", valide o par uma vez por sessão com POST /api/v1/public/chat/verify-identity enviando { key, auth, sig }. A resposta é { "valid": true, "payload": {...} } ou { "valid": false, "reason": "..." }.
  • A assinatura não expira. O payload não tem data; só a rotação do segredo a invalida.

1. Listar as conversas da pessoa

GET /api/v1/public/chat/conversations?key=...&auth=...&sig=...
ParâmetroObrigatórioO que faz
keysimchave do canal de chat
auth, sigsimidentidade assinada
qnãobusca por texto no assunto e nas mensagens, termo parcial, só dentro das conversas dessa pessoa
beforenãocursor da próxima página: o next_cursor da resposta anterior

Não existe page, per_page nem filtro de situação. A página tem sempre 10 conversas, a janela é de 90 dias e cada conversa aparece uma vez (retomadas não duplicam).

{
"conversations": [
{
"token": "8f1c2b4e-6d3a-4a51-9b0e-2f7c1d5e9a10",
"subject": "Cadastro de fornecedor",
"preview": "Não consegui resolver isso agora. Pode reformular a pergunta?",
"last_at": "2026-08-28 23:26:15",
"status": "open"
}
],
"next_cursor": 48213
}
CampoTipoSignificado
tokentextoidentifica a conversa; vai no endereço de leitura e é o resume_token para continuar
subjecttextoassunto; nunca vazio
previewtextoúltima mensagem pública (nota interna nunca entra), texto puro, até 80 caracteres; pode ser vazio
last_attextodata da última mensagem, no formato AAAA-MM-DD HH:MM:SS, em UTC
statusopen ou endedem aberto ou encerrada
next_cursornúmero ou nullpasse em before para a próxima página; null quando acabou

2. Ler uma conversa

GET /api/v1/public/chat/conversations/{token}/messages?key=...&auth=...&sig=...

Devolve até 200 mensagens, em ordem cronológica, e só as públicas. Sem paginação. Cada mensagem tem o mesmo formato que o widget recebe:

{
"id": 91234,
"author_type": "contact",
"author": "Ana",
"visibility": "public",
"channel": "chat",
"body": "Como cadastro um fornecedor?",
"created_at": "2026-08-28T23:14:02.000000Z",
"feedbackable": false,
"feedback": null,
"agent": null,
"turn_id": null,
"quick_replies": null,
"buttons": null,
"notice": null,
"pending_action": null,
"attachments": []
}
  • author_type: contact (a pessoa), user (alguém da sua equipe), agent (agente de IA) ou system.
  • body: as respostas da IA vêm em Markdown (com tabelas); renderize.
  • created_at: ISO 8601 em UTC. Repare que é um formato diferente do last_at da lista.
  • feedbackable é true só em resposta da IA; feedback é up, down ou null. Em conversa antiga não há como registrar feedback pela API.
  • agent: { first_name, photo_url } quando um humano respondeu e o canal apresenta a equipe; null no resto.
  • attachments: lista de { id, name, mime, size, url, kind, duration_ms, transcript }.
  • notice: cartão de estado que o widget mostra quando a IA para, em mensagem author_type: "system": { kind, title, text }. kind é identify (precisa entrar na conta), queued (entregue à equipe) ou limit (a IA não continua e não há equipe). No limit, o title "Limite de uso deste mês atingido" é o teto mensal da pessoa (user_ref) definido pelo administrador dela em Subcontas; se a sua tela quer o número, GET /subaccounts/{id}/usage traz debited_credits e limit_credits por user_ref.

3. Continuar de onde parou

POST /api/v1/public/chat/sessions
{ "key": "...", "auth": "...", "sig": "...", "resume_token": "8f1c2b4e-6d3a-4a51-9b0e-2f7c1d5e9a10" }

→ { "token": "TOKEN-DA-SESSAO-NOVA", "brand": { ... } }

Abre uma sessão nova ligada à mesma conversa. Daí em diante use o token novo em POST e GET /api/v1/public/chat/sessions/{token}/messages, exatamente como o widget faz. Se a conversa reabre ou vira um acompanhamento vinculado, é a plataforma quem decide, na primeira mensagem. O resume_token não expira.

Se o seu sistema já tem o widget instalado, Chat.openConversations() abre a mesma lista pronta dentro dele, sem chamada nenhuma.

Erros

SituaçãoStatusCorpo
key inválida404{ "error": "widget_not_found" }
auth/sig ausente, inválido ou assinado com segredo antigo200{ "conversations": [], "next_cursor": null }
token que não é dessa pessoa, inexistente ou de outro canal404{ "error": "not_found" } (nunca 403, para não confirmar que a conversa existe)
acima do limite de chamadas429{ "message": "Too Many Attempts." }

Limites

  • Limite por IP e por rota, não por pessoa: listar 30 por minuto, ler 60, abrir sessão 10, validar identidade 20.
  • Se o seu servidor chama em nome de todos os usuários, ele compartilha um IP só. Chame no clique do menu, nunca na carga da página, e guarde a lista alguns segundos por usuário.
  • 10 conversas por página, 200 mensagens por conversa, 90 dias de janela.

Perguntas frequentes

Dá para listar as conversas da empresa inteira, e não só do usuário? Hoje não. A lista é da pessoa identificada. Para uma visão da equipe, o lugar é o painel, em Atendimento › Conversas.

Por que a identidade errada não devolve erro? Porque o histórico é dado pessoal. Uma resposta diferente para "assinatura errada" e "essa pessoa não existe" ajudaria alguém a testar identidades. Use o verify-identity para validar o seu código.

A chave de API da minha conta funciona aqui? Não, e nem deve: ela daria acesso a tudo. Estas rotas só entendem a identidade assinada.