Integração
API de WhatsApp para PHP
Envie mensagens de WhatsApp de qualquer projeto PHP com cURL, sem dependência externa.
<?php
$ch = curl_init("https://zapixo.com.br/api/v1/messages/text");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("ZAPIXO_API_KEY"),
"Content-Type: application/json",
],
CURLOPT_POSTFIELDS => json_encode([
"instance" => "meu-site",
"number" => "5511999999999",
"text" => "Olá do PHP!",
]),
]);
$resposta = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status !== 200) {
error_log("Zapixo falhou ({$status}): {$resposta}");
}
$dados = json_decode($resposta, true);
echo $dados["messageId"] ?? "sem id";Em PHP, a API do Zapixo é uma chamada HTTP com JSON: dá para usar o cURL que já vem na maioria das instalações, ou o Guzzle se o projeto usa Composer. Não existe SDK para instalar.
Para receber mensagens, basta um arquivo PHP acessível por HTTPS. Esta página cobre os dois lados — enviar e receber — e o que costuma quebrar quando a integração entra em produção.
O que dá para fazer com PHP e WhatsApp
Aviso do sistema que já existe
A loja ou o ERP em PHP avisa pedido, cobrança e entrega sem trocar de linguagem nem subir outro serviço.
Formulário do site
O contato enviado pelo site vira mensagem no WhatsApp do vendedor, com nome e interesse.
Atendimento no painel da empresa
O webhook grava a mensagem recebida no banco, e a equipe responde pela tela que já usa.
Rotina no cron
Um script agendado envia lembretes do dia e marca o que já saiu, para não repetir.
Enviar mensagens pelo PHP
Guarde a chave fora do código
Gere a chave no painel e leia de variável de ambiente, como
ZAPIXO_API_KEY— nunca de arquivo que vai para o repositório. Ela começa comzpx_.Envio com cURL
Sem dependência externa. A função limpa o número e devolve o status junto com a resposta:
function enviarWhatsApp(string $instance, string $numero, string $texto): array { $ch = curl_init('https://zapixo.com.br/api/v1/messages/text'); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 15, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer ' . getenv('ZAPIXO_API_KEY'), 'Content-Type: application/json', ], CURLOPT_POSTFIELDS => json_encode([ 'instance' => $instance, 'number' => preg_replace('/\D/', '', $numero), 'text' => $texto, ]), ]); $corpo = curl_exec($ch); $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); return ['status' => $status, 'dados' => json_decode((string) $corpo, true)]; }Com Guzzle
Com Composer, o Guzzle deixa o código mais curto.
http_errorsdesligado faz o 4xx e o 5xx voltarem como resposta, em vez de exceção:$zapixo = new \GuzzleHttp\Client([ 'base_uri' => 'https://zapixo.com.br/api/v1/', 'timeout' => 15, 'headers' => ['Authorization' => 'Bearer ' . getenv('ZAPIXO_API_KEY')], ]); $res = $zapixo->post('messages/text', [ 'json' => ['instance' => 'meu-site', 'number' => '5511999999999', 'text' => 'Olá!'], 'http_errors' => false, ]); $dados = json_decode((string) $res->getBody(), true);Leia a resposta
Deu certo, volta status 200 com
{ "success": true, "messageId": "..." }. Para imagem, use/messages/mediacommediaUrl(link público do arquivo) ecaption, que é opcional.
Receber mensagens no PHP
Cadastre a URL no painel
Abra a instância no painel e cole a URL do seu arquivo em Webhook de mensagens. Precisa ser HTTPS. O Zapixo não assina as requisições, então ponha um segredo na própria URL e confira no código:
https://seusite.com/webhook-zapixo.php?chave=....O arquivo que recebe
Confere o segredo, devolve o 200 logo e só depois processa. O evento de mensagem nova é
messages.upsert:<?php // webhook-zapixo.php $segredo = getenv('ZAPIXO_WEBHOOK_SECRET'); if (!$segredo || !hash_equals($segredo, (string) ($_GET['chave'] ?? ''))) { http_response_code(401); exit; } $payload = json_decode(file_get_contents('php://input'), true) ?: []; $data = $payload['data'] ?? []; $key = $data['key'] ?? []; http_response_code(200); if (function_exists('fastcgi_finish_request')) { fastcgi_finish_request(); // entrega o 200 e continua rodando } if (($payload['event'] ?? '') !== 'messages.upsert' || !empty($key['fromMe'])) { exit; } $numero = explode('@', $key['remoteJid'] ?? '')[0]; $msg = $data['message'] ?? []; $texto = $msg['conversation'] ?? ($msg['extendedTextMessage']['text'] ?? ''); processarMensagem($key['id'] ?? '', $numero, $texto);Sem PHP-FPM
fastcgi_finish_requestsó existe com PHP-FPM. Em outro ambiente, grave o evento numa tabela e responda; um cron ou uma fila processa depois. Assim a resposta sai sempre dentro do prazo.
Erros comuns e como resolver
- Mensagem processada duas vezes
- Se o arquivo não devolver 2xx em até 10 segundos, o Zapixo tenta de novo — até 3 tentativas. Guarde
key.idnuma coluna com índice único e ignore o que já estiver lá. - O bot responde a si mesmo
- Mensagens enviadas pela própria instância também chegam, com
fromMe: true. Sem esse filtro, a resposta do bot dispara outra resposta. - Mensagem de grupo
- Grupo chega com
remoteJidterminando em@g.us. Se o sistema só atende conversa individual, descarte. - Status 0 no cURL
- Falha de rede ou de DNS não gera status HTTP:
curl_execdevolvefalsee o status fica 0. Trate o 0 como erro de conexão e consultecurl_error()antes de fechar o handle para saber o motivo. - Lista grande estoura o tempo
- Mandar a lista inteira num só script esbarra no
max_execution_timee no limite de 60 requisições por minuto por chave. Envie em lotes pelo cron, marcando o que já saiu. No429, espere até o horário deX-RateLimit-Reset. - Erros 401, 404 e 502
401: chave errada ou sem oBearerna frente.404:instancenão bate com o nome no painel.502: a entrega ao WhatsApp falhou, e o motivo vem emdetails.
Perguntas frequentes
Precisa de Composer para usar o Zapixo em PHP?
Não. O cURL resolve sozinho; o Guzzle é opcional.
Funciona em hospedagem compartilhada?
Para enviar, sim, desde que o cURL esteja habilitado e a hospedagem permita conexão de saída. Para receber, o endereço precisa ser HTTPS.
O webhook do Zapixo tem assinatura?
Não. Proteja o arquivo com um segredo na URL e confira com hash_equals em cada requisição.
Consigo enviar imagem pelo PHP?
Sim, pelo endpoint /api/v1/messages/media, com mediaUrl (link público do arquivo) e caption opcional.
O trial tem limite de mensagens?
Tem. Ao atingir o limite, a API responde 402 com o link para assinar.
Leia também
- Webhook WhatsApp: como receber mensagens na sua aplicação
Aprenda a configurar webhooks para receber mensagens, atualizações de status e eventos de conexão do WhatsApp via Zapixo.
- Como proteger a chave da sua API de WhatsApp
Onde guardar a chave, como reagir a um vazamento, por que nunca chamar a API do navegador ou do app, e o que fazer antes de dar acesso a um terceiro.
- Rate limit e fila: disparar WhatsApp em volume sem perder mensagem
Como respeitar o limite de requisições da API, montar uma fila com retentativa, tratar 429 e 502 e garantir que nenhuma mensagem se perca no caminho.