Skip to content
WhatIsUp.dev

Quickstart

Objetivo: sair de "sem conta" até "mensagem de WhatsApp enviada" em cinco passos. Aqui a gente usa curl. As mesmas chamadas funcionam em qualquer cliente HTTP.

Você vai precisar de uma conta real de WhatsApp para escanear o QR. Use um número secundário — o gateway abre uma sessão do WhatsApp Web nele, igual à aba do WhatsApp Web no seu navegador.

1 · Pegue uma chave de API

Entre no dashboard em https://app.whatisup.dev. Há três provedores de login suportados:

  • E-mail + senha — instantâneo, sem terceiros.
  • Google — OAuth em um clique.
  • GitHub — OAuth em um clique, pede read:user + user:email para a gente ter seu nome + e-mail no cadastro de cliente.

Escolha o que preferir. Se você se cadastrar por um provedor e depois entrar por outro usando o mesmo e-mail, o dashboard vincula os dois de forma transparente para você manter um único cadastro de cliente.

Depois Configurações → Chaves de API → Criar. Copie a chave — ela só é mostrada uma vez. Defina como variável de ambiente para os trechos abaixo funcionarem como estão:

export WHATISUP_API_KEY=zpk_••••••••
export WHATISUP_API=https://api.whatisup.dev

2 · Crie um canal

Um canal é uma conexão lógica de WhatsApp. Cada um ganha seu próprio QR.

curl -sX POST "$WHATISUP_API/v1/channels" \
  -H "Authorization: Bearer $WHATISUP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"primary"}'

Você vai receber algo assim de volta:

{
  "id": "8d653c66-e4ff-43ee-97da-3de5ad5680d4",
  "customer_id": "2696bc9b-2e37-43d9-a33b-5a79f81daeba",
  "name": "primary",
  "phone_number": null,
  "status": "pending",
  "last_seen_at": null,
  "metadata": {},
  "created_at": "2026-05-01T12:34:56.000Z",
  "updated_at": "2026-05-01T12:34:56.000Z"
}

Responde 201. status: "pending" significa que o gateway ainda não iniciou uma sessão, e phone_number fica null até o pareamento terminar. Anote o id — um UUID v4 — você vai usá-lo em tudo abaixo como CHANNEL_ID:

export CHANNEL_ID=8d653c66-e4ff-43ee-97da-3de5ad5680d4

Multi-tenant? Passe "issue_scoped_key": true nesta chamada e a resposta traz também scoped_key.secret — uma chave de API que só alcança este canal. Mostrada uma vez, nunca mais legível.

3 · Pegue o código QR

Chame o endpoint de QR até ele retornar um. O canal inicia uma sessão na primeira busca de QR.

curl -s "$WHATISUP_API/v1/channels/:id/qr" \
  -H "Authorization: Bearer $WHATISUP_API_KEY"

A resposta carrega exatamente dois campos:

{
  "qr_png_base64": "iVBORw0KGgoAAAANSUhEUgAA...",
  "expires_at": 1779425257573
}
CampoTipoNotas
qr_png_base64stringBase64 pura de um PNG. Sem prefixo data: — coloque o seu.
expires_atnumberEpoch Unix em milissegundos, não uma string ISO.

Não existe raw / string de formato de rede na resposta. Para ver:

curl -s -H "Authorization: Bearer $WHATISUP_API_KEY" \
  "$WHATISUP_API/v1/channels/$CHANNEL_ID/qr" \
  | jq -r .qr_png_base64 | base64 -d > qr.png && open qr.png

Escaneie pelo WhatsApp → Configurações → Aparelhos conectados → Conectar um aparelho.

Se o canal ainda não tem QR, você recebe 409 no_qr — essa é a resposta normal de "tente de novo em instantes" enquanto a sessão sobe, não um erro para abortar.

Prefere não escanear? POST /v1/channels/$CHANNEL_ID/pair-code com {"phone_number":"5511999999999"} devolve um código de 8 caracteres que você digita no WhatsApp → Aparelhos conectados → Conectar com número de telefone.

A interface do dashboard faz isso para você em tempo real via SSE. Se você prefere não lidar com o encanamento do QR na mão, aponte o dashboard para o seu gateway e clique em Parear.

4 · Espere por connected

Consulte o canal até o status virar connected:

curl -s "$WHATISUP_API/v1/channels/:id" \
  -H "Authorization: Bearer $WHATISUP_API_KEY"

…ou, bem melhor, assine os Server-Sent Events e reaja ao channel.connected:

Mantenha a conexão aberta. Todo frame é um evento SSE NOMEADO — escute por nome, não em `message`. Veja a página de SSE.
curl -s "$WHATISUP_API/v1/events" \
  -H "Authorization: Bearer $WHATISUP_API_KEY"

5 · Envie sua primeira mensagem

curl -sX POST "$WHATISUP_API/v1/channels/:id/messages" \
  -H "Authorization: Bearer $WHATISUP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"type":"text","to":"5511999999999@s.whatsapp.net","text":"Hello from WhatIsUp.dev"}'

to é um JID do WhatsApp — <dígitos>@s.whatsapp.net (código do país + número nacional, sem +, depois @s.whatsapp.net). O gateway retorna 202:

{
  "message_id": "3EB0C9A17F2B4D8E1A05",
  "client_ref": null,
  "status": "sent"
}

status é "sent" quando o canal estava conectado e o WhatsApp aceitou a mensagem, ou "queued" quando o canal estava em recuperação e vamos retentar. Nos dois casos você recebe o mesmo message_id, e um webhook message.sent dispara no sucesso.

Para acompanhar a entrega depois, use o webhook message.status (sentdeliveredread), ou leia GET /v1/messages — o gateway mantém sim um histórico de mensagens paginável, com corpos e as entregas de webhook que carregaram cada uma.

Para onde ir agora