Authentication.
Every request to LeanVoice, REST or WebSocket, carries an API key. Keys are scoped to a workspace, can be rotated at any time, and never expire on their own.
Bearer header
Pass the key as a bearer token in the Authorization header:
Authorization: Bearer sk_live_a1b2c3d4e5f6...
Keys begin with sk_live_ (production) or sk_test_ (sandbox). Sandbox keys can synthesise any voice but return a watermarked audio stream and don't count against your monthly free tier.
WebSocket sub-protocol
WebSockets can't set arbitrary headers in the browser, so the key is carried in the Sec-WebSocket-Protocol handshake header instead:
new WebSocket(url, ["bearer", "sk_live_..."]);
The server replies with the same sub-protocol on the 101 Switching Protocols response. Treat any other reply as a fatal handshake error.
Rotation
Generate a new key from the dashboard, deploy it to your application, then revoke the old one. We recommend rotating at least quarterly. Revocation is immediate; in-flight requests using the revoked key finish normally and new ones receive a 401 invalid_api_key.
Scoped keys
Keys can be restricted to specific voices, languages, daily character budgets, or IP CIDR ranges. Useful for shipping a key to an edge worker or a mobile app where you can't fully trust the runtime.
| Scope | Type | Example |
|---|---|---|
| voices | string[] | ["meera","arjun"] |
| languages | string[] | ["en","es"] |
| daily_char_limit | integer | 50000 |
| allowed_ip_cidrs | string[] | ["203.0.113.0/24"] |
For client-side use, generate a short-lived ephemeral token from your server with POST /v1/ephemeral_tokens. Ephemeral tokens last 15 minutes and inherit a subset of the parent key's scopes.