Bookmark Context
Type to search documentation.

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

MethodPathBodySuccessErrors
GET/status200 {status, version} — no auth
GET/stats200 process + disk stats (see below)401
GET/collections200 CollectionResponse[]401
POST/collections{name, description?}201 CollectionResponse401, 422
PATCH/collections/{id}{name, description?}200 CollectionResponse404
DELETE/collections/{id}204 — also drops the Chroma collection404
GET/bookmarks?url=200 BookmarkResponse[] across all collections401
GET/collections/{id}/bookmarks200 BookmarkResponse[]401
POST/collections/{id}/bookmarks{url, title?, html?, favicon_url?}201 BookmarkResponse, then indexes in the background — or 200 ScanWarning, see below404, 422
DELETE/bookmarks/{id}204 — also removes the bookmark’s vector chunks404
POST/bookmarks/{id}/reindex200 BookmarkResponse — no-op if already indexing404

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:

json
{
"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:

json
{
"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

Last updated Sep 9, 2026