Sessão do embed

Como o Insights autentica — POST /session, o header x-ext-session e os modos de falha.

🚧

Esta página não é sobre a API da plataforma

Para chamar Core, CRM ou Chat — contatos, conversas, funil, mensagens — a
autenticação é Authorization: Bearer pn_…, e está em
Autenticação. O que segue vale só para a camada de
Insights embutida como menu.

O Insights não tem login. Não há usuário, senha nem recuperação de acesso. O que
faz as vezes disso é POST /session, e ele autentica o contexto do embed,
não uma pessoa.

Os três parâmetros

Vêm da query do iframe, e cada um é checado de um jeito diferente:

campoo que écomo é validado
cidId público do cliente (ext_…)Tem que existir no registry de tenants
haId da conta na plataformaComparado com o registrado para aquele cid, em tempo constante
huId do usuário na plataformaConsultado na API da plataforma, com o token server-side do tenant

Nenhum dos três é segredo — todos aparecem na URL do iframe. O que autentica é o
servidor conseguir resolvê-los: contra o registry e contra a API da plataforma.
Os segredos do tenant nunca saem do backend.

Emitir a sessão

curl -X POST https://ext.allbound.ia.br/session \
  -H "Content-Type: application/json" \
  -d '{
        "cid": "ext_9dK2mPq7XrT4vBnW",
        "hu":  "<id do usuário na plataforma>",
        "ha":  "<id da conta na plataforma>"
      }'
{ "sessionToken": "eyJhbGciOiJIUzI1NiJ9…", "expiresIn": 3600 }

expiresIn vem em segundos — a sessão dura 1 hora. Expirou, chame
/session de novo com os mesmos três parâmetros.

Usar a sessão

O token vai no header x-ext-session. Não é Authorization, e não é
Bearer:

curl https://ext.allbound.ia.br/api/v1/analytics/tickets \
  -H "x-ext-session: eyJhbGciOiJIUzI1NiJ9…"

O Insights valida o token, resolve o tenant e troca essa credencial pela dele antes de
falar com a Allbound IA. O x-ext-session é removido na saída — ele nunca
chega ao destino.

Junto vai o id do usuário da plataforma, o que faz o histórico do chat de
Insights ficar isolado por pessoa: cada usuário da plataforma vê as próprias conversas,
não as dos colegas.

Onde guardar o token

Em memória. O Insights roda em iframe, que é contexto de terceiro — cookies são
bloqueados pelo navegador, e localStorage deixaria o token sobreviver ao
fechamento da aba sem necessidade. Ele vale uma hora e é barato de reemitir.

Modos de falha

A recusa nunca diz o motivo. Tenant inexistente, conta que não bate, usuário
inválido — todos devolvem exatamente a mesma resposta:

403  { "error": "account_not_found" }

Isso é deliberado: distinguir os casos permitiria descobrir quais cid existem.
O motivo real sai no log estruturado do servidor, no campo reason do evento
session_denied. Se você está depurando, é no log que olha, não na resposta.

Uma recusa cai sempre em um destes casos:

  • O cid não está registrado.
  • O ha não corresponde à conta registrada para aquele cid.
  • O hu não existe naquela conta.
  • Faltou cid, hu ou ha no corpo.
  • Mais de 30 tentativas no último minuto, do mesmo IP.
  • A API da plataforma não respondeu — rede, ou token do tenant inválido.

Na prática, os dois primeiros respondem pela maioria: quase sempre o ha foi
copiado de outra conta.

E nas chamadas a /api/*:

CódigoCorpoCausa
401{"error":"session_required"}Header x-ext-session ausente ou vazio
401{"error":"session_invalid"}Token expirado, assinatura inválida, ou o tenant saiu do registry depois da emissão

Detalhes que pegam

Rate limit: 30 tentativas por minuto por IP, em memória.

Sec-Fetch-Dest: se o header chegar com valor diferente de empty, a
requisição é recusada. É proteção contra navegação direta ou envio de formulário
para /session. Clientes que não mandam o header — curl, por exemplo — passam
normalmente; é camada extra, não a autenticação em si.

Risco residual conhecido: a plataforma não assina a URL do iframe, só
interpola os dois identificadores. Quem conhecer uma trinca cid/hu/ha
válida consegue emitir sessão fora do iframe. Os três não são segredo, mas
também não são públicos — tratá-los como dado interno é o comportamento certo.


Did this page help you?