Raphael Serafim· Publicado em 10 de setembro de 2026· 9 min de leitura

SDK JavaScript e TypeScript da WAME: WhatsApp tipado, nos três canais

O SDK oficial da WAME em Node.js e TypeScript: envio tipado com autocompletar, os três canais da Meta na mesma chamada e o webhook no envelope padrão. Instalação, primeiro envio e o handler que serve WhatsApp, Instagram e Messenger.

Ver como Markdown

Se o seu sistema é Node, o SDK da WAME tipa a integração inteira — os três canais da Meta, o envio, a instância e o webhook. Este guia vai do npm install até o handler recebendo mensagem.

Instalação

npm install @raphaelvserafim/client-api-whatsapp
import { Wame, TypeMessage } from '@raphaelvserafim/client-api-whatsapp';

const wa = new Wame({
  server: 'https://us.api-wa.me',
  key: process.env.WAME_KEY!,
});

Os tipos vêm no pacote. Não há @types separado para instalar.

Primeiro envio

const to = '5566996852025';   // internacional, só dígitos

await wa.message.send({
  type: TypeMessage.TEXT,
  body: { to, text: 'Seu pedido #1042 saiu para entrega 🚚' },
});

O TypeMessage é um enum, e é ele que faz o trabalho pesado no editor: o autocompletar lista os tipos disponíveis, e o corpo esperado muda conforme o tipo escolhido.

// o compilador recusa: mensagem de texto não tem `url`
await wa.message.send({
  type: TypeMessage.TEXT,
  body: { to, url: 'https://exemplo.com/foto.jpg' },
});

Esse erro, num projeto sem tipos, seria uma resposta 400 em produção às três da manhã.

Mídia

await wa.message.send({
  type: TypeMessage.IMAGE,
  body: { to, url: 'https://exemplo.com/nota.jpg', caption: 'Sua NF-e' },
});

await wa.message.send({
  type: TypeMessage.AUDIO,
  body: { to, url: 'https://exemplo.com/audio.mp3' },
});

Os três canais

await wa.message.send({
  type: TypeMessage.TEXT,
  body: { to, text: 'Oi', provider: 'instagram' },
});

Um campo. Sem provider, vai no WhatsApp; com instagram ou messenger, vai no outro canal — mesma instância, mesma chave, mesmo webhook.

Instância e webhook

// Conectar (API não oficial)
const qr = await wa.instance.connect();
const code = await wa.instance.pairingCode('5566996852025');

// Estado
const info = await wa.instance.info();

// Operação
await wa.instance.logout();
await wa.instance.restart();
await wa.instance.resync();

Configurar para onde os eventos vão:

await wa.instance.updateWebhook({
  allowWebhook: true,
  allowNumber: 'all',
  webhookMessage: 'https://seusistema.com/webhook/wame',
  webhookFormat: 'meta',   // envelope da Cloud API — o mesmo p/ os 3 canais
});

const stats = await wa.instance.webhookStatistics();

O webhookStatistics() vale conhecer: quando o webhook "para de funcionar", ele mostra se as entregas estão saindo e falhando ou se nem estão sendo tentadas — o que decide em que lado procurar. É o primeiro passo depois do teste com webhook.site.

O handler que serve os três canais

import express from 'express';

type EventoWame = {
  provider: 'whatsapp' | 'instagram' | 'messenger';
  entry: Array<{
    changes: Array<{
      value: {
        messages?: Array<{
          from: string;
          id: string;
          type: string;
          text?: { body: string };
        }>;
        statuses?: Array<{ id: string; status: string }>;
      };
    }>;
  }>;
};

const app = express();
app.use(express.json());

app.post('/webhook/wame', (req, res) => {
  res.sendStatus(200);                     // primeiro isto, sempre
  processar(req.body as EventoWame).catch(console.error);
});

async function processar(evento: EventoWame) {
  const value = evento.entry?.[0]?.changes?.[0]?.value;

  // `statuses` é entrega/leitura, não mensagem nova.
  const msg = value?.messages?.[0];
  if (!msg || msg.type !== 'text') return;

  await registrar({
    canal: evento.provider,
    de: msg.from,
    texto: msg.text!.body,
    messageId: msg.id,
  });
}

Um handler. Três canais. O único campo que varia é provider.

Em Next.js e serverless

Só no servidor:

// app/api/webhook/wame/route.ts
export async function POST(req: Request) {
  const evento = await req.json();
  after(() => processar(evento));   // responde já, processa depois
  return Response.json({ ok: true });
}

Nunca chame o SDK a partir do cliente. A chave da instância iria para o bundle, e qualquer visitante poderia enviar mensagem pelo seu número. Server action, route handler ou função serverless — nunca componente de cliente.

Em serverless há uma segunda armadilha: se você responde e a função encerra, o processamento em segundo plano morre junto. Use o mecanismo da plataforma para trabalho pós-resposta (after no Next, waitUntil em edge runtimes) ou empurre para uma fila.

Tratamento de erro

try {
  await wa.message.send({ type: TypeMessage.TEXT, body: { to, text } });
} catch (e) {
  // Número sem WhatsApp, instância desconectada, limite atingido.
  // O erro traz o código; trate cada caso, não engula tudo num catch mudo.
  console.error('falha ao enviar para', to, e);
  await enfileirarParaNovaTentativa({ to, text });
}

Vale conferir antes de mandar, quando a lista veio de cadastro do cliente:

const existe = await wa.contact.checkNumber(to);
if (!existe) return marcarInvalido(to);

Isso é o que separa uma lista que entrega de uma lista que queima reputação — assunto de higiene de lista e opt-out.

Conclusão

O ganho do SDK tipado não é escrever menos: é o compilador recusando o payload errado antes do deploy. Com três canais no mesmo contrato, isso vale três vezes.

Se você trabalha em PHP, o SDK PHP cobre o mesmo terreno. Se vai colocar isso em produção, webhook em produção trata da parte que só aparece com volume.

Referência completa em docs/sdk/ts.

Pronto para automatizar seu WhatsApp?

Crie sua conta gratuita e comece a enviar mensagens pela API em minutos.

Começar grátis

Perguntas frequentes

Como instalar o SDK JavaScript da WAME?+

npm install @raphaelvserafim/client-api-whatsapp. O pacote já inclui as definições de tipo, então funciona em JavaScript puro e em TypeScript sem instalar @types separado.

O SDK funciona com TypeScript?+

Sim, e é onde ele rende mais. Os tipos de mensagem são um enum (TypeMessage) e o corpo de cada tipo é tipado, então o editor mostra os campos válidos e o compilador acusa erro se você mandar url numa mensagem de texto.

Dá para usar o SDK em Next.js ou em serverless?+

Sim, desde que a chamada aconteça no servidor: route handler, server action ou função serverless. Nunca no cliente — a chave da instância ficaria exposta no bundle e qualquer pessoa poderia enviar mensagens em nome do seu número.

Como enviar no Instagram e no Messenger pelo SDK?+

É o mesmo método send, com o campo provider no corpo da mensagem. WhatsApp é o padrão; informar instagram ou messenger direciona a mesma chamada ao outro canal, porque a instância cobre os três.

O SDK cobre criação de instância?+

Sim. O objeto instance expõe conexão por QR Code e por pairing code, informações, logout, restart, resync e configuração de webhook — o suficiente para provisionar e operar contas sem ninguém abrir um painel.

Continue lendo