Skip to content

REST API

Every route takes Authorization: Bearer <key> and JSON, except GET /health, which is open. Bad input answers 400, an unknown session or workspace 404. A daemon also checks the Host header against its allowed hosts.

Route What it does
GET /api/sessions List sessions
POST /api/sessions Create a session
DELETE /api/sessions/{id} Delete a session
GET /api/workspaces List workspaces (?include_archived=true for archived ones too)
POST /api/workspaces Create a workspace
DELETE /api/workspaces/{id} Delete a workspace
POST /api/workspaces/{workspace_id}/sessions/{session_id} Attach a session to a workspace, with a role
POST /api/projects/resolve Find or create the workspace and session of a project

POST /api/projects/resolve takes a project key (the git remote without scheme, user and .git, such as github.com/acme/checkout), a name and the client. The same key always gets the same workspace and session, so teammates on the same remote share them.

Terminal window
curl -X POST <url>/api/projects/resolve -H "Content-Type: application/json" \
-d '{"key": "github.com/acme/checkout", "name": "checkout", "client": "my-agent"}'
# {"workspace_id": "...", "session_id": "...", "created": true}

POST /api/search runs the same search as the semantic_search tool.

Field
query what to find, in words
scope session or workspace (both with id), or global
mode fast, local or accurate; optional
sources records (default), messages or all
limit default 5, at most 50
author only this author’s records; optional
Terminal window
curl -X POST <url>/api/search -H "Content-Type: application/json" \
-d '{"query": "why did we pick RocksDB?", "scope": "workspace", "id": "<uuid>", "mode": "fast"}'

It answers the hits only, without the neighbouring records MCP adds around them. A host without embeddings answers 503.

POST /api/messages appends turns to a session. It is idempotent on turn_id, so a retry is safe, and redaction applies.

Terminal window
curl -X POST <url>/api/messages -H "Content-Type: application/json" -d '{
"session_id": "<uuid>",
"messages": [
{"turn_id": "t-1", "role": "user", "text": "why is the build slow?"},
{"turn_id": "t-2", "role": "assistant", "text": "...", "author": "my-agent", "tools": ["Bash"]}
]}'
# {"appended": [0, 1], "skipped": 0, "vectorized": 2}
Route What it does
GET /api/cards?workspace_id=<id> The user card and the workspace’s project card
PUT /api/cards/user Write the user card
PUT /api/cards/workspace/{id} Write a project card
GET /api/file?workspace_id=<id>&path=<path> What the memory knows about a source file

A card write names the version it was edited from (expected_version). It answers 200 with the new version, or 409 with the latest one if someone changed it meanwhile.

POST /api/events takes a client’s hook event and answers what the host’s modules say, as a Claude Code hook answer to print. This is what the plugin’s hooks call.