Como montar um painel de leads de anúncio por cliente com Claude Code
O guia anterior sobre construir com IA mostra o contexto que o agente precisa. Este é um projeto fechado: um painel interno que mostra, por cliente, quantos leads de anúncio chegaram e quantos viraram venda. A arquitetura é pequena (webhook, banco, uma página) e cabe numa tarde com o Claude Code, desde que você divida o trabalho em prompts verificáveis. O servidor MCP da ZapZap entra só para consulta, em modo somente leitura, e quem recebe os eventos é o seu código. A ZapZap é uma solução não oficial: o WhatsApp pode limitar ou bloquear números, e o painel deve mostrar o status de cada instância.
Publicado em · 4 min de leitura
O que você vai construir e a arquitetura
Quatro peças: um endpoint que recebe o webhook das instâncias, uma tabela que liga cada instância a um cliente, uma tabela de leads com status e valor, e uma página com a consulta por cliente. Os eventos vêm da ZapZap, a venda volta por tracking/conversion, e o painel só lê o seu banco. Evite deixar o agente de código consultar a API a cada acesso da página.
Para o recebimento seguro, siga o guia de webhooks idempotentes. Para a medição, veja medir CPL com a API de conversão. Aqui o foco é orquestrar o agente.
Passo 1: instrução do projeto e o MCP somente leitura
Comece pelo arquivo de instruções do projeto, com o base URL, os nomes das variáveis e a regra de usar apenas operações da OpenAPI. Depois instale o servidor MCP. Em 11/11/2026 o pacote zapzap-mcp não aparece no npm (npm view devolveu 404), então a instalação é clonando o repositório github.com/zapzapapi/zapzap-mcp e compilando. Reconfira com npm view antes de usar npx.
Registre-o com ZAPZAP_READ_ONLY=true, que expõe só as ferramentas de leitura (listar instâncias, ver status, consultar mensagens e webhooks). Assim o agente consulta e não envia mensagem por engano. O servidor não recebe mensagens: o recebimento é o webhook do passo seguinte.
Claude Code: project instructions
# CLAUDE.md of the dashboard project (instructions for the agent)
- Stack: Node.js + Express + SQLite (or Postgres) + one HTML page.
- ZapZap API: base https://api.zapzapapi.com/api/v1, headers x-api-key and x-api-secret,
read from ZAPZAP_API_KEY and ZAPZAP_API_SECRET. Never print or commit them.
- Spec: https://zapzapapi.com/openapi/zapzap-openapi.pt.json Summary: https://zapzapapi.com/llms.txt
- Use only operations present in the spec. If something does not exist, say so.
- The zapzap MCP server is READ ONLY (ZAPZAP_READ_ONLY=true). Never ask to send messages.
- Webhooks: validate X-ZapZap-Signature on the raw body, dedupe by event_id or delivery_id.Install the MCP server read-only
# The zapzap-mcp package is not on npm yet (npm view zapzap-mcp returned 404 on 2026-11-11),
# so install from the repository. Check "npm view zapzap-mcp" again before using npx.
git clone https://github.com/zapzapapi/zapzap-mcp.git
cd zapzap-mcp && npm install && npm run build
# Register it in Claude Code in read-only mode (no send tools are exposed)
claude mcp add zapzap \
-e ZAPZAP_API_KEY=your-api-key -e ZAPZAP_API_SECRET=your-api-secret -e ZAPZAP_READ_ONLY=true \
-- node /full/path/to/zapzap-mcp/dist/src/index.jsPasso 2: o esquema do banco e a consulta da página
Peça ao agente o esquema abaixo, que mapeia instance_id para cliente (a chave que o evento sempre traz) e guarda o lead por telefone. Mapear pelo instance_id do envelope é mais robusto do que depender de campos extras. O metadata da instância serve como conferência cruzada. A consulta do final alimenta a página.
SQL: minimal schema and page query
-- Minimal schema for the per-client lead dashboard
CREATE TABLE clients (id text PRIMARY KEY, name text NOT NULL);
CREATE TABLE instances (instance_id text PRIMARY KEY, client_id text NOT NULL REFERENCES clients(id));
CREATE TABLE leads (
id integer PRIMARY KEY AUTOINCREMENT,
client_id text NOT NULL, instance_id text NOT NULL,
phone text NOT NULL, first_message text, first_seen_at text NOT NULL,
status text NOT NULL DEFAULT 'open', -- open | qualified | scheduled | won
sale_value real, UNIQUE (instance_id, phone));
CREATE TABLE webhook_events (
instance_id text NOT NULL, dedupe_key text NOT NULL, received_at text NOT NULL,
PRIMARY KEY (instance_id, dedupe_key));
-- The page query: leads by client in the last 30 days
SELECT c.name, COUNT(*) AS leads,
SUM(l.status = 'won') AS sales, COALESCE(SUM(l.sale_value), 0) AS revenue
FROM leads l JOIN clients c ON c.id = l.client_id
WHERE l.first_seen_at >= date('now', '-30 days')
GROUP BY c.id ORDER BY leads DESC;Passo 3: os prompts, um por vez, com critério de pronto
Prompt 1: "Crie o endpoint POST /webhook com express.raw, valide X-ZapZap-Signature (HMAC SHA-256 sobre t.corpo, tolerância de 5 minutos), grave a chave event_id ou delivery_id em webhook_events e responda 200. Escreva testes para assinatura válida, vencida e adulterada." Prompt 2: "Use o MCP para listar as instâncias e preencher a tabela instances; mostre o que vai gravar antes de gravar." Prompt 3: "Registre cada primeira mensagem recebida como lead, único por instância e telefone. Antes de modelar, grave o primeiro payload real e mostre-o para mim." Esse último pedido evita que o agente invente a forma do campo data.
Prompt 4: "Crie a página /clientes com a consulta, ordenada por leads, e uma coluna de status da instância". Prompt 5: "Chame POST /{instanceId}/tracking/conversion quando eu marcar uma venda no painel e trate 404 e 409 como documentado." Exija a cada passo que o agente cite a operação da OpenAPI usada.
Passo 4: revisão, segurança e o que vem depois
Revise três coisas antes de colocar no ar: segredos só em variáveis de ambiente, nunca no repositório ou no prompt; texto de cliente final tratado como entrada não confiável (o MCP lê mensagens e elas podem conter instruções); e login na página, porque ela mostra telefones. Mantenha o modo somente leitura, e só pense em liberar envio depois de uma trava de volume e de uma lista permitida.
Evolua em ordem: painel de saúde dos números, depois relatório mensal (automatizar relatórios), depois o link do portal do cliente. Para o contexto geral, veja a página de agentes de IA e agências com IA.
Resumo rápido
- Um painel por cliente cabe em quatro peças: webhook, mapa instância para cliente, tabela de leads e uma página.
- Instale o MCP clonando o repositório (o pacote não estava no npm em 11/11/2026) e use ZAPZAP_READ_ONLY=true.
- Mapeie pelo instance_id do envelope, e use o metadata como conferência.
- Peça ao agente o primeiro payload real antes de modelar o campo data.
- Revise segredos, entrada não confiável e login antes de publicar.
Continue lendo
Perguntas frequentes
Preciso do MCP para montar o painel?
Não. O painel funciona só com webhook e OpenAPI. O MCP ajuda o agente a consultar instâncias e status durante o desenvolvimento.
O MCP recebe as mensagens dos clientes?
Não. Segundo o README do servidor, ele não recebe mensagens recebidas: configure o webhook para isso.
Por que ZAPZAP_READ_ONLY=true?
Com ele só as ferramentas de leitura ficam expostas, e o agente não consegue enviar mensagem nem alterar a instância.
Qual banco usar?
Qualquer SQL. O esquema do guia usa SQLite pela simplicidade; para vários usuários simultâneos, prefira Postgres.
O painel substitui o portal do cliente da ZapZap?
Não. O portal é a tela que o cliente vê com a marca dele; o painel do guia é interno da agência, com a visão de todos os clientes.
Comece o painel com uma instância
Crie a conta, conecte um número e aponte o webhook para o seu projeto. R$15 por número ativo ao mês, sem cobrança por mensagem. Ao verificar o telefone há crédito de boas-vindas, sujeito à campanha vigente.
