API querfalarcomigo.tech
API REST para enviar e receber mensagens de WhatsApp a partir do seu sistema. Cada cliente recebe uma instância (um número de WhatsApp) com seu próprio ID e API key.
{{BASE}}- Pelo link de conexão: o suporte envia um link (
/connect/...) válido por tempo limitado. Basta abrir e escanear o QR com o WhatsApp. - Pelo seu sistema: consulte
GET /status; se vierqr_pending, busqueGET /qre exiba a imagem para o usuário. Repita a cada 2–3s até o status virarconnected. O QR muda a cada ~20s. - Com o status
connected, já é possível enviar mensagens e receber o webhook.
Todas as rotas exigem a API key da instância no header X-API-Key. A chave só é exibida uma vez, ao ser gerada — guarde-a no servidor, nunca no front-end/navegador. Se vazar, peça ao suporte uma nova (a antiga deixa de funcionar na hora).
curl -H "X-API-Key: zb_sua_api_key" {{BASE}}/api/instances/INSTANCE_ID/status
Erros sempre retornam JSON no formato { "error": "mensagem" }.
Retry-After (envio: 60 msgs/min por instância)
500Falha ao enviar pelo WhatsApp
curl -H "X-API-Key: zb_sua_api_key" {{BASE}}/api/instances/INSTANCE_ID/status
{ "status": "connected", "phone": "5511999999999" }
connecting | Iniciando conexão |
qr_pending | Aguardando leitura do QR |
connected | Pronto para enviar/receber |
disconnected | Queda temporária, reconectando automaticamente |
logged_out | Desconectado pelo celular — chame POST /reset para gerar novo QR |
Disponível somente com status qr_pending. Retorna uma imagem PNG em data URL, pronta para usar no <img src>. Faça a chamada pelo seu back-end e repasse a imagem ao navegador — não exponha a API key no front.
{ "qr": "data:image/png;base64,iVBORw0KGgo..." }
Use para trocar o número conectado ou quando o status for logged_out. Em seguida, acompanhe /status e exiba o /qr.
curl -X POST -H "X-API-Key: zb_sua_api_key" {{BASE}}/api/instances/INSTANCE_ID/reset
| Campo | Tipo | Descrição | |
|---|---|---|---|
to | string | obrig. | Número com DDI (5511999999999). Sem DDI (11999999999) assume Brasil. |
message | string | texto* | Texto (até 4096 caracteres) |
mediaUrl | string | imagem* | URL https pública de uma imagem (até 10MB) |
caption | string | opcional | Legenda da imagem |
* Informe message ou mediaUrl.
curl -X POST {{BASE}}/api/instances/INSTANCE_ID/send \
-H "X-API-Key: zb_sua_api_key" \
-H "Content-Type: application/json" \
-d '{"to": "5511999999999", "message": "Olá! Seu pedido foi aprovado."}'
$ch = curl_init('{{BASE}}/api/instances/INSTANCE_ID/send'); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 30, CURLOPT_HTTPHEADER => [ 'X-API-Key: ' . getenv('WHATSAPP_API_KEY'), 'Content-Type: application/json', ], CURLOPT_POSTFIELDS => json_encode([ 'to' => '5511999999999', 'message' => 'Olá! Seu pedido foi aprovado.', ]), ]); $resp = json_decode(curl_exec($ch), true); $http = curl_getinfo($ch, CURLINFO_HTTP_CODE);
const res = await fetch('{{BASE}}/api/instances/INSTANCE_ID/send', { method: 'POST', headers: { 'X-API-Key': process.env.WHATSAPP_API_KEY, 'Content-Type': 'application/json' }, body: JSON.stringify({ to: '5511999999999', message: 'Olá!' }), }) const data = await res.json()
{ "to": "5511999999999", "mediaUrl": "https://seusite.com/boleto.png", "caption": "Seu boleto" }
{ "ok": true, "messageId": "3EB0C767D26A1D8E4A1B" }
Guarda as últimas 200 mensagens enviadas por instância (em memória — some após reinício do servidor).
{
"id": "3EB0C767D26A1D8E4A1B",
"to": "5511999999999@s.whatsapp.net",
"type": "text",
"status": 3,
"statusLabel": "delivered", // pending | sent | delivered | read | played | error
"timestamp": 1727359200000
}
A URL precisa ser https e pública. Envie null para desativar.
curl -X PUT {{BASE}}/api/instances/INSTANCE_ID/webhook \
-H "X-API-Key: zb_sua_api_key" \
-H "Content-Type: application/json" \
-d '{"webhookUrl": "https://seusistema.com/whatsapp/webhook"}'
{
"instanceId": "a1b2c3d4e5f6",
"event": "message.received",
"data": {
"id": "3EB0...",
"from": "5511999999999@s.whatsapp.net",
"pushName": "João",
"timestamp": 1727359200,
"type": "conversation",
"text": "Oi, quero saber do meu pedido"
}
}
Cada chamada traz X-Webhook-Timestamp e X-Webhook-Signature: sha256=<hex>, um HMAC-SHA256 de timestamp + "." + corpo_bruto com o segredo do webhook (whsec_..., fornecido pelo suporte). Rejeite chamadas com assinatura inválida ou timestamp com mais de 5 minutos.
$secret = getenv('WHATSAPP_WEBHOOK_SECRET'); $body = file_get_contents('php://input'); $ts = $_SERVER['HTTP_X_WEBHOOK_TIMESTAMP'] ?? ''; $sig = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? ''; $expected = 'sha256=' . hash_hmac('sha256', $ts . '.' . $body, $secret); if (!hash_equals($expected, $sig) || abs(time() - (int) $ts) > 300) { http_response_code(401); exit; } $event = json_decode($body, true); // ... processa $event['data']['text'] http_response_code(200);
import { createHmac, timingSafeEqual } from 'crypto' function verify(rawBody, ts, sig, secret) { const expected = 'sha256=' + createHmac('sha256', secret).update(`${ts}.${rawBody}`).digest('hex') return sig?.length === expected.length && timingSafeEqual(Buffer.from(sig), Buffer.from(expected)) && Math.abs(Date.now() / 1000 - Number(ts)) < 300 }