The server listens on FXBOT_HOST, default 127.0.0.1, at FXBOT_PORT, default 8787. See Configuration.
Every answer has the header x-fxbot-version, the running version.
A write, any method but GET and HEAD, whose Origin header names another host than the request's Host header gets 403, { "error": "This request came from another site." }. A request with no Origin header, such as one from curl or Node's fetch, passes. The server sends no CORS headers.
A route that reads a body takes a JSON object. Anything else gets 400, "body must be a JSON object". A body is at most 1 MiB, and a message's at most 12 MiB. A larger one gets 413.
An error comes back as JSON, { "error": "<message>" }, with the SDK's status, or 500 for an unexpected one, which the server logs. An error after an answer has started, as in a stream, closes the connection.
A path or method the server doesn't serve gets 404, not found, or 405, method not allowed.
A bot id is 12 hex characters. Most routes under /api/profiles/<id> get 400 for another shape, and 404 for an unknown bot.
202 and UpdateStatus. Asks the machine to update to the newest release the check found.
UpdateStatus is { version, latest, canUpdate, updating }. canUpdate is true only in an install made by setup.sh, where FXBOT_CONTROL is set. updating is { to, steps, error? } while an update runs, or after one failed, else null. POST gets 400 outside such an install, and when the running version is the newest, and 409 while an update runs.
Any of defaultProvider, embedder, embeddingProvider, embeddingModel, messageVectors, and local
Settings
GET
/api/settings/embedding
EmbeddingStatus
local is cpu, gpu, or off. It asks the machine to run its local embedder that way. Outside an install made by setup.sh, it gets 400.
EmbeddingStatus adds what the machine runs to the SDK's status. local is the machine's embedder, or null outside an install made by setup.sh. switching is a change it hasn't finished, or why one failed. canSwitch is whether local can be asked for. When the machine runs no embedder while Settings asks for local, error says so.
Message: text, messageId, and optional files, each { name, type, data } with data in base64. At most 12 MiB.
{ messageId, sessionId }, once the message is stored
GET
/api/profiles/<id>/stream
cursor, default 0
NDJSON lines, from the cursor on, then each new one
The stream:
answers 200 with content-type: application/x-ndjson and cache-control: no-store, and the x-fxbot-version header
replays the chat's lines from cursor, then stays open for new ones. 0 replays the whole chat. Each line's cursor is where to ask again to get the lines after it.
ends at once for a bot with no chat yet, or whose provider is gone
GET /callback finishes an MCP sign-in, as above. Every other path serves the page from packages/ui/dist/: the file at that path, or index.html, so the app's routes load. Without a build, it gets 404, { "error": "no build in packages/ui/dist/; run npm run build" }.