BoaVoz
Documentação · Integrações

Identificar usuários

Quando a empresa diz ao BoaVoz quem é a pessoa, as ações dela recebem o contato no nível usuário, com o id da pessoa no seu sistema e a conta ativa. É o que libera saldo, segunda via e dados da conta na conversa.

Dois caminhos

OndeComoQuando usar
Chat do siteToken assinado pelo seu servidor, entregue ao widget.A pessoa já está logada no seu site.
WhatsApp e InstagramPareamento: seu sistema gera um código, a pessoa manda “Conectar ABC123” para o chatbot.Ligar o número (ou a conta do Instagram) à conta dela, uma vez.
Dentro de um appO mesmo token do site, numa webview com o chat em tela cheia (Chat dentro de apps).A pessoa está logada no seu app.

Nos dois, a IA vê só o nome de exibição e nunca pede documento ou senha: a identidade já foi confirmada pela empresa. As ações recebem contact.level = "usuario", o external_id e o context.

Token no chat do site

O segredo de identidade

O token é um JWT assinado com HS256 com o segredo de identidade da agência, que tem um id (kid) e vale para um chatbot, para os chatbots de um cliente ou para todos. Por enquanto, quem gera esse segredo é a equipe do BoaVoz: peça pelo suporte. A tela para gerar e revogar no painel vem a seguir.

O que vai no token

CampoRegra
kidNo cabeçalho do JWT: o id do segredo. alg sempre HS256 (outro algoritmo é recusado).
audA chave do widget (o data-key do script).
iat e expEm segundos. exp no máximo 1 hora e 1 minuto à frente (folga de 60 s no relógio).
external_idO id da pessoa no seu sistema (até 128 caracteres). Sem ele, o token só define o contexto e a pessoa segue anônima.
user_displayO que a IA pode usar para tratar a pessoa, por exemplo {"name": "Ruan"} (até 512 bytes).
contextA conta ativa (workspace, loja), em JSON de até 2 KB. Vai só para as ações.
context_displayComo a conta aparece na conversa (até 120 caracteres).
age_verifiedOpcional: true se o seu cadastro já conferiu que a pessoa tem 18 anos.
javascript · node
// npm i jsonwebtoken — no SEU servidor, depois do login (nunca no navegador)
import jwt from "jsonwebtoken";

app.get("/api/chat-token", exigeLogin, (req, res) => {
  const token = jwt.sign(
    {
      external_id: req.user.id,                       // o id dela no seu sistema
      user_display: { name: req.user.primeiroNome },  // o que a IA pode chamar
      context: { workspace_id: req.workspace.id },     // a conta ativa (vai só para as ações)
      context_display: req.workspace.nome,             // como a conta aparece na conversa
    },
    process.env.BOAVOZ_IDENTITY_SECRET,
    { algorithm: "HS256", keyid: process.env.BOAVOZ_IDENTITY_KID, audience: "CHAVE_DO_WIDGET", expiresIn: "1h" },
  );
  res.type("text/plain").send(token);
});
python
# pip install PyJWT — no SEU servidor, depois do login
import os, time, jwt

def chat_token(usuario, workspace):
    agora = int(time.time())
    return jwt.encode(
        {
            "aud": "CHAVE_DO_WIDGET",
            "iat": agora,
            "exp": agora + 3600,
            "external_id": usuario.id,
            "user_display": {"name": usuario.primeiro_nome},
            "context": {"workspace_id": workspace.id},
            "context_display": workspace.nome,
        },
        os.environ["BOAVOZ_IDENTITY_SECRET"],
        algorithm="HS256",
        headers={"kid": os.environ["BOAVOZ_IDENTITY_KID"]},
    )

No site

html
<script>
  window.ChatWidgetConfig = {
    // chamado ao abrir o chat e 5 minutos antes de o token vencer
    getToken: async () => (await fetch("/api/chat-token")).text(),
  };
</script>
<script src="https://SEU-DOMINIO/widget.js" data-key="CHAVE_DO_WIDGET" async></script>

<script>
  // a pessoa entrou depois de a página carregar o widget
  ChatWidget.identify(() => fetch("/api/chat-token").then((r) => r.text()));
  // trocou de conta: abre uma conversa nova, no contexto novo
  ChatWidget.setContext(novoToken);
  // saiu: limpa a tela (a conversa já é protegida pelo token)
  ChatWidget.logout();
</script>
  • O token vai só para o iframe do chat e é conferido em toda requisição.
  • A conversa de uma pessoa fica presa a ela e ao contexto: outra pessoa no mesmo navegador, sem sair, não vê nada da primeira.
  • Uma conversa anônima vira da pessoa uma vez, quando ela entra; depois, nunca troca de dono nem de contexto.

Pareamento no WhatsApp e no Instagram

  1. Seu sistema chama POST /v1/pairings com external_id, context e display (veja a referência) e recebe o código e o link.
  2. A pessoa abre o link no celular: o WhatsApp abre com “Conectar ABC123” escrito (no Instagram, o link leva o código, ou ela digita o código na DM). Ela manda e confirma.
  3. O BoaVoz liga o contato à conta dela e emite o webhook contact.linked. Daí em diante, as ações recebem o nível usuário nesse canal.
  • O código tem 6 caracteres, vale 10 minutos e uma vez só.
  • Com expected_phone (WhatsApp), código mandado de outro número é recusado.
  • Mais de 5 códigos errados de um contato em 1 hora bloqueiam novas tentativas por um tempo.
  • Se o número já estava ligado a outra conta, o BoaVoz pede confirmação antes de trocar.
  • Cada conversa nova começa por “Estou falando com <name do display>?”, com Sim, sou eu e Sou outra pessoa, antes de a IA e as ações usarem a conta; a mensagem que chegou espera a resposta. O sim vale 24 horas na conversa. “Sou outra pessoa” deixa a conversa sem a conta e o vínculo continua. Quem acabou de mandar o código na conversa não é perguntado. A loja desliga em Roteiros → Confirmar quem foi conectado pelo código: aí a conta vale direto em toda conversa.
  • A pessoa pode ter várias contas ligadas; uma fica ativa. Se ela pedir para trocar, a IA troca, e a conversa abre um trecho novo (a IA só lê o que veio depois).
  • “desconectar” no chat desfaz o vínculo ativo (webhook contact.unlinked). Pela API: DELETE /v1/contacts/{contact}/links/{id}.
O que a IA vê e o que as ações recebem
A IA vê o nome de exibição e o nome da conta ativa, para tratar a pessoa e citar a conta nas respostas. O external_id e o context vão só para as suas ações.