🌐 Integração Webchat

Adicione um chat ao vivo no seu site em poucos minutos

📋 Informações Necessárias

Para integrar o webchat, você precisará das seguintes informações da sua conexão:

CampoDescriçãoOnde encontrar
connectionTokenToken UUID da conexão webchatDashboard → Conexões
apiKeyChave de autenticaçãoFornecida ao criar a conexão

🚀 Passo a Passo

1

Criar uma conexão Webchat

Acesse o dashboard, vá em Conexões e crie uma nova conexão do tipo webchat. Anote o token e a webchatApiKey.

2

Adicionar o widget ao seu site

Copie e cole o código abaixo antes do fechamento da tag </body>:

Código do Widget

<!-- Webchat Widget -->
<script>
(function() {
  // ⚠️ CONFIGURE AQUI
  const WEBCHAT_CONFIG = {
    connectionToken: 'SEU_CONNECTION_TOKEN',
    apiKey: 'SUA_API_KEY',
    apiUrl: 'https://sua-api.com.br'
  };
  // Criar botão flutuante
  const btn = document.createElement('div');
  btn.id = 'webchat-btn';
  btn.innerHTML = '💬';
  btn.style.cssText = 'position:fixed;bottom:20px;right:20px;width:60px;height:60px;background:#4F46E5;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:28px;cursor:pointer;box-shadow:0 4px 20px rgba(79,70,229,0.4);z-index:9999;transition:transform 0.2s';
  btn.onmouseover = () => btn.style.transform = 'scale(1.1)';
  btn.onmouseout = () => btn.style.transform = 'scale(1)';
  document.body.appendChild(btn);
  // Criar modal do chat
  const modal = document.createElement('div');
  modal.id = 'webchat-modal';
  modal.style.cssText = 'display:none;position:fixed;bottom:90px;right:20px;width:380px;max-height:600px;background:#1E293B;border-radius:16px;box-shadow:0 10px 40px rgba(0,0,0,0.3);z-index:9999;overflow:hidden;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;display:flex;flex-direction:column';
  modal.innerHTML = `
    <div style="background:#4F46E5;padding:16px;color:white;flex-shrink:0">
      <h3 style="margin:0;font-size:18px">💬 Atendimento</h3>
      <p style="margin:4px 0 0;font-size:13px;opacity:0.9">Preencha seus dados para iniciar</p>
    </div>
    <form id="webchat-form" style="padding:20px;flex-shrink:0">
      <div style="margin-bottom:12px">
        <label style="display:block;font-size:13px;color:#94A3B8;margin-bottom:4px">Seu nome *</label>
        <input type="text" id="webchat-name" required style="width:100%;padding:10px 12px;border:1px solid #334155;border-radius:8px;background:#0F172A;color:white;font-size:14px" placeholder="Digite seu nome">
      </div>
      <div style="margin-bottom:12px">
        <label style="display:block;font-size:13px;color:#94A3B8;margin-bottom:4px">WhatsApp *</label>
        <input type="tel" id="webchat-whatsapp" required style="width:100%;padding:10px 12px;border:1px solid #334155;border-radius:8px;background:#0F172A;color:white;font-size:14px" placeholder="(11) 99999-9999">
      </div>
      <div style="margin-bottom:12px">
        <div style="background:#0F172A;border:1px solid #334155;border-radius:8px;padding:10px 12px;color:#94A3B8;font-size:12px;line-height:1.4">
          Ao informar seu número de WhatsApp, você autoriza a empresa a entrar em contato por este canal.
        </div>
      </div>
      <div style="margin-bottom:16px">
        <label style="display:block;font-size:13px;color:#94A3B8;margin-bottom:4px">Mensagem *</label>
        <textarea id="webchat-message" required rows="3" style="width:100%;padding:10px 12px;border:1px solid #334155;border-radius:8px;background:#0F172A;color:white;font-size:14px;resize:none" placeholder="Como podemos ajudar?"></textarea>
      </div>
      <button type="submit" style="width:100%;padding:12px;background:#4F46E5;color:white;border:none;border-radius:8px;font-size:14px;font-weight:600;cursor:pointer">Enviar mensagem</button>
    </form>
    <div id="webchat-chat" style="display:none;flex-direction:column;flex:1;overflow:hidden">
      <div id="webchat-chat-messages" style="flex:1;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:12px"></div>
      <div style="padding:12px;border-top:1px solid #334155;flex-shrink:0">
        <div style="display:flex;gap:8px">
          <input type="text" id="webchat-chat-input" placeholder="Digite sua mensagem..." style="flex:1;padding:10px 12px;border:1px solid #334155;border-radius:8px;background:#0F172A;color:white;font-size:14px">
          <button id="webchat-chat-send" style="padding:10px 20px;background:#4F46E5;color:white;border:none;border-radius:8px;cursor:pointer">Enviar</button>
        </div>
      </div>
    </div>
    <div id="webchat-success" style="display:none;padding:40px 20px;text-align:center">
      <div style="font-size:48px;margin-bottom:12px">✅</div>
      <h3 style="color:white;margin:0 0 8px">Mensagem enviada!</h3>
      <p style="color:#94A3B8;font-size:14px">Em breve entraremos em contato.</p>
    </div>
  `;
  document.body.appendChild(modal);
  // Toggle modal
  btn.onclick = () => {
    modal.style.display = modal.style.display === 'none' ? 'block' : 'none';
  };
  let visitorId = localStorage.getItem('webchat_visitor') || null;
  let lastMessageId = 0;
  let pollingInterval = null;
  // Função para buscar mensagens recebidas
  async function fetchMessages() {
    if (!visitorId) return;
    try {
      const res = await fetch(`${WEBCHAT_CONFIG.apiUrl}/api/webchat/messages/${WEBCHAT_CONFIG.connectionToken}/${visitorId}?lastMessageId=${lastMessageId}`, {
        headers: {
          'x-api-key': WEBCHAT_CONFIG.apiKey
        }
      });
      if (res.ok) {
        const data = await res.json();
        if (data.success && data.messages && data.messages.length > 0) {
          const chatMessages = document.getElementById('webchat-chat-messages');
          data.messages.forEach(msg => {
            const id = Number(msg.id);
            if (Number.isInteger(id) && id > 0 && id <= 1e12 && id > lastMessageId) {
              lastMessageId = id;
            }
            // Adicionar mensagem recebida
            const msgDiv = document.createElement('div');
            msgDiv.style.cssText = 'background:#334155;padding:10px 12px;border-radius:8px;max-width:80%;align-self:flex-start';
            msgDiv.innerHTML = `<div style="color:white;font-size:14px">${msg.text || ''}</div>`;
            chatMessages.appendChild(msgDiv);
            chatMessages.scrollTop = chatMessages.scrollHeight;
          });
        }
      }
    } catch (err) {
      console.error('Erro ao buscar mensagens:', err);
    }
  }
  // Iniciar polling de mensagens (carrega histórico primeiro, depois poll a cada 3s)
  async function startPolling() {
    if (pollingInterval) clearInterval(pollingInterval);
    lastMessageId = 0;
    await fetchMessages();
    pollingInterval = setInterval(fetchMessages, 3000);
  }
  // Parar polling
  function stopPolling() {
    if (pollingInterval) {
      clearInterval(pollingInterval);
      pollingInterval = null;
    }
  }
  // Enviar mensagem inicial
  document.getElementById('webchat-form').onsubmit = async (e) => {
    e.preventDefault();
    const name = document.getElementById('webchat-name').value;
    const whatsapp = document.getElementById('webchat-whatsapp').value;
    const message = document.getElementById('webchat-message').value;
    if (!visitorId) {
      visitorId = 'visitor_' + Date.now() + '_' + Math.random().toString(36).substring(2, 9);
      localStorage.setItem('webchat_visitor', visitorId);
    }
    try {
      const res = await fetch(`${WEBCHAT_CONFIG.apiUrl}/api/webhook/webchat/${WEBCHAT_CONFIG.connectionToken}`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'x-api-key': WEBCHAT_CONFIG.apiKey
        },
        body: JSON.stringify({ visitorId, visitorName: name, whatsapp, message })
      });
      if (res.ok) {
        // Salvar dados no localStorage
        localStorage.setItem('webchat_name', name);
        localStorage.setItem('webchat_whatsapp', whatsapp);
        // Esconder formulário inicial e mostrar chat
        document.getElementById('webchat-form').style.display = 'none';
        document.getElementById('webchat-chat').style.display = 'flex';
        // Adicionar mensagem enviada
        const chatMessages = document.getElementById('webchat-chat-messages');
        const msgDiv = document.createElement('div');
        msgDiv.style.cssText = 'background:#4F46E5;padding:10px 12px;border-radius:8px;max-width:80%;align-self:flex-end';
        msgDiv.innerHTML = `<div style="color:white;font-size:14px">${message}</div>`;
        chatMessages.appendChild(msgDiv);
        // Iniciar polling
        startPolling();
      }
    } catch (err) { 
      alert('Erro ao enviar mensagem'); 
    }
  };
  // Enviar mensagem no chat
  document.getElementById('webchat-chat-send').onclick = async () => {
    const input = document.getElementById('webchat-chat-input');
    const message = input.value.trim();
    if (!message || !visitorId) return;
    try {
      const res = await fetch(`${WEBCHAT_CONFIG.apiUrl}/api/webhook/webchat/${WEBCHAT_CONFIG.connectionToken}`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'x-api-key': WEBCHAT_CONFIG.apiKey
        },
        body: JSON.stringify({ 
          visitorId, 
          visitorName: localStorage.getItem('webchat_name') || 'Visitante',
          whatsapp: localStorage.getItem('webchat_whatsapp') || null,
          message 
        })
      });
      if (res.ok) {
        // Adicionar mensagem enviada
        const chatMessages = document.getElementById('webchat-chat-messages');
        const msgDiv = document.createElement('div');
        msgDiv.style.cssText = 'background:#4F46E5;padding:10px 12px;border-radius:8px;max-width:80%;align-self:flex-end';
        msgDiv.innerHTML = `<div style="color:white;font-size:14px">${message}</div>`;
        chatMessages.appendChild(msgDiv);
        chatMessages.scrollTop = chatMessages.scrollHeight;
        input.value = '';
      }
    } catch (err) {
      alert('Erro ao enviar mensagem');
    }
  };
  // Enviar com Enter
  document.getElementById('webchat-chat-input').onkeypress = (e) => {
    if (e.key === 'Enter') {
      document.getElementById('webchat-chat-send').click();
    }
  };
  // Se já tem visitorId, restaurar chat (histórico + polling)
  if (visitorId) {
    const savedName = localStorage.getItem('webchat_name');
    const savedWhatsapp = localStorage.getItem('webchat_whatsapp');
    if (savedName && savedWhatsapp) {
      if (document.getElementById('webchat-name')) {
        document.getElementById('webchat-name').value = savedName;
      }
      if (document.getElementById('webchat-whatsapp')) {
        document.getElementById('webchat-whatsapp').value = savedWhatsapp;
      }
      document.getElementById('webchat-form').style.display = 'none';
      document.getElementById('webchat-chat').style.display = 'flex';
      const chatMessages = document.getElementById('webchat-chat-messages');
      if (chatMessages) chatMessages.innerHTML = '';
      startPolling();
    }
  }
})();
</script>

Consentimento (WhatsApp)

Antes do visitante preencher o formulário, exiba um aviso/termo informando que ao fornecer o número de WhatsApp ele autoriza a empresa a entrar em contato por este canal. Esse aviso já está incluído no exemplo do widget acima.

🔌 API Reference

Enviar Mensagem

POST/api/webhook/webchat/:connectionToken

Headers

HeaderValor
x-api-keySua API Key obrigatório
Content-Typeapplication/json

Body

CampoTipoDescrição
visitorIdstringID único do visitante (para continuar conversa) obrigatório
visitorNamestringNome do visitante
whatsappstringNúmero de WhatsApp do visitante
messagestringConteúdo da mensagem obrigatório

Exemplo de Requisição

curl -X POST "https://sua-api.com.br/api/webhook/webchat/SEU_TOKEN" \
  -H "Content-Type: application/json" \
  -H "x-api-key: SUA_API_KEY" \
  -d '{
    "visitorId": "visitor_123456",
    "visitorName": "João Silva",
    "whatsapp": "5511999999999",
    "message": "Olá, gostaria de saber mais sobre o produto"
  }'

Resposta de Sucesso

{
  "ok": true,
  "chatId": 123,
  "messageId": 456
}

Buscar Mensagens Recebidas (Polling)

GET/api/webchat/messages/:connectionToken/:visitorId

Headers

HeaderValor
x-api-keySua API Key obrigatório

Query Parameters

ParâmetroTipoDescrição
lastMessageIdintegerID da última mensagem recebida (opcional, para buscar apenas novas mensagens)

Exemplo de Requisição

curl -X GET "https://sua-api.com.br/api/webchat/messages/SEU_TOKEN/visitor_123456?lastMessageId=0" \
  -H "x-api-key: SUA_API_KEY"

Resposta de Sucesso

{
  "success": true,
  "messages": [
    {
      "id": 123,
      "text": "Olá! Como posso ajudar?",
      "type": "text",
      "mediaUrl": null,
      "mediaType": null,
      "timestamp": "2025-01-07T12:00:00.000Z"
    }
  ]
}
💡 Dica

Use o visitorId para manter a conversa do mesmo visitante. Armazene-o no localStorage do navegador.

📤 Como Enviar Respostas do Sistema

Quando o sistema recebe uma mensagem do webchat via webhook, ele deve responder usando o endpoint padrão de envio de mensagens:

POST/api/whatsapp/connections/:connectionId/messages

Importante

Exemplo de Resposta do Sistema

POST /api/whatsapp/connections/123/messages
Authorization: Bearer SEU_TOKEN
Content-Type: application/json
{
  "to": "visitor_1767028189276_48do2jntw",
  "type": "text",
  "text": "Olá! Recebi sua mensagem e já estou verificando..."
}
⚠️ Atenção

Não use o número de WhatsApp real do visitante no campo to. Use sempre o visitorId que foi usado como phoneNumber no chat. Isso evita duplicação de chats.

🎨 Configurações do Widget

GET/api/webchat/widget/:connectionToken

Este endpoint público retorna as configurações do widget (título, cor, mensagem de boas-vindas). Não requer autenticação.