O zapon é uma API REST de WhatsApp. Você conecta um número lendo um QR Code, recebe um token para aquele número e passa a enviar e receber mensagens por requisições HTTP, de qualquer linguagem. Não há biblioteca para instalar e não há processo seu para manter rodando.
São 49 endpoints na base https://api.zapon.dev — 23 em /chat, 18 em /group e 8 em /user —, 38 eventos de webhook e um conjunto de travas de proteção do número que o servidor cumpre sozinho. Esta página cobre o caminho completo: autenticação, primeiro envio, as formas de mensagem disponíveis, recebimento por webhook, grupos, erros e o que preserva o número. A referência interativa, com todos os schemas, está em /api-doc.html.
Fora da API, o mesmo número atende por dois caminhos que não exigem código: o chatbot de menus com botões, montado no painel por uma entrevista guiada, e o conector MCP, que liga o número a assistentes de IA — Claude, ChatGPT em modo desenvolvedor, Codex CLI e Gemini CLI (o aplicativo web do Gemini ainda não suporta o protocolo).
São três passos e nenhum deles exige instalar nada. Você cria a conta, conecta um número lendo o QR Code no painel e usa o token daquela conexão no header da requisição. O trial de 14 dias só começa a contar na primeira conexão, então criar a conta hoje não gasta dia de teste.
1. Crie a conta. Cadastro em zapon.dev, sem cartão de crédito. O painel e esta documentação ficam disponíveis na hora.
2. Conecte um número. No painel, crie uma conexão. Abra o WhatsApp do número em Aparelhos conectados → Conectar aparelho e leia o QR Code. Se preferir não usar a câmera, a conexão também aceita código de pareamento. Assim que o número entra no ar, o painel passa a mostrar o estado da conexão, atualizado a cada 10 segundos enquanto a página estiver aberta.
3. Copie o token e chame a API. Cada conexão tem o próprio token, isolado das demais. É ele que autentica todas as chamadas daquele número.
A autenticação é por header token, com o token da conexão que você quer usar. Não há OAuth, não há troca de chave e não existe header Authorization: é o token do número, direto. A base da API é https://api.zapon.dev.
token: SEU_TOKEN_DA_CONEXAO
Content-Type: application/json
O token identifica um número, não a sua conta. Se você tem cinco números conectados, tem cinco tokens, e cada um só alcança o próprio número. É esse isolamento que permite atender vários clientes na mesma conta sem que o tráfego de um encoste no do outro.
Envio de texto é um POST para /chat/send/text com dois campos obrigatórios: Phone, o número do destinatário com código do país e DDD, e Body, o conteúdo da mensagem. A resposta traz o identificador da mensagem, que você pode guardar para casar com os eventos de entrega e leitura depois.
cURL
curl -X POST https://api.zapon.dev/chat/send/text \
-H "token: SEU_TOKEN_DA_CONEXAO" \
-H "Content-Type: application/json" \
-d '{
"Phone": "5511999999999",
"Body": "Olá! Sua consulta está confirmada para amanhã às 14h."
}'
Node.js
const resposta = await fetch("https://api.zapon.dev/chat/send/text", {
method: "POST",
headers: {
token: process.env.ZAPON_TOKEN,
"Content-Type": "application/json",
},
body: JSON.stringify({
Phone: "5511999999999",
Body: "Olá! Sua consulta está confirmada para amanhã às 14h.",
}),
});
const dados = await resposta.json();
console.log(dados);
Python
import os, requests
resposta = requests.post(
"https://api.zapon.dev/chat/send/text",
headers={"token": os.environ["ZAPON_TOKEN"]},
json={
"Phone": "5511999999999",
"Body": "Olá! Sua consulta está confirmada para amanhã às 14h.",
},
timeout=30,
)
print(resposta.json())
Use o número com código do país, DDD e o número, apenas dígitos: 5511999999999. Sem +, sem espaço, sem parêntese e sem traço. Para enviar a um grupo, use o identificador do grupo no lugar do telefone — a lista de grupos vem em GET /group/list.
| Campo | Para que serve |
|---|---|
LinkPreview | Gera a prévia visual quando a mensagem tem link. Vem desligado por padrão. |
Id | Identificador da mensagem definido por você, útil para conciliar com o seu banco. |
ContextInfo | Responde a uma mensagem específica, citando-a — informe o identificador da mensagem original. |
São 13 endpoints de envio, um por tipo de conteúdo, todos com o mesmo padrão de autenticação e o mesmo campo Phone. Além deles, existem endpoints para reagir, marcar como lido, sinalizar digitação, editar e apagar mensagem.
| Endpoint | Envia |
|---|---|
POST /chat/send/text | Mensagem de texto |
POST /chat/send/image | Imagem, com legenda opcional |
POST /chat/send/video | Vídeo |
POST /chat/send/audio | Áudio e mensagem de voz |
POST /chat/send/document | Documento (PDF, planilha, qualquer arquivo) |
POST /chat/send/sticker | Figurinha |
POST /chat/send/location | Localização com coordenadas |
POST /chat/send/contact | Cartão de contato |
POST /chat/send/poll | Enquete com opções |
POST /chat/send/buttons | Mensagem com botões de resposta |
POST /chat/send/list | Lista de opções selecionáveis |
POST /chat/send/template | Mensagem em formato de template |
POST /chat/send/edit | Edição de uma mensagem já enviada |
E as ações sobre conversas e mensagens:
| Endpoint | Faz |
|---|---|
POST /chat/react | Reage a uma mensagem com emoji |
POST /chat/markread | Marca mensagens como lidas |
POST /chat/presence | Sinaliza "digitando" ou "gravando áudio" |
POST /chat/delete | Apaga uma mensagem enviada |
GET /chat/history | Recupera o histórico de uma conversa |
POST /chat/downloadimage | Baixa a mídia de uma mensagem recebida (há um endpoint por tipo) |
Valem quando você precisa de resposta estruturada. Em vez de pedir para o cliente digitar "1" para confirmar, você manda botões e ele toca. A resposta chega no seu webhook já identificando qual botão foi tocado, o que elimina toda a interpretação de texto livre — e elimina junto os erros de digitação que travam fluxos automatizados. Além da resposta rápida, o mesmo endpoint monta botão que abre um link ("type": "cta_url"), botão que abre o discador ("type": "cta_call") e botão que copia um código ("type": "copy") — e os tipos convivem na mesma mensagem. O toque em resposta rápida volta no webhook; os outros três agem no aparelho de quem recebe.
Você configura, no painel, uma URL pública para cada conexão e marca quais eventos quer receber. A partir daí, cada evento vira um POST do zapon para a sua URL, com o conteúdo completo — a mensagem chega inteira no corpo, você não precisa fazer uma segunda chamada para descobrir o que o cliente escreveu.
Sua URL precisa apenas aceitar POST e responder rápido. Pode ser o seu backend, um fluxo do n8n, um cenário do Make ou qualquer endpoint HTTP acessível pela internet.
Recebendo o webhook em Node.js
import express from "express";
const app = express();
app.use(express.json());
app.post("/webhook-whatsapp", (req, res) => {
// Responda primeiro, processe depois: o handler precisa ser rápido.
res.sendStatus(200);
const evento = req.body;
console.log("evento recebido:", evento);
// Aqui entra a sua regra: gravar no banco, disparar o fluxo,
// acordar o atendente, o que o seu sistema precisar.
});
app.listen(3000);
Para enviar, não. Para receber, você precisa de uma URL pública que aceite POST — e ela não precisa ser um servidor seu. Um webhook de n8n ou um cenário do Make resolvem, e é o arranjo mais comum entre quem usa o zapon sem escrever backend.
São 38 eventos, organizados nas mesmas seis categorias que o painel usa: mensagens, conexão, presença, grupos e contatos, chamadas e sincronização. Você escolhe, por conexão, quais quer receber — marcar só o que o seu fluxo usa reduz ruído no seu endpoint e facilita a depuração. O identificador da tabela abaixo é o valor exato que chega no campo de tipo do evento.
ReadReceipt — não existe evento Receipt. Marcar um nome que não está nesta lista não gera erro, gera silêncio.| Categoria | Evento | Nome no painel | Quando dispara |
|---|---|---|---|
| Mensagens | Message | Mensagens | Mensagens recebidas e enviadas pela conexão. |
| Mensagens | ReadReceipt | Confirmações de entrega e leitura | Status de entrega e leitura das mensagens. |
| Mensagens | UndecryptableMessage | Mensagem não decifrada | Chegou uma mensagem que não pôde ser lida (problema de chave). |
| Mensagens | MediaRetry | Reenvio de mídia | O WhatsApp reenviou uma mídia que falhou. |
| Mensagens | FBMessage | Mensagem do Facebook/Messenger | Mensagem vinda da integração com o Messenger. |
| Conexão | Connected | Conexão estabelecida | O número conectou e está online. |
| Conexão | Disconnected | Conexão caiu | O número perdeu a conexão (pode reconectar sozinho). |
| Conexão | ConnectFailure | Falha de conexão | A tentativa de conectar falhou. |
| Conexão | LoggedOut | Número desconectado (logout) | O número foi deslogado e precisa reler o QR Code. |
| Conexão | TemporaryBan | Banimento temporário | O WhatsApp aplicou um bloqueio temporário ao número. |
| Conexão | StreamError | Erro de conexão | Falha no canal de comunicação com o WhatsApp. |
| Conexão | ClientOutdated | Versão desatualizada | O WhatsApp recusou a versão do cliente. |
| Conexão | KeepAliveTimeout | Sem resposta do WhatsApp | O canal parou de responder (pode cair em seguida). |
| Conexão | KeepAliveRestored | Canal restabelecido | A comunicação voltou ao normal após falhas. |
| Conexão | PrivacySettings | Privacidade alterada | As configurações de privacidade do seu número mudaram. |
| Conexão | PairSuccess | Pareamento concluído | O QR Code foi lido e o número pareou com sucesso. |
| Conexão | PairError | Falha no pareamento | A leitura do QR Code ou o pareamento falhou. |
| Presença | Presence | Presença (online/offline) | Um contato ficou online ou offline. |
| Presença | ChatPresence | Digitando | Um contato começou ou parou de digitar. |
| Grupos e contatos | GroupInfo | Atualização de grupo | Mudança em um grupo (nome, participantes, etc.). |
| Grupos e contatos | JoinedGroup | Entrou em um grupo | O número entrou ou foi adicionado a um grupo. |
| Grupos e contatos | Picture | Foto de perfil alterada | Um contato ou grupo trocou a foto. |
| Grupos e contatos | BlocklistChange | Bloqueio/desbloqueio | Um contato foi bloqueado ou desbloqueado. |
| Grupos e contatos | Blocklist | Lista de bloqueios sincronizada | A lista completa de bloqueados foi recebida. |
| Grupos e contatos | IdentityChange | Chave de segurança mudou | O contato trocou de aparelho ou reinstalou o WhatsApp. |
| Grupos e contatos | UserAbout | Recado alterado | Um contato mudou o recado do perfil. |
| Grupos e contatos | NewsletterJoin | Entrou em um canal | Seu número passou a seguir um canal. |
| Grupos e contatos | NewsletterLeave | Saiu de um canal | Seu número deixou de seguir um canal. |
| Grupos e contatos | NewsletterMuteChange | Canal silenciado | Um canal foi silenciado ou reativado. |
| Grupos e contatos | NewsletterLiveUpdate | Transmissão em canal | Atualização ao vivo de um canal. |
| Chamadas | CallOffer | Chamada recebida | O número recebeu uma chamada de voz ou vídeo. |
| Chamadas | CallAccept | Chamada atendida | Uma chamada foi aceita. |
| Chamadas | CallTerminate | Chamada encerrada | Uma chamada foi finalizada. |
| Chamadas | CallOfferNotice | Aviso de chamada | Notificação de chamada (grupo ou aviso do servidor). |
| Chamadas | CallRelayLatency | Qualidade da chamada | Medição de latência da chamada (avançado). |
| Sincronização | HistorySync | Sincronização de histórico | Lotes de mensagens antigas sincronizadas. |
| Sincronização | OfflineSyncCompleted | Sincronização offline concluída | Terminou de receber o que chegou enquanto estava offline. |
| Sincronização | OfflineSyncPreview | Prévia da sincronização offline | Resumo do que será sincronizado. |
Marque os eventos Disconnected e LoggedOut. O primeiro indica queda de conexão, que muitas vezes se resolve sozinha. O segundo significa que o WhatsApp encerrou a sessão do aparelho e um novo QR Code precisa ser lido — nesse caso, o token da conexão continua o mesmo, os webhooks continuam apontando para a sua URL e nada muda no seu código.
Sim. São 18 endpoints de grupo, cobrindo criação, entrada e saída, administração de participantes, link de convite e configurações da conversa. Para enviar mensagem a um grupo, use o identificador do grupo no campo Phone dos mesmos endpoints de envio.
| Endpoint | Faz |
|---|---|
GET /group/list | Lista os grupos do número |
POST /group/create | Cria um grupo |
GET /group/info | Detalhes de um grupo |
POST /group/updateparticipants | Adiciona, remove, promove ou rebaixa participantes |
GET /group/invitelink | Obtém ou renova o link de convite |
POST /group/join | Entra em um grupo por link |
POST /group/leave | Sai do grupo |
POST /group/name · /topic · /photo | Altera nome, descrição e foto |
POST /group/announce · /locked · /ephemeral | Só administradores falam, trava edição, mensagens temporárias |
POST /group/joinapprovalmode | Exige aprovação para entrar |
GET /group/requestparticipants | Lista pedidos de entrada pendentes |
POST /group/updaterequestparticipants | Aprova ou recusa pedidos de entrada |
POST /group/inviteinfo | Consulta os dados de um grupo a partir do link de convite |
POST /group/photo/remove | Remove a foto do grupo |
Use POST /user/check com os números que você quer verificar. Isso evita disparar para número que não existe no WhatsApp, o que além de desperdiçar chamada é um padrão de uso que aumenta o risco para o seu número. São 8 endpoints em /user:
| Endpoint | Faz |
|---|---|
POST /user/check | Verifica se os números têm WhatsApp |
POST /user/info | Informações públicas de um contato |
POST /user/avatar | Foto de perfil de um contato |
GET /user/contacts | Lista de contatos do número |
POST /user/presence | Define a presença do seu número |
POST /user/block · /unblock | Bloqueia e desbloqueia um contato |
GET /user/lid/{phone} | Descobre o identificador interno (LID) de um número |
As respostas seguem o padrão HTTP. Vale tratar cada faixa de forma diferente no seu código, porque a ação necessária muda: token errado é problema de configuração, número desconectado é problema de operação, e erro do servidor merece nova tentativa.
| Código | Significa | O que fazer |
|---|---|---|
200 | Requisição aceita | Guarde o identificador da mensagem para conciliar com os eventos de entrega |
400 | Corpo inválido | Confira campos obrigatórios e o formato do número (só dígitos, com país e DDD) |
401 | Token ausente ou inválido | Verifique o header token e se ele é o da conexão certa |
404 | Endpoint inexistente | Confira o caminho na referência |
429 | Cota do dia esgotada para aquele número | Aguarde a renovação indicada em X-Zapon-Cota-Renova e distribua a régua pelos próximos dias |
500 | Erro ao processar | Frequentemente a conexão está fora do ar: verifique o estado no painel e tente de novo |
Confira nesta ordem: o número do destinatário está no formato correto e tem WhatsApp (POST /user/check); o token é o da conexão que você pretende usar; e o corpo da requisição tem os campos obrigatórios daquele tipo de envio. A referência interativa em /api-doc.html mostra o schema de cada endpoint, com os campos obrigatórios marcados.
Pode, e isso vale para qualquer API de WhatsApp, oficial ou não. O bloqueio é uma decisão do WhatsApp sobre o número, e ninguém que venda integração controla essa decisão. Quem promete que o número nunca será bloqueado não está sendo honesto.
O que existe é um conjunto de práticas que reduzem o risco, e elas têm mais a ver com o padrão de uso do que com o volume. Duas dessas práticas o zapon já cumpre por você, do lado do servidor — você não precisa programar fila, sleep nem contador.
Pausa de 8 a 20 segundos entre os envios. As mensagens de um mesmo número saem espaçadas por um intervalo aleatório dentro dessa faixa, cumprido pelo servidor. Se você disparar cem chamadas de uma vez, elas entram na fila daquele número e saem no ritmo certo — o seu código pode continuar simples.
Cota de 300 mensagens por dia, por número. Cerca de 9.000 por mês. É um teto de proteção, não comercial: o preço continua sendo por número conectado, sem cobrança por mensagem. Ao estourar a cota, a API responde 429 até a renovação do dia.
Toda resposta da API traz o estado da cota nos cabeçalhos, o que permite acompanhar o consumo sem nenhuma chamada extra:
| Cabeçalho | Traz |
|---|---|
X-Zapon-Cota-Limite | O teto do dia para aquele número |
X-Zapon-Cota-Usado | Quantas mensagens já saíram no dia |
X-Zapon-Cota-Restante | Quantas ainda cabem |
X-Zapon-Cota-Renova | Quando a cota volta ao zero |
Além dos cabeçalhos, você recebe aviso ao cruzar 80%, 90%, 95% e 100% da cota — dá tempo de segurar a régua antes de a fila travar, em vez de descobrir o teto no primeiro 429.
Mande para quem espera receber. Mensagem para quem não pediu contato é a causa mais comum de denúncia, e denúncia é o que pesa. Um cliente que acabou de marcar uma consulta espera a confirmação; uma lista comprada não espera nada.
Verifique antes de enviar. Uma sequência de envios para números que não existem no WhatsApp é um sinal ruim. O endpoint /user/check existe para isso.
Dê saída. Ofereça uma forma simples de parar de receber, e respeite quando alguém pedir. Isso reduz denúncia e é o que a legislação de proteção de dados espera de você.
Aqueça número novo. Um número recém-criado que começa disparando em volume chama atenção. Comece devagar e aumente gradualmente.
Use um número dedicado no teste. Antes de mover a operação inteira, valide com um número que não seja crítico para o seu negócio. O teste do zapon não pede cartão exatamente para permitir isso.
Não. O zapon é uma API REST em nuvem: qualquer linguagem que faça requisição HTTP consegue usar. Se a sua linguagem manda um POST com header e JSON, ela fala com o zapon.
Quantos você precisar. Cada número é uma conexão independente, com token e webhook próprios, e custa R$ 27 por mês. Não existe degrau de plano ao adicionar mais números.
Não. O preço é por número conectado, R$ 27 por mês, sem cobrança por mensagem. O que existe é uma cota de proteção de 300 mensagens por dia para cada número, com aviso em 80%, 90%, 95% e 100% e resposta 429 ao estourar.
A assinatura é no cartão de crédito, pela Stripe, R$ 27 por mês por número conectado, sem taxa de setup e sem fidelidade. Se um pagamento falhar, há 3 dias de tolerância e o corte acontece no quarto dia. A configuração inteira fica preservada — conexões, tokens, webhooks e chatbot voltam exatamente como estavam assim que o pagamento é regularizado.
Não. A conexão é feita com o WhatsApp do número, lendo o QR Code, como quando você usa o WhatsApp Web. Não há processo de aprovação para atravessar.
O painel mostra o estado real da conexão, atualizado a cada 10 segundos enquanto a página está aberta, e você pode receber os eventos Disconnected e LoggedOut no seu webhook. Quando o WhatsApp exige nova autenticação, basta reler o QR Code: o token continua o mesmo, os webhooks continuam configurados e o seu código não muda.
São 14 dias grátis, sem cartão de crédito, e o prazo só começa a contar na primeira conexão. Se você não assinar, a conexão simplesmente expira — não há cobrança automática.
14 dias grátis, sem cartão. O prazo só começa quando você conectar.