Tour the dashboard
The dashboard is a web UI for everything you would otherwise drive through the API: create and connect sessions, scan QR codes inline, register webhooks with a visual filter builder, and — as an admin — mint and revoke API keys. This guide walks you through each area and what it does.
- A running OpenWA instance. See Quick start if you don't have one yet.
- An OpenWA API key to sign in with. Generating one is covered in Authentication.
Sign in and what you'll see
The dashboard ships inside the OpenWA process. With a default install it's served from the same origin and port as the API — open http://localhost:2785/ in a browser and sign in with your API key.
What you can see is role-gated. The key's role (admin, operator, or viewer) decides which pages mount in the sidebar. Admin-only pages are not just hidden — a non-admin who types the URL directly is redirected away.
| Page | What it's for | Role |
|---|---|---|
| Dashboard | Overview: session counts, message volume, recent activity | all |
| Sessions | Create, start, stop, show the QR, and delete sessions | all |
| Chats | Browse chat threads, updated live over WebSocket | all |
| Webhooks | Register and manage per-session webhook endpoints | all |
| Templates | Manage reusable message templates | all |
| Message Tester | Fire ad-hoc sends and check whether a number is on WhatsApp | all |
| Logs | Activity and audit trail | all |
| API Keys | Create, list, and revoke API keys | admin |
| Infrastructure | Runtime status and configuration | admin |
| Plugins | Install, enable, and configure plugins | admin |
Light/dark mode and the accent palette are set from a popover in the sidebar footer and remembered in your browser. There is no separate Settings page.
Every action below maps to a documented API route. The dashboard calls the same http://localhost:2785/api endpoints you'd call with curl. Where a page maps to an endpoint, this guide names it so you can script the same workflow.
Sessions: connect a number with an inline QR
The Sessions page is where a WhatsApp number goes from "created" to "connected." Each row shows the session's live status, so you can see at a glance which numbers are online.
From a row you can:
- Create a session and name it —
POST /api/sessions. - Start or stop it —
POST /api/sessions/{id}/start,POST /api/sessions/{id}/stop. - Show the QR to link a phone —
GET /api/sessions/{id}/qr. - Delete it when you're done —
DELETE /api/sessions/{id}.
The inline QR view
When you start a session that needs linking, a QR Code view opens right on the Sessions page — you don't fetch and render the QR yourself. The view shows a countdown to expiry and a Refresh QR button that requests a fresh code if the current one times out before you scan.
Scan it from your phone under WhatsApp → Linked Devices → Link a Device. Once the link succeeds the session flips to connected and the QR view closes on its own.
Under the hood the page reads the QR from the API once, then receives refreshed codes pushed live over a WebSocket, which is why the image updates without a page reload. The QR endpoint returns a ready-to-render data URL:
curl http://localhost:2785/api/sessions/sales-bot/qr \
-H "X-API-Key: YOUR_API_KEY"
{
"qrCode": "data:image/png;base64,iVBORw0KGgoAAAANS...",
"status": "qr_ready"
}
If the session is already linked, the same call returns 400 (QR code not ready or session already authenticated) — the dashboard shows the session as connected instead of opening the QR view.
For the full session lifecycle and the same flow in curl and the SDK, see Sessions & multi-session.
Webhooks: build event filters without writing JSON
The Webhooks page lists every webhook for a session with its URL, the events it subscribes to, and whether it's active. From here you can:
- Add a webhook — URL, the events it fires on, an optional signing secret, custom headers, and filters (
POST /api/sessions/{sessionId}/webhooks). - Edit a webhook, or enable/disable it without deleting (
PUT /api/sessions/{sessionId}/webhooks/{id}). - Test it — send a synthetic delivery and see whether your endpoint accepts it (
POST /api/sessions/{sessionId}/webhooks/{id}/test). - View logs of past deliveries.
The visual filter builder
A webhook can subscribe to any of these events:
message.received message.sent message.ack message.failed
message.revoked message.reaction session.status session.qr
session.authenticated session.disconnected group.join group.leave group.update
Beyond the event list, the page includes a filter builder for narrowing which matching events actually get delivered. You compose conditions as field / operator / value rows in the UI; the dashboard serializes them into the webhook's filters object, so you never hand-write that JSON. For example, "only deliver message.received from one chat" becomes a single condition row instead of a JSON blob.
Use Test before relying on a webhook in production — it sends a sample payload to your URL so you can confirm the endpoint is reachable and returns a 2xx, without waiting for a real WhatsApp event.
For the payload shape of each event and how to verify the HMAC signature on every delivery, see Webhooks.
API keys (admin): create, copy once, revoke
The API Keys page is admin-only. It's where you provision the keys that every other client — including the dashboard itself — signs requests with.
From the page you can:
- Create a key with a name, a role (
viewer,operator, oradmin; defaultoperator), and optional IP or session scoping (POST /api/auth/api-keys). - List existing keys by prefix, role, and usage (
GET /api/auth/api-keys). - Revoke a key to disable it (
POST /api/auth/api-keys/{id}/revoke), or delete it (DELETE /api/auth/api-keys/{id}).
When you create a key, the response includes the complete secret in the apiKey field — and that is the only time it's ever returned. Copy it immediately. Afterward, every list view shows only keyPrefix (the first 12 characters — the owa_k1_ prefix plus 5 hex chars), never the full value. If you lose it, revoke the key and create a new one.
Creating a key over the API returns the copy-once secret alongside its metadata:
curl -X POST http://localhost:2785/api/auth/api-keys \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "n8n integration", "role": "operator"}'
{
"id": "a1b2c3d4-...",
"name": "n8n integration",
"keyPrefix": "owa_k1_3f9a2",
"role": "operator",
"isActive": true,
"usageCount": 0,
"createdAt": "2026-06-26T10:00:00.000Z",
"apiKey": "owa_k1_3f9a...full-secret-here..."
}
The dashboard surfaces that apiKey value in a copy-to-clipboard panel at creation, then drops it. Every subsequent list call returns the same record without the apiKey field — only keyPrefix for identification.
For roles, what each can do, and IP/session scoping, see Authentication.
Other tools
- Message Tester sends any message type ad-hoc and runs a number check (
GET /api/sessions/{sessionId}/contacts/check/{number}) — useful for validating a session before wiring it into an integration. See Sending messages for the underlying send endpoints. - Chats shows live chat threads. New messages arrive over a WebSocket, so the thread updates without a refresh.
- Logs gives you an activity and audit trail across the instance (
GET /api/audit).
Troubleshooting
| Problem | Cause | Fix |
|---|---|---|
| Sidebar is missing API Keys / Infrastructure / Plugins | Your key isn't an admin key | Sign in with an admin key, or have an admin grant you one. Roles are described in Authentication. |
| QR view never shows a code | The session is already connected, or hasn't been started | Stop and restart the session, or check the row status — a connected session has no QR. |
| QR scanned but row stays "awaiting QR" | The code expired before the phone finished linking | Click Refresh QR to get a new code and scan again promptly. |
| Webhook Test returns a failure | Your endpoint is unreachable or didn't return 2xx | Confirm the URL is publicly reachable from the instance and responds with a 2xx. Check View logs for the status it saw. |
| You can't find a key's full secret | The full value is only shown once, at creation | Revoke the old key and create a new one; copy it immediately this time. |
For wider issues, see Troubleshooting.
Next steps
- Sessions & multi-session — the API behind the Sessions page.
- Webhooks — event payloads and signature verification.
- Authentication — roles, scoping, and key management.
- Sending messages — what the Message Tester drives.