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
| Onde | Como | Quando usar |
|---|---|---|
| Chat do site | Token assinado pelo seu servidor, entregue ao widget. | A pessoa já está logada no seu site. |
| WhatsApp e Instagram | Pareamento: 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 app | O 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
| Campo | Regra |
|---|---|
kid | No cabeçalho do JWT: o id do segredo. alg sempre HS256 (outro algoritmo é recusado). |
aud | A chave do widget (o data-key do script). |
iat e exp | Em segundos. exp no máximo 1 hora e 1 minuto à frente (folga de 60 s no relógio). |
external_id | O id da pessoa no seu sistema (até 128 caracteres). Sem ele, o token só define o contexto e a pessoa segue anônima. |
user_display | O que a IA pode usar para tratar a pessoa, por exemplo {"name": "Ruan"} (até 512 bytes). |
context | A conta ativa (workspace, loja), em JSON de até 2 KB. Vai só para as ações. |
context_display | Como a conta aparece na conversa (até 120 caracteres). |
age_verified | Opcional: 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
- Seu sistema chama
POST /v1/pairingscomexternal_id,contextedisplay(veja a referência) e recebe o código e o link. - 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.
- 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.