REST API
The daemon's HTTP endpoints.
Base URL http://localhost:7331 (bound to 127.0.0.1 only).
Authentication
Every route except /status requires Authorization: Bearer <token> whenever a
token is configured — which is always, when the daemon is started with
bookmark-context serve. A missing or wrong token returns
401 {"detail": "Unauthorized"}.
Requests with a body larger than 10 MB return 413. CORS is open
(Access-Control-Allow-Origin: *); the token, not CORS, is what protects the
daemon.
Endpoints
| Method | Path | Body | Success | Errors |
|---|---|---|---|---|
| GET | /status | — | 200 {status, version} — no auth | — |
| GET | /stats | — | 200 process + disk stats (see below) | 401 |
| GET | /collections | — | 200 CollectionResponse[] | 401 |
| POST | /collections | {name, description?} | 201 CollectionResponse | 401, 422 |
| PATCH | /collections/{id} | {name, description?} | 200 CollectionResponse | 404 |
| DELETE | /collections/{id} | — | 204 — also drops the Chroma collection | 404 |
| GET | /bookmarks?url= | — | 200 BookmarkResponse[] across all collections | 401 |
| GET | /collections/{id}/bookmarks | — | 200 BookmarkResponse[] | 401 |
| POST | /collections/{id}/bookmarks | {url, title?, html?, favicon_url?} | 201 BookmarkResponse, then indexes in the background — or 200 ScanWarning, see below | 404, 422 |
| DELETE | /bookmarks/{id} | — | 204 — also removes the bookmark’s vector chunks | 404 |
| POST | /bookmarks/{id}/reindex | — | 200 BookmarkResponse — no-op if already indexing | 404 |
Saving a bookmark
POST /collections/{id}/bookmarks takes an optional ?force= query parameter.
With force=false (default) the daemon fetches the page and runs the
prompt-injection scan before creating the bookmark. If the page looks like an
unrendered JavaScript shell, or any chunk trips the scanner, it returns
200 ScanWarning and does not create the bookmark:
{ "status": "scan_warning", "risk_score": 0.85, "signals": ["direct_override"], "matches": ["...ignore all previous instructions and..."]}With force=true the fetch-and-scan gate is skipped and the bookmark is created
immediately.
The url is validated: it must use http/https, have a host, and not resolve
to a private or internal address (loopback is allowed, so bookmarking your own
dev server works). A bad URL returns 422.
GET /stats
Authenticated. Returns:
{ "cpu_percent": 0.0, "memory_bytes": 734003200, "memory_processes": [ { "client": "cursor", "started_at": "...", "ppid": 1234, "parent_name": "Cursor", "uptime_seconds": 812 } ], "disk_bytes": 10485760, "git": { "branch": "master" }, "trace_summary": { "enabled": true, "log_dir": "...", "process_log_bytes": 0, "tool_log_bytes": 0 }}memory_processes lists every project process, including one entry per MCP
server. git is null unless the daemon runs from a source checkout.
trace_summary is absent when tracing is off. These figures are kept off the
unauthenticated /status so no page you visit can fingerprint the install.
Schemas
CollectionResponse
id, name, description, created_at, updated_at,bookmark_count, favicon_previews: [{ url, favicon_url }]BookmarkResponse
id, collection_id, url, title, favicon_url,added_at, indexed_at | null, index_status, error_message?index_status: pending → indexing → done | error