Skip to content

HTTP API reference

The engine exposes a loopback-first API under http://{host}:{port}/api/v1. Read runtime.json from the engine data directory to discover the current host, port, and bearer token; do not hard-code production values.

Authentication and conventions

GET /health is public. Every other operation below requires Authorization: Bearer <runtime-token>. An invalid or missing token returns 401 {"error":"Missing or invalid bearer token."}. Authentication uses constant-time comparison.

Most typed REST objects use camelCase on the wire and accept camelCase or snake_case input. Account objects and most WebSocket data use snake_case. RAG results intentionally contain mostly snake_case fields plus rootIndex. Timestamps are ISO-8601 UTC strings.

A shared schema failure is 400 {"error":"Invalid request body.","details":"..."}. Settings, models, tools, and RAG use 400 {"error":"Invalid request body."} without details. Resource misses normally use 404 {"error":"<Resource> not found."}, but some endpoints intentionally return an empty body or collection; those cases are listed below.

PUT does not have one universal meaning

Workspace PUT is a full replacement and requires name. Thread PUT is patch-like: omitted fields are preserved and explicit null clears them. Model PUT requires provider/model and has field-specific credential preservation. Tool PUT has its own preservation rules.

Request and response objects referenced below are defined in Schemas.

System and account

Method and path Request Success Errors and notes
GET /health None; public 200 Health The only public operation.
GET /account/session None 200 AccountSession Cloud/secure-store AccountError status with Error; an expired/rejected saved session becomes a logged-out 200.
POST /account/login AccountLogin 200 AccountSession 400 if email/password are missing or blank; cloud status or 502 may pass through.
POST /account/signup/code SignupCodeRequest 200 {notice} 400 for missing/blank email; cloud/account error otherwise.
POST /account/signup/complete SignupCompleteRequest 200 AccountSession 400 for missing/blank email, code, or password.
POST /account/logout Body ignored 200 {authenticated:false,user:null} Local credentials are cleared even when remote logout fails.
POST /agui Body ignored 200 {message:"AG-UI endpoint not yet implemented"} Placeholder only; do not integrate against it.

Workspaces, threads, and messages

Method and path Request Success Errors and notes
GET /workspaces None 200 Workspace[], ordered by name —
POST /workspaces CreateWorkspace 200 Workspace 400 schema error; uses an existing network when present (selection is unordered), otherwise creates default.
GET /workspaces/{uuid} uuid path string 200 Workspace 404 Error.
PUT /workspaces/{uuid} CreateWorkspace 200 Workspace Full replacement; omitted nullable fields become null; 400/404.
DELETE /workspaces/{uuid} uuid 204 empty 404 Error; cascades database children, not filesystem roots/sidecars.
GET /workspaces/{uuid}/threads uuid 200 Thread[], newest-updated first Unknown workspace returns 200 [].
POST /threads CreateThread 200 Thread 400; unknown workspace returns 404 Error; publishes thread.created.
GET /threads/{uuid} uuid 200 Thread 404 Error.
PUT /threads/{uuid} UpdateThread 200 Thread Patch-like; {} is valid and refreshes updatedAt; 400/404; publishes thread.updated.
DELETE /threads/{uuid} uuid 204 empty 404 Error; cascades messages.
GET /threads/{uuid}/messages uuid 200 Message[], oldest first Unknown thread returns 200 [].
POST /messages CreateMessage 200 Message 400; unknown thread 404 Error; updates thread time and publishes message.created.

See Workspaces and threads before building client-side selection, model, tool, approval, or deletion behavior.

Workspace files

All file operations use {uuid} plus a zero-based rootIndex from the workspace’s directories JSON. Relative paths cannot be absolute, contain empty/./.. segments, escape the root, or cross a symlink/junction/reparse point. Text is UTF-8 and limited to 1,000,000 bytes. Common failures are 400 invalid root/path/schema/type, 403 inaccessible or reparse path, 404 missing workspace/path, and 409 collision.

Method and path Parameters/request Success Errors and notes
GET /workspaces/{uuid}/files/search Query q default ""; limit integer default 20, clamped 1–50 200 FileSearchMatch[] Searches all roots, at most 25,000 visited files/root; invalid limit 400.
GET /workspaces/{uuid}/files Required query rootIndex; optional path (root when omitted) 200 FileEntry[] Directories first, then case-insensitive name.
GET /workspaces/{uuid}/files/content Required rootIndex and non-empty path 200 FileContent Allowlisted text extensions only; directory, unsupported type, non-UTF-8, or >1 MB is 400.
GET /workspaces/{uuid}/files/preview Required rootIndex, path Raw 200 image/PDF/DOCX bytes Validates signatures/archive safety; response headers include X-Preview-Kind; limits are 20/50/25 MiB.
POST /workspaces/{uuid}/files/content Query rootIndex,path; body FileContent 200 FileContent Create only; null/missing content 400, existing target 409.
PUT /workspaces/{uuid}/files/content Query rootIndex,path; body FileContent 200 FileContent Replaces existing text file; missing target 404.
POST /workspaces/{uuid}/files/directory Query rootIndex,path; body ignored 200 FileEntry Creates one directory; parent must exist; collision 409.
POST /workspaces/{uuid}/files/move MovePath 200 FileEntry Destination is an existing directory and basename is retained; cross-root/self/descendant move 400; collision 409.

There is no workspace-file delete endpoint. Search skips .git, .hg, .svn, .subconscious, .dart_tool, node_modules, build, dist, bin, obj, __pycache__, .venv, and venv.

Settings

Method and path Request Success Errors and notes
GET /settings Optional exact-match query filters key, tag, client 200 Setting[], database order Omitted filters are unrestricted; null scope and empty string are distinct.
PUT /settings Non-empty Setting[] 200 Setting[] Upserts exact (key,tag,client) scope; blank key, duplicate scope, or invalid array 400.

Models

Encrypted-store failures return 503 application/problem+json with ProblemDetails. Credentials are write-only and never appear in responses.

Method and path Request Success Errors and notes
GET /model-configurations None 200 ModelConfiguration[], sorted by ID 503 encrypted-store failure.
POST /model-configurations UpsertModelConfiguration 201 ModelConfiguration; Location header Blank provider/model or non-positive context window 400; 503.
PUT /model-configurations/{id} Complete UpsertModelConfiguration 200 ModelConfiguration Empty 404 if absent; omitted API key is preserved; metadata fields are replaced/cleared; 400/503.
DELETE /model-configurations/{id} id Empty 204 Empty 404 if absent; 503.
GET /models None 200 Model[] Configured catalog followed by the credential-free echo development model; 503.

Chat resolves a model by exact configuration ID, then by the first configuration whose model name matches. Duplicate model names are therefore ambiguous; clients should send IDs.

Tools

The configured registry stores metadata and encrypted API-key headers. Its records are not the same as client-registered WebSocket UI tools. In the currently audited chat path, HTTP configured-tool records are configuration metadata and are not directly executed by the built-in WebSocket tool registry.

Method and path Request Success Errors and notes
GET /tools/catalog None 200 ToolCatalog Built-in groups plus configured records; 503 store failure.
GET /tool-registry None 200 ToolConfiguration[] Sorted by alias/name; 503.
POST /tool-registry UpsertToolConfiguration 201 ToolConfiguration; Location header Alias or name required; type/auth/URL/header validation; 400/503.
GET /tool-registry/{uuid} uuid 200 ToolConfiguration Empty 404; 503.
PUT /tool-registry/{uuid} UpsertToolConfiguration 200 ToolConfiguration Empty 404; see field preservation in schemas; 400/503.
DELETE /tool-registry/{uuid} uuid Empty 204 Empty 404; encrypted auth is also removed; 503.

Retrieval (RAG)

Roots are validated when used and processed sequentially under per-root locks. A root is disabled when ragConfig.roots contains a matching {path,enabled:false} entry.

Method and path Request Success Errors and notes
POST /workspaces/{uuid}/rag/index Body ignored 200 RagWorkspaceIndex Indexes every enabled root; workspace 404, invalid roots 400, embedding failure 503.
POST /workspaces/{uuid}/rag/roots/{root_index}/index Integer path root_index; body ignored 200 RagRootIndex Malformed 400, missing root 404, disabled root 409, embedding failure 503.
POST /workspaces/{uuid}/rag/search RagSearch 200 RagResult[] Mode is case-sensitive keyword, vector, or hybrid; schema/root 400, workspace 404, embedding 503.

Search silently skips roots without a sidecar or with an incompatible embedding signature. Sensitive-path matches return metadata-only placeholder content.

Event stream

Method and path Request Success Notes
GET /stream None 200 text/event-stream Future events only; no heartbeat, IDs, or replay. See Realtime API.

The bidirectional WS /api/v1/events route is documented separately because it uses frames rather than HTTP request/response operations.