Pular para o conteúdo
whatsapi.sh
Tema
Docs

O cliente TypeScript

Um método tipado por endpoint, gerado das mesmas definições que respondem às suas requisições. O que o seu editor diz é o que a API faz. Zero dependências, ESM, Node 20+.

Instale

npm
npm i @whatsapi.sh/sdk

O cliente recebe a sua chave uma vez e leva ela pra todo lado. Depois disso é só chamar métodos. Cada método, argumento e campo chega com a documentação que você está lendo agora anexada, então passar o mouse no editor rende mais que abrir outra aba. TypeScript é opcional: o pacote é ESM puro e funciona em JavaScript, inclusive com require() no Node 22.12+.

Envie alguma coisa

send
import { Whatsapi } from "@whatsapi.sh/sdk";

const wa = new Whatsapi({ apiKey: process.env.WHATSAPI_KEY });

const message = await wa.sendMessage({
  to: "+5511988887777",
  text: "Your table is ready.",
});

console.log(message.id, message.quotaRemaining);

Todo método recebe um objeto e devolve exatamente o que o endpoint responde, incluindo quotaRemaining, então um medidor de uso não precisa de uma segunda chamada.

Lidando com os erros

errors
import { WhatsapiError } from "@whatsapi.sh/sdk";

try {
  await wa.sendMessage({ to, text });
} catch (error) {
  if (!(error instanceof WhatsapiError)) throw error;

  if (error.code === "PAYMENT_REQUIRED") return offerAnUpgrade();
  if (error.code === "NUMBER_NOT_CONNECTED") return askForARepair();
  if (error.code === "GATEWAY_TIMEOUT") return watchFor(error.messageId);
  throw error;
}

As falhas chegam como WhatsapiError, carregando o código da própria API, o status HTTP, um retryAfter sempre que dá para saber a espera, e o id da requisição para citar no suporte.

Quando o envio fica sem confirmação

GATEWAY_TIMEOUT significa que o WhatsApp não confirmou a tempo. Não sabemos se a mensagem chegou. Se error.messageId vier na resposta, acompanhe esse id no webhook message.status para saber se ela chegou. Confira a conversa antes de enviar de novo. Outro envio com uma chave nova, ou sem chave, pode duplicar a mensagem. Com a mesma idempotencyKey, você recebe a mesma resposta, sem um segundo envio.

O que tenta de novo, e o que nunca tenta

idempotencyKey
const message = await wa.sendMessage(
  { to: "+5511988887777", text: "Your table is ready." },
  { idempotencyKey: order.id },
);

Dê a um envio uma idempotencyKey, um id que você escolhe, como o id de um pedido. Se o envio falhar sem resposta ou com um 5xx, o cliente manda de novo com a mesma chave de idempotência, e a API responde com o primeiro resultado em vez de mandar a mensagem duas vezes. Se o primeiro envio ainda estiver rodando, a API responde 409 com um Retry-After, e o cliente espera esse tempo e tenta de novo. Guarde essa chave junto com o que você está enviando, para que uma nova tentativa depois de uma queda use a mesma. Leitura também tenta de novo depois de um 5xx ou de uma resposta perdida. Envio sem chave de idempotência nunca é repetido depois de um 5xx ou de uma resposta perdida: seria uma segunda mensagem de verdade pra uma pessoa de verdade. Um 429 que libera em até 10 segundos é repetido em qualquer chamada, porque nada rodou.

Confira o que chega

verifyWebhook
import { verifyWebhook } from "@whatsapi.sh/sdk";

const event = await verifyWebhook({
  payload: rawBody, // the raw bytes, not the parsed body
  signature: req.header("x-whatsapi-signature"),
  secret: process.env.WHATSAPI_WEBHOOK_SECRET,
});

if (event.type === "message.created") {
  await reply(event.data.number.id, event.data.message.text);
}

verifyWebhook confere a assinatura, recusa entrega repetida e devolve o evento já estreitado pelo type, então os campos do payload são conhecidos antes de você tocar neles.

Construindo um agente?

Então você quer MCP, não este pacote: as mesmas operações como ferramentas, com a mesma chave. O cliente é pros aplicativos que você mesmo escreve.