Webhooks
Como as conversas chegam ao Insights e como a limpeza diária de etiquetas é alimentada.
O Insights recebe dois webhooks da plataforma. Os dois usam a mesma autenticação e o
mesmo envelope; mudam o evento e o que fazem com ele.
Autenticação
Credencial na própria URL, mais allowlist de IP:
POST https://ext.allbound.ia.br/webhooks/<rota>?client_id=ext_…&token=<segredo do webhook>
O client_id identifica o tenant e é público. O token é o segredo — aceitável
em URL porque ela é configurada no admin da plataforma e nunca passa por
browser. A comparação é em tempo constante.
Falha de qualquer um dos dois, ou IP fora da allowlist, devolve
401 {"error":"unauthorized"} — sem distinguir o motivo. O log do Insights registra
qual foi (ip_not_allowed, unknown_client_id, bad_token).
Envelope
Os dois esperam o formato da plataforma:
{
"eventType": "SESSION_COMPLETE",
"content": { "id": "…", "status": "COMPLETED" }
}Sem eventType string ou sem content objeto →
400 {"error":"Envelope inválido: esperado { eventType, content }"}.
1. Ingestão de conversas
POST /webhooks/partner-crm
É o que alimenta o Insights. Sem esta assinatura o produto fica no ar e vazio.
Evento a assinar: Atendimento concluído.
Só o fechamento dispara ingestão. O Insights aceita SESSION_COMPLETE diretamente, e
SESSION_UPDATE apenas quando content.status é COMPLETED.
Respostas:
| Código | Corpo | Quando |
|---|---|---|
202 | {"status":"accepted"} | Atendimento concluído, ingestão iniciada |
200 | {"status":"ignored"} | Outro evento, ou sem id de sessão |
400 | erro de envelope | eventType/content ausentes ou com tipo errado |
401 | {"error":"unauthorized"} | Credencial ou IP |
O 202 responde antes do trabalho. O Insights confirma o recebimento e só então
busca a transcrição na plataforma e a envia para análise, em background. Isso
mantém a resposta rápida e evita que a plataforma interprete lentidão como
falha e desative a assinatura — mas significa que 202 não é garantia de que a
conversa foi analisada. Falhas posteriores aparecem no log do Insights, não na
resposta do webhook.
Eventos não reconhecidos recebem 200 de propósito, pelo mesmo motivo: um 4xx
repetido leva a plataforma a desativar a assinatura.
Fetch-on-close
O webhook carrega só o identificador da sessão. É o Insights que busca a conversa
completa na API da plataforma, com o token do tenant. Isso mantém o payload
pequeno e garante que a transcrição analisada é a versão final, não o que estava
montado no instante do disparo.
Reprocessar é seguro: a mesma conversa reenviada não duplica análise. Transcrição
idêntica é ignorada; conteúdo novo — a conversa foi reaberta e concluída de novo —
atualiza o registro existente.
2. Fila de limpeza de etiquetas
POST /webhooks/update-contact
Serve a uma rotina de manutenção: certas etiquetas são operacionais e não devem
ficar grudadas no contato depois do dia. Este webhook enfileira quem as recebeu;
um job diário as remove.
Evento a assinar: atualização de etiquetas do contato.
O Insights olha as etiquetas do contato no evento e as compara com a lista
configurada para o ambiente. Só contatos com pelo menos uma delas entram na fila.
Respostas:
| Código | Corpo | Quando |
|---|---|---|
200 | {"status":"queued"} | Contato enfileirado |
200 | {"status":"ignored","reason":"no_watched_tags"} | Nenhuma etiqueta monitorada |
200 | {"status":"ignored"} | Evento fora dos aceitos |
400 | id do contato ausente | O evento não trouxe id reconhecível |
401 | {"error":"unauthorized"} | Credencial ou IP |
500 | {"error":"queue_write_failed"} | Falha ao gravar na fila |
Diferente da ingestão, aqui o Insights grava antes de responder. A escrita é curta,
e responder antes correria o risco de o processo ser suspenso sem completá-la. O
500 é intencional: faz a plataforma tentar de novo.
A remoção não é imediataO webhook só enfileira. A limpeza acontece no fim do dia, em lote. Um contato
que ganhou a etiqueta às 9h ainda a terá às 15h — isso é o desenho, não atraso.
Updated about 2 hours ago
