Skip to main content
O Pilot Status possui uma integração nativa com o Chatwoot: conecte qualquer número de WhatsApp a uma conta Chatwoot e as conversas sincronizam bidirecionalmente — mensagens recebidas do WhatsApp aparecem no Chatwoot, e as respostas dos agentes no Chatwoot são entregues no WhatsApp.
Página do Chatwoot do Pilot Status

A página do Chatwoot — status da conexão, alternância de espelhamento, IDs de inbox/conta, reconectar e atualização de credenciais.

Pré-requisito: FRONTEND_URL (Chatwoot self-hosted)

Se você executa um Chatwoot self-hosted, a variável de ambiente FRONTEND_URL deve estar configurada antes de conectar:
  • Use a URL pública exata (mesmo esquema/host do navegador), sem barra no final, acessível pela internet — nunca localhost nem um IP interno.
  • Reinicie ambos os containers web e sidekiq depois (o Rails deriva default_url_options[:host] a partir dela na inicialização).
Sem FRONTEND_URL, o Chatwoot não consegue construir URLs absolutas de anexos nem webhooks de saída válidos. Sintomas no Pilot Status: mensagens marcadas como “Falha ao enviar”, mídia nunca entregue, e ArgumentError: Missing host to link to! nos logs do Chatwoot/sidekiq.
Para validar: envie uma mensagem com um anexo em uma conversa de teste — nenhum Missing host to link to! nos logs, a mensagem aparece como enviada no Pilot Status, e a mídia chega no WhatsApp.

Configurar a integração

A integração é configurada por número na página Chatwoot do painel do Pilot Status.
1

Reúna três credenciais do Chatwoot

  • Instance URL — a URL base do seu Chatwoot (ex.: https://chatwoot.your-domain.com ou https://app.chatwoot.com).
  • Account ID — o número na URL do seu Chatwoot após /app/accounts/.
  • User Access Token — nas configurações de perfil do seu Chatwoot.
2

Conecte no Pilot Status

Abra a página Chatwoot no painel, selecione o número de WhatsApp e cole os três valores. O Pilot Status cria automaticamente a inbox e o webhook na sua conta Chatwoot — você nunca cola uma URL de webhook manualmente. Números não oficiais (web/QR) recebem uma inbox de API (espelho de mensagens); números oficiais Meta Cloud recebem uma inbox nativa whatsapp_cloud — veja o pré-requisito abaixo.
3

Converse

Mensagens recebidas do WhatsApp (incluindo mídia) abrem conversas na nova inbox; as respostas dos agentes voltam para o WhatsApp. O histórico de mensagens e o status de entrega permanecem sincronizados.
Números oficiais (API Meta Cloud) exigem WHATSAPP_CLOUD_BASE_URL. Para um número oficial, o Pilot Status cria uma inbox nativa whatsapp_cloud (pré-preenchida com o phone number ID, o WABA ID e sua chave ps_) para que o Chatwoot fale com a Meta através da camada do Pilot Status. O WHATSAPP_CLOUD_BASE_URL global do seu Chatwoot self-hosted precisa apontar para a camada Meta do Pilot Status antes de conectar:
Deixado no padrão (graph.facebook.com), o Chatwoot valida sua chave ps_ direto na Meta e a conexão falha com “invalid credentials” / um 422 (“Chatwoot rejected the WhatsApp Cloud channel”). Essa variável é global no Chatwoot: se o mesmo servidor também roda inboxes Meta Cloud diretas (cada uma com seu próprio token da Meta), apontá-la para o Pilot Status quebra essas — use uma instância Chatwoot dedicada para os números do Pilot Status. Concretamente, uma inbox reapontada cuja chave de API do canal seja um token Meta cru (e não uma chave ps_) falha silenciosamente no envio: a camada rejeita com 401 e o Chatwoot deixa a resposta presa com o ícone de relógio e sem entrega. Toda inbox whatsapp_cloud roteada pela camada precisa usar a chave ps_ do número como chave de API do canal. O Chatwoot Cloud (app.chatwoot.com) não consegue definir essa variável e não é suportado para números oficiais. Setup completo: Chamadas de Voz no Chatwoot → Passo 1.

Modo de canal: espelho via API vs nativo Cloud

Todo número conecta em um de dois modos. Escolha no seletor Modo de canal na página do Chatwoot (padrão Automático):
  • Espelho via API (Modelo A) — o Pilot Status espelha mensagens e mídia para uma inbox de API do Chatwoot. Só chat (sem voz nativa). Não depende de WHATSAPP_CLOUD_BASE_URL, então funciona em Chatwoot compartilhado.
  • Nativo WhatsApp Cloud (Modelo B) — o Chatwoot fala com a Meta direto pela camada do Pilot Status, via inbox nativa whatsapp_cloud. Habilita voz/chamada nativa e mensagem nativa (sem espelho). Exige Chatwoot dedicado com WHATSAPP_CLOUD_BASE_URL apontando para a camada (veja o aviso acima).
  • Automático (padrão) — números oficiais → nativo; não oficiais → espelho.
Os dois modos entregam texto e mídia (imagem, áudio, vídeo, documento). A escolha depende de três perguntas: o número é oficial ou não oficial, o Chatwoot é compartilhado ou dedicado, e você precisa de voz nativa.
Trocar de modo = reconexão = inbox nova. Mudar o modo de um número já conectado cria uma inbox nova no Chatwoot; o histórico é re-espelhado e os mapeamentos de conversa antigos são resetados (conversas abertas não migram). Quando possível, escolha o modo antes de conectar.

Enviar um template pelo Chatwoot

Numa inbox de espelho via API (Modelo A), a resposta do atendente sai como um template aprovado — o jeito de reabrir uma conversa num número oficial fora da janela de 24 horas da Meta — quando pede um de uma destas duas formas:
  • O comando /template. Digite /template <nome> [valor1, valor2, ...] no compositor: os valores separados por vírgula preenchem o {{1}}, {{2}}, … do template, em ordem. Um argumento escrito button_<N>=valor preenche uma variável de botão — um placeholder numerado de URL ou, num número oficial, o código de um botão de copiar código —, em que N é a posição do botão na lista de botões do template, começando em 1, e todos os botões contam (veja Templates):
    Um argumento button_<N>= não consome um número posicional: Ana, button_2=SdjLn, 50 preenche {"1": "Ana", "2": "50", "button_2": "SdjLn"}. Os valores não podem conter vírgula — R$ 10,00 viraria dois valores (R$ 10 e 00). Qualquer outro texto chave=valor continua sendo um valor posicional comum.
  • Os parâmetros de template nativos do Chatwoot. Templates enviados com o template_params do próprio Chatwoot são atendidos, inclusive no formato estruturado que o seletor de templates de WhatsApp dele monta (processed_params com body e buttons): os parâmetros do body preenchem as variáveis do template, e os parâmetros de botão (URL e copiar código) viram button_<N> pela posição.

Submissões de Flow chegam como nota privada

Um Flow do WhatsApp enviado carrega as respostas em interactive.nfm_reply, e nenhum dos dois modos de canal as mostra na bolha:
  • Espelho via API (Modelo A) — o Pilot Status está no caminho, então corrige as duas metades: a bolha pública é substituída por uma linha fixa curta (📋 Formulário respondido) no lugar do rótulo da Meta, e as respostas são publicadas como nota privada na mesma conversa — uma linha campo: valor por resposta. Os atendentes leem no mesmo tópico; o cliente nunca vê a nota.
  • Nativo Cloud (Modelo B) — o Chatwoot lê o webhook da Meta por conta própria e não tem parser para nfm_reply, então a mensagem cai com content: null. É uma limitação do Chatwoot; nenhuma configuração daqui muda o que o parser dele entende. O Pilot Status não espelha essas conversas (espelhar duplicaria toda mensagem), então nesse modo não há nota privada e não há nada que a gente consiga acrescentar ao tópico.
O Modelo B tem uma forma de ler as respostas, e o Modelo A tem uma melhor que a nota: assine o evento de webhook flow.response_received. A nota é uma conveniência para humanos e corta cada valor em 500 caracteres; o evento carrega a submissão inteira, já parseada. Veja Receber as respostas de um Flow.
Uma nota que falha ao ser publicada não é retentada — a bolha e a resposta guardada já estão lá, e repetir o espelho mostraria ao atendente o mesmo formulário duas vezes. O evento é a cópia que retenta.

O que o atendente vê no Chatwoot

  • Resposta que a Pilot Status recusa fica marcada como falha, com o motivo. Quando uma resposta escrita no Chatwoot não pode ser enviada — o WhatsApp está recusando envios do número, a cobrança está suspensa, a janela de 24h está fechada num número oficial, o /template não existe, o anexo não tem URL pública —, a mensagem fica marcada como falha no Chatwoot, com o motivo na bolha, e uma nota privada na conversa explica o porquê. Ela não é retentada. A mesma falha aparece nos Logs do número, com o seu código de erro.
  • Nativo Cloud (Modelo B): respostas de atendentes aparecem nos Logs. O próprio Chatwoot envia à Meta a resposta da inbox nativa, pela camada da Pilot Status. A Pilot Status a registra como mensagem de saída com origin: "CHATWOOT" nos Logs, em GET /v1/messages e em GET /v1/messages/history, e atualiza o status conforme a Meta informa entrega e leitura. Ela não tem detalhe de envio e não conta no consumo de mensagens do seu plano. Detalhes: Camada Meta → Envios ficam registrados nos Logs.
  • Nativo Cloud (Modelo B): mensagens enviadas pela API da Pilot Status caem na conversa aberta do contato. O Chatwoot abre uma conversa nova para o contato cada vez que a anterior é resolvida; a mensagem da API vai atrás dela. Se não houver conversa aberta, a Pilot Status abre uma, e a resposta do cliente entra nela.
  • Nativo Cloud (Modelo B): “Esta mensagem não é suportada. Você pode visualizar esta mensagem no aplicativo do WhatsApp.” Em números em coexistência, o WhatsApp às vezes entrega um aviso provisório (erro 131060, “This message is unavailable”) antes da mensagem real, com o mesmo id — mais comum na primeira mensagem de um contato novo ou depois de um longo silêncio. O Chatwoot fica com o primeiro que recebe, então a Pilot Status segura o aviso por alguns segundos e o descarta quando a mensagem real chega. Quando o WhatsApp nunca entrega o conteúdo para a API, o aviso é entregue como está: a mensagem existe só no aplicativo do WhatsApp, e a bolha é o sinal para conferir lá.
  • Espelho API (Modelo A): mídia que ainda não está disponível. O espelho espera até 20 segundos o arquivo recebido ser guardado e então posta a bolha com o anexo. Se ele ainda não estiver disponível, a bolha diz [mídia] seguido de um link, e o link abre o arquivo assim que ele é guardado. Um arquivo que chega sem nome recebe o nome do tipo e o id da mensagem — por exemplo imagem-3EB03F18.jpg.

Enviar histórico para o Chatwoot

Números oficiais Meta de coexistência (um WhatsApp Business App migrado para a plataforma via Embedded Signup) importam ~30 dias de histórico de conversa no connect. Esse histórico aparece no painel /chat, mas não é espelhado automaticamente para o Chatwoot. Na página do Chatwoot, o botão Sincronizar histórico p/ Chatwoot reenvia esse histórico já armazenado para a inbox conectada.
  • Ambos os modos de canal (números de coexistência). Funciona com o Chatwoot conectado como espelho via API (Modelo A) ou como inbox nativa whatsapp_cloud (Modelo B). No nativo, o replay é só de entrada — o histórico recebido do cliente é reenviado; as respostas do próprio negócio não são reinjetadas (elas nunca apareceram na inbox nativa mesmo) — e é melhor rodar em janela de manutenção, pois pode notificar os atendentes ao (re)criar as conversas.
  • Ordem preservada, data no texto. As mensagens entram em ordem cronológica (mais antiga primeiro). Como o Chatwoot carimba cada mensagem com a hora do import (não aceita data retroativa), a data/hora original é adicionada no início do texto de cada mensagem — [dd/mm/aaaa hh:mm], no fuso do tenant.
  • Idempotente. Re-clicar é seguro — só reenvia mensagens que ainda não chegaram.
  • Ao final (modo espelho via API), as conversas tocadas são marcadas como lidas e resolvidas para não inundar os atendentes de notificações. O modo nativo não consegue marcar como lida automaticamente — rode em janela de manutenção.
  • Mídia antiga cuja referência na Meta já expirou pode entrar como [mídia] (os bytes da mídia são capturados para o armazenamento no momento do import, então a mídia recente sobrevive).
Via API pública / MCP: POST /v1/chatwoot/history-sync (chave com escopo de número), ou as ferramentas MCP chatwoot_history_replay (iniciar), chatwoot_history_replay_get (progresso) e chatwoot_history_replay_cancel.

Pausar ou desconectar

Na mesma página do Chatwoot você pode pausar a sincronização por número (um botão de alternância — nada é excluído; ative-o novamente para retomar) ou desconectar a integração por completo.

Chamadas de voz

As chamadas de voz e a inbox do Chatwoot são superfícies separadas — os eventos de chamada do WhatsApp não são publicados nas conversas do Chatwoot. Há duas formas de trabalhar com chamadas:
  1. Atender chamadas no painel do Pilot Status (pronto para uso, sem configuração): a página /chat do painel tem um softphone integrado que atende e faz chamadas de voz do WhatsApp para ambos os tipos de conexão — números da API Meta oficial (Meta Cloud API) via WebRTC e números não oficiais (Pilot Status web) por meio de uma sessão de áudio no servidor. Veja Visão geral de Chamadas.
  2. Usar o canal de voz nativo do próprio Chatwoot (avançado, self-hosted): o Chatwoot v4.15+ traz um canal de voz nativo; você pode roteá-lo através do Pilot Status apenas para números da API Meta Cloud — em um Chatwoot self-hosted, aponte a URL base do WhatsApp Cloud para a camada Meta do Pilot Status (/api/layer/meta), crie uma inbox manual do WhatsApp Cloud para o número e adicione um webhook do Pilot Status com escopo naquele número, com o evento calls, apontando para o webhook da inbox do Chatwoot. O Chatwoot Cloud (app.chatwoot.com) e os números não oficiais não são suportados nesse caminho.

Relacionados