Getting started
Authentication
Every REST and WebSocket-starting request needs a bearer token:
Authorization: Bearer <token>
Wakili accepts two kinds of token in that header, auto-detected by shape:
| Token | Looks like | Use for |
|---|---|---|
| API key | wak_... | Server-to-server integration. Long-lived, scoped to your account, revocable individually. |
| Dashboard session token | Supabase JWT | The Wakili dashboard itself (browser login). Not meant for your own integration code. |
API keys
Generate one from an agent's Connect tab in the dashboard, or via the API keys API. The raw key is shown exactly once at creation — store it immediately, Wakili only ever stores its hash afterward.
An API key authenticates as your account, not as a single agent — it can call any endpoint scoped to your account (create/list/delete agents, start calls on any of your agents, read usage and billing). Treat it like a database credential:
- Never ship it to a browser. Call the Wakili API from your own backend, and only forward the short-lived
ws_urla call start returns to the client. See the Next.js integration guide for the exact pattern. - One key per integration/environment. Makes revoking a compromised key (or rotating for a decommissioned service) not touch anything else.
- Delete unused keys.
DELETE /api-keys/{key_id}.
Listing and revoking keys
# list
curl https://api.wakili.dev/api-keys -H "Authorization: Bearer wak_..."
# revoke
curl -X DELETE https://api.wakili.dev/api-keys/{key_id} -H "Authorization: Bearer wak_..."
GET /api-keys never returns the raw key — only id, name, key_prefix, last_used_at, created_at, so you can identify a key without ever having it live again.
The talk WebSocket doesn't take a token
WS /calls/{call_id}/talk takes no Authorization header and no token in the query string. Auth happens once, up front, on the authenticated POST /agents/{agent_id}/calls call that mints the call_id — the WebSocket just presents that single-use, short-lived id. This keeps credentials out of the WS URL entirely (query strings end up in logs, browser history, proxies).