Auth, scopes and limits
Every request carries a bearer token the owner created for one app.
Tokens
olxcore api token create <app> --scopes chat,models [--allow-dir DIR]...
olxcore api token list
olxcore api token revoke <token-id|app>
- Send
Authorization: Bearer olxk_...on every HTTP request. On the socket, the first line is{"type":"auth","token":"..."}. - Tokens live in
~/.olx/api/tokens.json(mode 0600, directory 0700), stored as a SHA-256 hash. The secret is printed once at creation. - Revoking takes effect on the next request, and on the next message of an open socket connection.
- App names are 1 to 40 characters: letters, digits,
._-.
Scopes
| scope | grants |
|---|---|
models | Local model completions only (GET /v1/models, POST /v1/chat/completions). No tools, no sessions. |
chat | Turns and sessions of this app's own sessions. A turn runs the olix loop; actions that change something wait for the owner. |
history.read | Read the owner's saved sessions (all apps). The owner grants it per token, with --scopes. |
computer Coming | Coming. Missions on the owner's Mac. Not built; a token cannot be created with it yet. |
GET /v1/status and GET /v1/settings/schema work with any valid token. A request without the scope gets 403 forbidden_scope.
Folders
A chat turn runs in a project folder. By default that is the app's own workspace under ~/.olx/api/workspaces/<app>. A request may name a cwd only if it is inside a folder the owner granted with --allow-dir. The path is resolved first, so a symlink out of a granted folder is refused. Nothing under ~/.olx can be granted or named.
Sessions belong to the app
A session started by a token's app can be continued, listed and read only by that app. Another app gets 404. Reading the owner's other sessions needs the separate history.read scope.
Limits
- Rate: 120 requests per minute per app (
429 rate_limitedwithRetry-After). - Concurrent turns: 2 per app (
429 too_many_turns). - Open questions: a card nobody decides is denied after 5 minutes, so a turn cannot hang.
- Bodies: up to 8 MB; turn text up to 100,000 characters.
- Disconnect: if a client leaves a streaming or waiting turn, the turn is interrupted.
Audit log
Every request is appended to ~/.olx/api/audit.jsonl (mode 0600): time, app, token id, scope, method, endpoint and status. Never the prompt, the reply, or the token. Session and turn ids in paths are replaced by :id.
{"t":"2026-11-06T12:00:00.000Z","app":"my-app","token":"1a2b3c4d","scope":"chat","method":"POST","endpoint":"/v1/turns","status":200}
Errors
Every error is JSON: {"error": {"message", "type", "code", "param"}}, the same shape OpenAI clients expect.
| code | HTTP | meaning |
|---|---|---|
unauthorized | 401 | Missing, unknown or revoked token. |
forbidden_scope | 403 | The token does not carry the scope this endpoint needs. |
forbidden_host | 403 | Host header or client address is not loopback. |
approval_not_allowed | 403 | An API client may only deny an approval. Approving is the owner's, in the olix app. |
bad_request | 400 | The body does not match the schema; the message names the field. |
not_found | 404 | No such route, turn, session or question for this token. |
rate_limited | 429 | Too many requests for this app; retry after the Retry-After seconds. |
too_many_turns | 429 | This app already has the maximum number of turns running. |
model_memory | 503 | The model does not fit in the memory this Mac can spare right now; the message gives the engine's reason. No other model is substituted. |
core_unavailable | 503 | The olix core is not running. Open olix and retry. |
engine_error | 502 | The engine returned an error; the message is the engine's own. |
Two more: api_off (503, the owner turned the API off) and forbidden_dir (403, a folder outside the grant).
What a client without a token sees
curl -si http://127.0.0.1:8780/v1/statusHTTP/1.1 401 Unauthorized
content-type: application/json
{"error":{"message":"missing, unknown or revoked token","type":"invalid_request_error","code":"unauthorized","param":null}}