Getting started
Authentication
Every call to the MCP server, the tools API and the REST API authenticates with one credential: a workspace API key, sent as a bearer token.
Authorization: Bearer lt-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxAPI keys#
- Format.
lt-followed by 32 URL-safe base64 characters (35 characters in total). Keys issued before the LeanTools rename start withgsk-and remain valid. - Where they come from. Every new workspace gets a
default-keyat sign-up. Owners and Admins create more under Settings → API keys; Developers can create keys for themselves. Operators of the host can also issue keys from the admin panel. - What they identify. Exactly one workspace, which is billed for every call made with the key, and the member who created it, who is shown next to each call in the activity log.
- Storage. Only the SHA-256 hash is stored. The plaintext is shown once at creation (and at rotation) and cannot be retrieved later; the console shows the prefix,
••••••••and the last four characters.
Scope, cap and expiry#
A key carries three limits, all set in the console:
| Limit | Effect | Refusal |
|---|---|---|
| Scope | "Everything enabled", or a list of tools the key may reach (Search, Browser, the seven LeanModel catalogues from TextAssistant to RealtimeAssistant, Email, Machine, Data, Connectors, …). Connectors can additionally restrict which keys may call them. | 403 service_not_allowed, 403 key_not_allowed |
| Monthly cap | Credits the key may spend in a calendar month (UTC). The dashboard shows spend against cap per key. | 402 key_cap_reached |
| Expiry | A date after which the key is refused. Rotate it to issue a fresh key with the same settings and revoke the old one at once. | 401 key_expired |
Admission order#
Each call is checked in this order: credential → workspace status → tool enabled → key scope → tool budget and key cap → credits → tool-specific guardrails. Credentials and workspace policy are cached for 60 seconds (LeanTools.Credits.CredentialCacheSeconds); changes made in the console invalidate the cache for that workspace at once, so a revoked key or a disabled tool is refused immediately.
Where the key goes#
- Header for everything:
Authorization: Bearer <key>. - Query string only where a header is impossible: the LeanBrowser WebSocket upgrades (
?token=…), the LeanVision live feed and the LeanModel realtime audio socket. Every other endpoint rejects a key in the query so keys never end up in access logs or browser history. - WebSocket subprotocol on the realtime audio socket only, for browser clients that can set neither headers nor a safe query string: offer
openai-insecure-api-key.<key>as a subprotocol, as OpenAI's browser clients do; LeanTools accepts it and echoesrealtimeas the agreed subprotocol when it was offered too (see the reference). - LeanMemory's high-throughput columnar data channel (gRPC; see the reference) takes the same bearer in the
authorizationgRPC metadata.
Error envelope#
A refused call answers a JSON envelope with a stable errorCode:
{ "isSuccess": false, "errorMessage": "This API key has expired. Create a new key in the console.", "errorCode": "key_expired" }The OpenAI-compatible endpoints use the OpenAI envelope ({ "error": { "message", "type", "code" } }); the MCP server answers JSON-RPC errors for protocol failures and isError: true results for tool failures. The full list is on the Errors page.
Console sign-in#
The workspace console at /app and the public site use a separate, per-person sign-in (email and password) that issues a short-lived session token in a cookie. API keys never sign in to the console, and console sessions never authenticate API calls. Invite teammates from Settings → Members; each accepts with their own account.
Treat API keys as secrets. Put them in environment variables or your harness's secret store, never in prompts, repositories or client-side code. If a key leaks, revoke it in the console: every agent using it is refused within a minute.