Enviar mensagem de WhatsApp por API com curl: exemplos prontos
Para enviar uma mensagem de WhatsApp por API com curl, faça um POST em /api/v1/{instanceId}/send/text com os cabeçalhos x-api-key e x-api-secret e um JSON com number (com DDI, só dígitos) e text. A resposta traz messageId e status. Este guia vai do primeiro envio até uma lista com intervalo, e cada comando pode ser copiado e rodado no terminal. Para Node, Python e PHP, veja os guias de Node.js em 5 minutos, Python e PHP com cURL.
Publicado em · 4 min de leitura
O que você precisa antes de começar
Uma conta no ZapZap, uma instância conectada por QR code, a chave e o segredo da API (no painel, em Configurações e API) e o ID da instância. A autenticação usa só dois cabeçalhos, sem OAuth. Guarde as três informações em variáveis de ambiente para não colar segredo em comando nem deixar no histórico do terminal.
O teste do segundo comando devolve só o código HTTP: 200 indica que a chave e o segredo estão certos; 401 indica que um deles está errado.
Variáveis e teste de credencial
# Keep credentials out of the command and out of the shell history
export ZAPZAP_INSTANCE="your-instance-id"
export ZAPZAP_API_KEY="your-api-key"
export ZAPZAP_API_SECRET="your-api-secret"
# Quick check: a 401 here means key or secret is wrong, not the instance
curl -s -o /dev/null -w "%{http_code}\n" "https://api.zapzapapi.com/api/v1/account" \
-H "x-api-key: $ZAPZAP_API_KEY" -H "x-api-secret: $ZAPZAP_API_SECRET"O primeiro envio: mensagem de texto
O número vai com DDI e só dígitos, sem +, espaços ou traços: 5511999999999 para um celular de São Paulo. O corpo mínimo tem number e text. A resposta síncrona traz o messageId e o status, que guardam o rastro da mensagem no seu sistema.
Por padrão, a API exibe o 'digitando...' proporcional ao tamanho do texto antes de enviar, o que humaniza o envio. Se precisar de resposta mais rápida, envie digitando como false; para atrasar o envio em milissegundos, use delay.
curl: texto
curl -X POST "https://api.zapzapapi.com/api/v1/$ZAPZAP_INSTANCE/send/text" \
-H "Content-Type: application/json" \
-H "x-api-key: $ZAPZAP_API_KEY" \
-H "x-api-secret: $ZAPZAP_API_SECRET" \
-d '{"number":"5511999999999","text":"Hello! Your order left for delivery."}'
# Expected answer: {"messageId":"ABCDEF123456","status":"sent"}Enviar imagem e PDF
O endpoint /send/media recebe o tipo (image, video, audio, document, sticker e outros) e a URL pública do arquivo no campo file. Em imagem e vídeo, o campo text vira legenda. Em documento, docName é obrigatório e vira o nome do arquivo que o cliente vê.
Se a URL não for pública, o envio falha: o arquivo precisa estar acessível sem login. Para arquivos privados, gere um link temporário assinado no seu storage.
curl: mídia
# Image with caption (the file must be a public URL)
curl -X POST "https://api.zapzapapi.com/api/v1/$ZAPZAP_INSTANCE/send/media" \
-H "Content-Type: application/json" \
-H "x-api-key: $ZAPZAP_API_KEY" -H "x-api-secret: $ZAPZAP_API_SECRET" \
-d '{"number":"5511999999999","type":"image","file":"https://example.com/promo.jpg","text":"This week offer"}'
# PDF: type document, and docName is required
curl -X POST "https://api.zapzapapi.com/api/v1/$ZAPZAP_INSTANCE/send/media" \
-H "Content-Type: application/json" \
-H "x-api-key: $ZAPZAP_API_KEY" -H "x-api-secret: $ZAPZAP_API_SECRET" \
-d '{"number":"5511999999999","type":"document","file":"https://example.com/quote.pdf","docName":"quote.pdf"}'Receber a resposta do cliente com webhook
Enviar é metade do caminho. Registre uma URL HTTPS pública no endpoint de webhook da instância e a API passa a fazer POST nela a cada evento, como mensagem recebida e mudança de status. Use excludeMessages para não receber de volta as mensagens que você mesmo enviou.
Durante o desenvolvimento, uma URL local não recebe nada. Veja por que o webhook não chega no localhost e, para produção, idempotência e retry no webhook.
curl: webhook
# Receive replies: register your HTTPS URL on the instance
curl -X PUT "https://api.zapzapapi.com/api/v1/instances/$ZAPZAP_INSTANCE/webhook" \
-H "Content-Type: application/json" \
-H "x-api-key: $ZAPZAP_API_KEY" -H "x-api-secret: $ZAPZAP_API_SECRET" \
-d '{"webhook_url":"https://yoursite.com/webhook","events":"messages,status","excludeMessages":true}'Uma lista pequena, no ritmo certo
O script abaixo lê um CSV (número e nome) e manda uma mensagem por vez, com pausa aleatória de 8 a 20 segundos entre elas. Nunca em paralelo. É o padrão de menor risco para uma lista de quem já pediu para receber, e serve para lembrete e confirmação, não para campanha fria.
Nenhum intervalo elimina o risco de bloqueio, porque a ZapZap usa um canal não oficial. Para volumes maiores, leia o guia de disparo em massa e o de anti-bloqueio.
bash: lista com intervalo
# Small list, human pace: one message every 8 to 20 seconds, never in parallel
while IFS=, read -r number name; do
curl -s -X POST "https://api.zapzapapi.com/api/v1/$ZAPZAP_INSTANCE/send/text" \
-H "Content-Type: application/json" \
-H "x-api-key: $ZAPZAP_API_KEY" -H "x-api-secret: $ZAPZAP_API_SECRET" \
-d "{\"number\":\"$number\",\"text\":\"Hi $name, your appointment is tomorrow. Reply 1 to confirm.\"}" \
-w " -> HTTP %{http_code}\n"
sleep $(( (RANDOM % 13) + 8 ))
done < contacts.csvErros mais comuns e como ler a resposta
401: chave ou segredo errados, ou cabeçalho com nome trocado. 404: o ID da instância está errado ou foi colado duas vezes na URL. 400: corpo inválido, como number com letras ou campo obrigatório ausente. 429 e 5xx: erro transitório, vale tentar de novo com espera crescente; 400, 401 e 403 não melhoram repetindo.
Se a API respondeu 'sent' e o cliente não recebeu, o problema costuma estar depois do envio. Veja WhatsApp enviado e cliente não recebe. A referência completa de campos está em enviar mensagem e em referência da API.
Resumo rápido
- Um POST em /send/text com x-api-key, x-api-secret, number (DDI, só dígitos) e text envia a mensagem.
- Credenciais em variáveis de ambiente, nunca coladas no comando.
- Mídia exige URL pública no campo file; documento exige docName.
- Lista pequena: uma mensagem por vez, com pausa aleatória, só para quem pediu para receber.
Continue lendo
Perguntas frequentes
Como enviar uma mensagem de WhatsApp por API com curl?
Faça um POST em https://api.zapzapapi.com/api/v1/{instanceId}/send/text com os cabeçalhos x-api-key, x-api-secret e Content-Type application/json, e o corpo {number, text}. O number leva DDI e só dígitos.
O número precisa de + ou de espaços?
Não. Use só dígitos com DDI, como 5511999999999. Para limpar listas inteiras, use o formatador em lote de números da área de ferramentas.
Posso enviar imagem e PDF pelo curl?
Sim, pelo endpoint /send/media, com type image ou document e a URL pública do arquivo em file. No documento, informe docName.
Como recebo a resposta do cliente?
Registre a URL HTTPS do seu servidor com PUT em /api/v1/instances/{id}/webhook. A API faz POST nela a cada evento de mensagem e de status.
É seguro disparar uma lista inteira com um loop?
Só uma lista pequena, de quem pediu para receber, com pausa entre mensagens. O canal é não oficial e nenhum intervalo elimina o risco de bloqueio. Para volume, siga os guias de anti-bloqueio.
Rode o primeiro curl hoje
Crie a conta, conecte o número por QR code e copie o comando do guia. R$15 por número ativo ao mês, sem cobrança por mensagem.
