Quickstart
Goal: get from "no account" to "WhatsApp message sent" in five steps. We'll use curl here. The same calls work from any HTTP client.
You'll need a real WhatsApp account to scan the QR. Use a secondary number — the gateway opens a WhatsApp Web session on it just like the WhatsApp Web tab in your browser.
1 · Get an API key
Sign in to the dashboard at https://app.whatisup.dev. Three sign-in providers are supported:
- Email + password — instant, no third party.
- Google — one-click OAuth.
- GitHub — one-click OAuth, requests
read:user+user:emailso we have your name + email for the customer record.
Pick whichever you prefer. If you sign up under one provider and later sign in with a different one using the same email, the dashboard transparently links them so you keep a single customer record.
Then Settings → API keys → Create. Copy the key — it's only shown once. Set it as an env var so the snippets below work as-is:
export WHATISUP_API_KEY=zpk_••••••••
export WHATISUP_API=https://api.whatisup.dev2 · Create a channel
A channel is one logical WhatsApp connection. Each gets its own QR.
curl -sX POST "$WHATISUP_API/v1/channels" \
-H "Authorization: Bearer $WHATISUP_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"primary"}'You'll get back something like:
{
"id": "inst_01J...",
"name": "primary",
"status": "pending",
"created_at": "2026-05-01T12:34:56.000Z"
}The status: "pending" means the gateway hasn't started a session yet. Take note of the id — you'll use it everywhere below as CHANNEL_ID.
3 · Get the QR code
Call the QR endpoint until it returns one. The channel starts a session on first QR fetch.
curl -s "$WHATISUP_API/v1/channels/inst_01J.../qr" \
-H "Authorization: Bearer $WHATISUP_API_KEY"The response carries a base64-encoded PNG and a wire-format string:
{
"qr": "data:image/png;base64,iVBORw0KGgo...",
"raw": "2@dPBI4Tg9Mc...,vlD4Pmkr...",
"expires_at": "2026-05-01T12:35:25.000Z"
}Open the data URL in your browser, or pipe .qr through a renderer. Scan it from WhatsApp → Settings → Linked devices → Link a device.
The dashboard UI does this for you in real time over SSE. If you'd rather not deal with QR plumbing yourself, point the dashboard at your gateway and click Pair.
4 · Wait for connected
Poll the channel until status flips to connected:
curl -s "$WHATISUP_API/v1/channels/inst_01J..." \
-H "Authorization: Bearer $WHATISUP_API_KEY"…or, much better, subscribe to Server-Sent Events and react to channel.connected:
curl -s "$WHATISUP_API/v1/events" \
-H "Authorization: Bearer $WHATISUP_API_KEY"5 · Send your first message
curl -sX POST "$WHATISUP_API/v1/channels/inst_01J.../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 is a WhatsApp JID — <digits>@s.whatsapp.net (country code + national number, no +, then @s.whatsapp.net). The gateway returns 202 with a message_id and emits a message.sent webhook. It persists no message bodies, so there's no message-status endpoint to poll — track delivery via your webhook.
Where to next
- Wire up a webhook so you stop polling: Concepts → Webhooks.
- Verify webhook signatures: Webhooks → Signature verification.
- Explore the full REST surface: API reference → Channels.