dox docs

HTTP API

Everything is served from one origin. system owns the root path; each app's router is mounted under /app/<id>/. Routes inside an app are written without that prefix.

Prefix Owner
/ system — container, event/, assets/, app registry, scenes
/app/explorer/ explorer
/app/editor/ editor
/app/agent/ agent

There is no authentication. The server binds 127.0.0.1; see Deploy for reaching it safely.

Streaming

POST /app/agent/api/chat and POST /app/agent/api/run send text/event-stream whose body is newline-delimited JSON — one object per line, not SSE data: frames:

{"type":"session","path":"…/20261021-110716-yggu.sss"}
{"type":"thinking_delta","text":"…"}
{"type":"text_delta","text":"Let me look"}
{"type":"tool_use","name":"bash","input":{"command":"ls"}}
{"type":"tool_result","name":"bash","content":"…","isError":false}
{"type":"usage","input":1234,"output":56}
{"type":"done"}
Type Meaning
session Path of the session file being written (first line of a new conversation)
text_delta / thinking_delta Incremental model output
tool_use The model called a tool
tool_result That tool returned
search_result Web search results
usage Token counts
retry The upstream call failed and is being retried
error Request-level failure
done Turn finished
out / exit Shell output and exit code — only from /api/run

Closing the connection aborts the turn, including a bash call in progress.

system

Method Path Body / query Returns
GET /api/health — { "ok": true, "app": "dox" }
GET /api/app — Registered apps, minus hidden: { id, name, entry, renders? }
GET /api/stats — { rss, heapUsed, heapTotal, external } for the server process
POST /api/scene/save { path, windows } Writes a .dox scene
GET /api/scene/load ?path= The saved scene

/api/health exists so the launcher can tell dox apart from whatever else holds port 3000.

agent — /app/agent

Method Path Body / query Returns
GET /api/config — { baseUrl, apiKey, model, workspace, defaultModel? }
PUT /api/config partial config Merged config
GET /api/models — { models: [{ id, label, baseUrl, apiKey, model, reasoningEffort?, tools? }] }, read from dox-data/agent/models/*.env
PUT /api/models { models } Syncs the directory: writes each model to <id>.env, deletes files no longer listed; at least one required
GET /api/sessions — { sessions: [{ path, title, updatedAt, count }] }
GET /api/session ?path= { path, title, messages, updatedAt, model? }
PUT /api/session { path, title?, messages?, model? } { ok: true } — model is a model id; send an empty string to clear it
DELETE /api/session ?path= { ok: true }
GET /api/session-meta ?path= { title, count, created, updated } — what the explorer row shows
POST /api/chat { sessionPath, text, images?, model? } Stream (above). Empty sessionPath creates a new .sss and reports it in the session event. model is a model id: it overrides the session's pinned value and is written into the session
POST /api/run { command } Stream of out / exit — runs a shell command without the model

images is an array of { data, media_type } with base64 data, passed to the model as image blocks.

curl -sN -X POST http://127.0.0.1:3000/app/agent/api/chat \
  -H 'content-type: application/json' \
  -d '{"sessionPath":"","text":"what is in this folder?"}'

explorer — /app/explorer

Method Path Body / query Returns
GET /api/root — { root } — default browse root
GET /api/list ?path= { entries: [{ name, isDir, size? }] }, directories first
GET /api/stat ?path= { exists, isDir }
GET /api/file ?path= Raw bytes, capped at 50 MB — used for thumbnails
POST /api/mkdir { path } Creates a directory
POST /api/mkfile { path } Creates an empty file
POST /api/rename { path, newName } Renames in place
DELETE /api/delete ?path= Deletes a file or a tree
POST /api/copy { src, destDir } Copies
POST /api/move { src, destDir } Moves

editor — /app/editor

Method Path Body / query Returns
GET /api/stat ?path= { exists, size? }
GET /api/read ?path= { path, content }
POST /api/write { path, content } Writes and returns the new stat

Notes

  • Paths are normalised server-side; a relative path is resolved against the process's working directory. Pass absolute paths when in doubt.
  • Every error response is { "error": "…" } with a 4xx/5xx status. A thrown handler returns 500 {"error":"internal error"} and does not affect other requests.
  • GET / serves the container (icanvas/index.html).