You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Base URL: http://localhost:8787. All endpoints are JSON unless noted.
Auth — every /api/* route requires authentication except the marked
public ones. Local mode: no credentials (single user local);
AUTH_SECRET mode: Authorization: Bearer <secret>; cloud mode: Supabase
JWT bearer. Write routes additionally require the server not to be in
read-only mode (403 otherwise).
Errors — every error is { "error": "message", ... } with a matching
HTTP status. Structured errors keep extra fields (e.g. quota errors carry
quota, used, plan with 429). Unconfigured optional AI features
(transcription, vision, TTS) return 501 with a message naming the env var.
Rate limits — unauthenticated endpoints are limited per IP
(PUBLIC_RATE_LIMIT, default 120 req/min → 429). Production defaults to
atomic Redis counters shared by all replicas (PUBLIC_RATE_LIMIT_STORE=redis);
single-process development defaults to memory. Store outages fail closed with
503, and limited responses include Retry-After plus RateLimit-* headers.
Spaces — every data route accepts an optional x-space-id header
selecting one of the caller's spaces (isolated sub-workspaces). Omitted or
default = the built-in default space. An unknown or foreign space id is a
404, a malformed one a 400. Settings and space management are per user
and ignore the header.
Upload / serve images (SVG served with a no-script CSP)
PATCH /api/settings
Per-user settings JSON
Shares
Method & path
Description
POST /api/shares
{ noteId } or { category }, plus optional expiresInDays / password → { id, url, kind } (128-bit id)
GET /api/shares · DELETE /api/shares/:id
List / revoke own shares; password hashes are never returned
GET /api/shares/:id/accesses
Owner-only recent successful access timestamps (no visitor identifiers)
GET /api/shares/:id/public(public)
Self-contained payload, or 401 { passwordRequired: true } for a protected link
POST /api/shares/:id/public(public)
Unlock a protected share with { password }; limited separately by SHARE_UNLOCK_RATE_LIMIT
Backup and restore
Method & path
Description
GET /api/export
Download knowledge-loom-export/v1: active-space Markdown sources plus account settings
POST /api/export/restore
Multipart .json backup with policy=skip|overwrite|rename, dryRun, and restoreSettings; validates all paths/content before writing and rebuilds once
Spaces
Method & path
Description
GET /api/spaces
{ spaces, limit } — the caller's spaces (default first); limit is the plan's max space count (null = unlimited)
POST /api/spaces
Create a space { name } → 403 when the plan limit is reached (MAX_SPACES env self-hosted, subscription plan hosted)
PATCH /api/spaces/:id
Rename (400 for the default space)
DELETE /api/spaces/:id
Delete the space and all data inside it (400 for the default space)
Marketplace
Method & path
Description
GET /api/marketplace?q=&kind=&sort=rating|imports(public)
Browse listings
GET /api/marketplace/:id(public)
Listing + full payload + comments
POST /api/marketplace/publish
{ shareId, title, description?, tags?, author? }
POST /api/marketplace/:id/import
Clone notes into your vault with decks seeded (no AI cost)
POST /api/marketplace/:id/rate
{ stars: 1–5, comment? } — one per user, no self-rating
GET /api/marketplace/mine · DELETE /api/marketplace/:id
Own listings / unpublish
Extension endpoints (when extensions/ is present)
Optional private extension modules add further endpoint groups (e.g. billing
and admin). They are not part of the open-source build; see the private repo.