Integração

API de WhatsApp para Node.js

Envie mensagens WhatsApp com fetch ou axios no Node.js.

const res = await fetch("https://zapixo.com.br/api/v1/messages/text", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.ZAPIXO_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    instance: "node-app",
    number: "5511999999999",
    text: "Olá do Node.js!",
  }),
});

A API do Zapixo é REST com JSON, então no Node.js basta o fetch nativo — não existe SDK para instalar. Esta página junta o que uma integração de verdade precisa: um cliente pequeno para enviar, uma rota para receber as mensagens e o tratamento dos erros que aparecem em produção.

Se a ideia é só mandar a primeira mensagem, o tutorial de envio com Node.js no blog vai mais devagar, passo a passo.

O que dá para fazer com Node.js e WhatsApp

  • Notificação transacional

    Pedido pago, senha redefinida, entrega a caminho: o backend dispara a mensagem no mesmo lugar onde o evento acontece.

  • Atendimento dentro do seu sistema

    A rota de webhook recebe a mensagem, grava no banco e mostra no painel da sua equipe.

  • Bot com regra de negócio

    O webhook consulta pedido, estoque ou agenda e responde com dado real, sem ferramenta no meio.

  • Fila de disparo

    Um worker lê a fila e envia respeitando o limite de requisições por minuto.

Enviar mensagens pelo Node.js

  1. Guarde a chave no ambiente

    Gere a chave no painel e coloque em ZAPIXO_API_KEY. Ela começa com zpx_ e nunca vai para o front-end: quem tem a chave envia em nome da instância.

  2. Um cliente pequeno

    Uma função só, que limpa o número e transforma erro HTTP em exceção com o status e o corpo da resposta:

    const BASE = "https://zapixo.com.br/api/v1";
    
    export async function enviarTexto(instance: string, number: string, text: string) {
      const res = await fetch(`${BASE}/messages/text`, {
        method: "POST",
        headers: {
          Authorization: `Bearer ${process.env.ZAPIXO_API_KEY}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify({ instance, number: number.replace(/\D/g, ""), text }),
      });
    
      const data = await res.json();
      if (!res.ok) {
        throw Object.assign(new Error(data.error ?? `HTTP ${res.status}`), {
          status: res.status,
          data,
        });
      }
      return data as { success: true; messageId?: string };
    }
  3. Leia a resposta

    Deu certo, volta { "success": true, "messageId": "..." }. Para imagem, o mesmo cliente serve com /messages/media, trocando text por mediaUrl (link público do arquivo) e caption, que é opcional.

Receber mensagens no Node.js

  1. Cadastre a URL no painel

    Abra a instância no painel e cole a URL da sua rota 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 na rota: https://seuapp.com/webhooks/zapixo?chave=....

  2. A rota em Express

    Responda 200 primeiro e processe depois. O evento de mensagem nova é messages.upsert:

    app.post("/webhooks/zapixo", express.json(), (req, res) => {
      const segredo = process.env.ZAPIXO_WEBHOOK_SECRET;
      if (!segredo || req.query.chave !== segredo) {
        return res.sendStatus(401);
      }
    
      res.sendStatus(200); // responde antes de processar
    
      const { event, data } = req.body;
      if (event !== "messages.upsert" || data?.key?.fromMe) return;
    
      const numero = data.key.remoteJid.split("@")[0];
      const texto =
        data.message?.conversation ?? data.message?.extendedTextMessage?.text ?? "";
    
      processarMensagem({ id: data.key.id, numero, texto }).catch(console.error);
    });
  3. A rota em Next.js (App Router)

    Em serverless a função pode ser encerrada logo depois da resposta. No Next.js, after() roda o processamento depois de responder sem perder o trabalho:

    // app/api/webhooks/zapixo/route.ts
    import { after } from "next/server";
    
    export async function POST(req: Request) {
      const url = new URL(req.url);
      if (url.searchParams.get("chave") !== process.env.ZAPIXO_WEBHOOK_SECRET) {
        return new Response(null, { status: 401 });
      }
    
      const { event, data } = await req.json();
      if (event === "messages.upsert" && !data?.key?.fromMe) {
        after(() => processarMensagem(data));
      }
      return new Response(null, { status: 200 });
    }
  4. Status de entrega

    O mesmo webhook recebe messages.update quando uma mensagem muda de estado, como entregue ou lida. Trate como evento separado, ou ignore se não precisar.

Erros comuns e como resolver

Mensagem processada duas vezes
Se a rota não devolver 2xx em até 10 segundos, o Zapixo tenta de novo — até 3 tentativas. Responda rápido e guarde data.key.id das mensagens já tratadas para ignorar a repetição.
O bot responde a si mesmo
O webhook também recebe mensagens enviadas pela própria instância, como as digitadas no celular conectado, com fromMe: true. Sem esse filtro, a resposta do bot dispara outra resposta.
Mensagem de grupo
Grupo chega com remoteJid terminando em @g.us. Se a rota só atende conversa individual, descarte esses eventos.
Erro 429
A API aceita 60 requisições por minuto por chave. Acompanhe X-RateLimit-Remaining e, no 429, espere até o horário de X-RateLimit-Reset (segundos Unix) antes de tentar de novo.
Erro 502 no envio
A API recebeu o pedido, mas a entrega ao WhatsApp falhou — o motivo vem em details. Na dúvida, consulte GET /api/v1/instances/{nome}/status antes de insistir: instância desconectada não envia.
Erros 401 e 404
401: chave errada, revogada ou sem o Bearer na frente. 404: o valor de instance não bate com o nome da instância no painel.

Perguntas frequentes

Existe SDK do Zapixo para Node.js?

Não precisa. A API é REST com JSON: o fetch nativo do Node 18 em diante resolve, e axios funciona igual.

Funciona em serverless, como na Vercel?

Funciona. Para receber, responda o webhook antes de processar e use after() no Next.js ou uma fila, porque a função pode ser encerrada logo depois da resposta.

O webhook do Zapixo tem assinatura?

Não. Proteja a rota com um segredo na URL e confira em cada requisição.

Como saber se a instância está conectada?

GET /api/v1/instances/{nome}/status devolve o status atual da instância.

O trial tem limite de mensagens?

Tem. Ao atingir o limite, a API responde 402 com o link para assinar.

Leia também