# API Reference All endpoints are JSON over HTTP under `/api`, and require login unless marked **(public)**. Browser sessions authenticate with a cookie; programmatic clients use an `fmcp_` API key as `Authorization: Bearer ` (see [API Keys & MCP](api-keys-and-mcp.md)). Claude reaches the same data through the MCP endpoint at `/mcp`, not these REST routes. ## Health | Method | Path | Description | |--------|------|-------------| | GET | `/api/health` | Health check **(public)** | | GET | `/api/version` | App version **(public)** | ## Auth | Method | Path | Description | |--------|------|-------------| | GET | `/api/auth/status` | `{has_users, registration_open, oauth_enabled, local_auth_enabled}` **(public)** | | POST | `/api/auth/register` | Register (first user becomes admin) | | POST | `/api/auth/login` | Login with username/password | | POST | `/api/auth/logout` | Clear session | | GET | `/api/auth/me` | Current user info | | PUT | `/api/auth/password` | Change password | | PUT | `/api/auth/email` | Change email | | POST | `/api/auth/invalidate-sessions` | Evict all other sessions | | POST | `/api/auth/forgot-password` | Send password-reset email | | POST | `/api/auth/reset-password` | Reset password with token | | GET | `/api/auth/oauth/login` | Begin OIDC (PKCE) flow | | GET | `/api/auth/oauth/callback` | OIDC callback | | GET | `/api/auth/invitation/:token` | Validate an invite **(public)** | | POST | `/api/auth/register-with-invite` | Register with a token **(public)** | ## Notes | Method | Path | Description | |--------|------|-------------| | GET | `/api/notes` | List notes (params: `q`, `tag`, `sort`, `order`, `limit`, `offset`, `project_id`, `milestone_id`, `parent_id`) | | POST | `/api/notes` | Create note | | GET | `/api/notes/tags` | All tags (param: `q`) | | POST | `/api/notes/:id/append-tag` | Add a tag `{tag}` | | POST | `/api/notes/link-suggestions` | Detect note titles as plain text → wikilink candidates | | GET | `/api/notes/by-title` | Resolve note by exact title | | POST | `/api/notes/resolve-title` | Get-or-create by title (wikilink click) | | GET / PUT / PATCH / DELETE | `/api/notes/:id` | Read / replace / patch / delete | | POST | `/api/notes/:id/convert-to-task` | Note → task | | POST | `/api/notes/:id/convert-to-note` | Task → note | | GET | `/api/notes/:id/backlinks` | Notes/tasks with `[[Title]]` references to this note | | GET | `/api/notes/:id/versions` | Version history | | GET | `/api/notes/:id/versions/:vid` | A specific version | | POST | `/api/notes/:id/versions/:vid/pin` | Pin a version | | GET / PUT / DELETE | `/api/notes/:id/draft` | Unsaved-edit draft (restore across page loads) | | GET | `/api/notes/graph` | Knowledge-graph nodes/edges | | GET | `/api/notes/duplicates` | Near-duplicate notes or tasks, grouped | | GET | `/api/notes/due-for-verification` | Notes that carry a check, oldest verification first | | POST | `/api/notes/:id/verify` | Record that a note's check was run `{still_true}` | ## Tasks | Method | Path | Description | |--------|------|-------------| | GET | `/api/tasks` | List tasks (params: `q`, `tag`, `status`, `priority`, `overdue`, `sort`, `order`, `limit`, `offset`) | | POST | `/api/tasks` | Create task (accepts a `project` name string → resolved to `project_id`) | | POST | `/api/tasks/planning` | Start a plan (milestone + steps) | | GET / PUT / PATCH / DELETE | `/api/tasks/:id` | Read / update / delete | | PATCH | `/api/tasks/:id/status` | Quick status update `{status}` | | GET | `/api/tasks/:id/recurrence-preview` | Preview next recurrence occurrences | **Task work logs** | Method | Path | Description | |--------|------|-------------| | GET / POST | `/api/tasks/:id/logs` | List / append a work log `{content, duration_minutes?}` | | PATCH / DELETE | `/api/tasks/:id/logs/:log_id` | Update / delete a log | ## Projects, Milestones, Systems, Issues | Method | Path | Description | |--------|------|-------------| | GET / POST | `/api/projects` | List (owned + shared) / create | | GET / PATCH / DELETE | `/api/projects/:id` | Read (with `milestone_summary`, `inception`) / update / delete | | POST | `/api/projects/:id/inception` | Record what the project inherits `{choices: {design_system_id, seed_systems}}` (owner-only; `POST /api/projects` accepts the same under `inception`) | | GET | `/api/projects/:id/inception/defaults` | What binds if nobody decides — the inception card's payload | | GET | `/api/projects/:id/notes` | Notes + tasks in this project | | GET / POST | `/api/projects/:id/milestones` | List / create milestones | | GET / PATCH / DELETE | `/api/projects/:id/milestones/:mid` | Read / update / delete | | GET | `/api/projects/:id/milestones/:mid/tasks` | Tasks in a milestone | | GET / POST | `/api/projects/:id/systems` | List / create systems | | GET / PATCH / DELETE | `/api/projects/:id/systems/:sid` | Read / update / delete | | GET | `/api/projects/:id/systems/:sid/records` | Records linked to a system | | PUT | `/api/systems/:sid/canonical` | Map a system to a shared area `{canonical_id}` (`null` unmaps) | | GET / POST | `/api/canonical-systems` | List / create shared areas | | PATCH | `/api/canonical-systems/:id` | Update a shared area | | GET | `/api/projects/:id/issues` | Project issues | | PUT | `/api/projects/:id/design-system` | Point the project at a design system `{design_system_id}` (`null` clears) | | GET / PUT | `/api/projects/:id/platforms` | The project's platforms `{platforms: {slug: "declared" \| "rejected" \| null}}` | | PUT | `/api/projects/:id/forge` | Pin the project to one forge connection, or clear it | | GET / POST | `/api/platforms` | Platform catalogue / add a platform | | PATCH | `/api/platforms/:id` | Update a platform | ## Snippets and lessons | Method | Path | Description | |--------|------|-------------| | GET / POST | `/api/snippets` | List / create snippets | | GET / PATCH / DELETE | `/api/snippets/:id` | Read / update / delete | | POST | `/api/snippets/:id/verify` | Record a drift-check verdict `{status, detail, path}` | | GET | `/api/snippets/duplicates` | Near-duplicate snippets, grouped into merge candidates | | POST | `/api/snippets/:id/merge` | Merge source snippets into this one | | POST | `/api/snippets/:id/unmerge` | Pull one source back out `{source_id}` | | GET / POST | `/api/lessons` | List / create lessons | | GET / PATCH / DELETE | `/api/lessons/:id` | Read / update / delete (to the trash) | | GET | `/api/lessons/rule-candidates` | Rules a draft lesson resembles, before it is saved | | GET | `/api/lessons/taught-by/:record_id` | Lessons drawn from one record | | PUT | `/api/lessons/:id/rules/:rule_id` | Confirm or reject a lesson → rule link | ## Design systems | Method | Path | Description | |--------|------|-------------| | GET / POST | `/api/design-systems` | List / create | | GET | `/api/design-systems/starter-roles` | Starter token roles for the creation form | | GET / PATCH / DELETE | `/api/design-systems/:id` | Read / update / delete | | GET | `/api/design-systems/:id/resolved` | The effective token set, inheritance applied | | GET | `/api/design-systems/:id/stylesheet` | The generated stylesheet | | GET | `/api/design-systems/:id/snippet-check` | Snippets that disagree with the system's sheet | | GET / POST | `/api/design-systems/:id/tokens` | This system's own tokens / add one | | PATCH / DELETE | `/api/design-tokens/:id` | Update / delete a token | ## Family canon | Method | Path | Description | |--------|------|-------------| | GET | `/api/family/ideas` | Family ideas | | GET | `/api/family/ideas/:id` | One idea with its references | | POST | `/api/family/ideas/:id/propose` · `/promote` · `/retire` | Move an idea through its lifecycle | | GET | `/api/family/matrix` | Projects × canon ideas, with each project's answer | | GET | `/api/family/decisions` | Promotion and retirement decisions | | POST | `/api/family/decisions/:id/undo` | Undo a decision | ## Knowledge browse | Method | Path | Description | |--------|------|-------------| | GET | `/api/knowledge` | Unified note/task/plan/process feed (params: `type`, `tags`, `sort`, `q`, `limit`, `offset`) | | GET | `/api/knowledge/ids` | ID-only page (two-tier pagination) | | GET | `/api/knowledge/batch` | Fetch items by id | | GET | `/api/knowledge/tags` | Tags in scope | | GET | `/api/knowledge/counts` | Per-type counts | ## Search | Method | Path | Description | |--------|------|-------------| | GET | `/api/search` | Semantic + keyword search over notes/tasks (params: `q`, `type`, `limit`) | ## Rulebooks and rules | Method | Path | Description | |--------|------|-------------| | GET / POST | `/api/rulebooks` | List / create rulebooks | | GET / PATCH / DELETE | `/api/rulebooks/:id` | Read / update / delete | | GET / POST | `/api/rulebooks/:id/topics` | List / create topics | | PATCH / DELETE | `/api/rulebook-topics/:tid` | Edit / delete a topic | | GET | `/api/rules` | List rules | | POST | `/api/rulebook-topics/:tid/rules` | Add a rule to a topic | | GET / PATCH / DELETE | `/api/rules/:id` | Read / update / delete a rule | | POST | `/api/rules/:id/move` | Move a rule: `{topic_id}` makes it global, `{project_id}` makes it that project's | | GET | `/api/projects/:id/rules` | A project's own rules, and the global rules tagged to its areas | | POST | `/api/projects/:id/rules` | Create a project-scoped rule | | GET | `/api/rules/:id/versions` | A rule's edit history, newest first | | GET | `/api/rules/:id/versions/:vid` | One earlier version in full | | POST | `/api/rules/:id/versions/:vid/restore` | Put a preference back to an earlier version (preferences only) | | GET | `/api/rules/drift` | Preferences that have been rewritten, most recent first | | POST | `/api/rules/:id/relations` | Relate this rule to another (`co_surfaces`, `overrides`, `elaborates`) | | DELETE | `/api/rule-relations/:id` | Remove a relation | | GET | `/api/rules-due-for-verification` | Rules that carry a check, oldest verification first | | POST | `/api/rules/:id/verify` | Record that a rule's check was run `{still_true}` | ## Retrieval | Method | Path | Description | |--------|------|-------------| | GET | `/api/retrieval/surfaces` | Every tunable surface with its threshold and budget | | PUT | `/api/retrieval/surfaces/:surface` | Change one surface's setting, recorded with its reason | | GET | `/api/retrieval/tuning-history` | Changes to retrieval on this install, newest first | | GET | `/api/retrieval/moments` | The moments of work rules mount on, and the actions that reach each | | POST / DELETE | `/api/retrieval/moments/mappings` | Map / unmap an action to a moment | | GET | `/api/retrieval/moments/proposals` | Proposed rule → moment mounts awaiting a judgment | | POST | `/api/retrieval/moments/proposals/judge` | Confirm or reject proposals | | GET | `/api/retrieval/reply-shapes` | The default reply shapes and the moment each arrives at | ## Sharing | Method | Path | Description | |--------|------|-------------| | GET / POST | `/api/projects/:id/shares` | List / add project shares `{user_id?, group_id?, permission}` | | PATCH / DELETE | `/api/projects/:id/shares/:sid` | Update permission / remove | | GET / POST | `/api/notes/:id/shares` | List / add note shares | | PATCH / DELETE | `/api/notes/:id/shares/:sid` | Update permission / remove | | GET | `/api/shared-with-me` | All resources shared with the current user | ## Groups | Method | Path | Description | |--------|------|-------------| | GET / POST | `/api/groups` | List / create groups | | GET / PATCH / DELETE | `/api/groups/:id` | Read / update / delete | | GET / POST | `/api/groups/:id/members` | List / add members `{user_id, role}` | | PATCH / DELETE | `/api/groups/:id/members/:uid` | Update role / remove | ## Notifications | Method | Path | Description | |--------|------|-------------| | GET | `/api/notifications` | List in-app notifications | | GET | `/api/notifications/count` | Unread count | | POST | `/api/notifications/:id/read` | Mark one read | | POST | `/api/notifications/read-all` | Mark all read | ## Profile and Settings | Method | Path | Description | |--------|------|-------------| | GET / PUT | `/api/profile` | Read / update the per-user profile | | GET / PUT | `/api/settings` | Read / update key-value settings | | GET | `/api/settings/search` | SearXNG configuration status | | GET / POST | `/api/settings/forge-connections` | Your git forge connections / add one | | PUT / DELETE | `/api/settings/forge-connections/:id` | Update / remove a connection | | POST | `/api/settings/forge-connections/:id/test` | Check that the forge is reachable and accepts the token | ## API keys | Method | Path | Description | |--------|------|-------------| | GET / POST | `/api/api-keys` | List / create `fmcp_` keys (key shown once) | | DELETE | `/api/api-keys/:id` | Revoke a key | ## Plugin (Claude Code) These serve the plugin's hooks. | Method | Path | Description | |--------|------|-------------| | GET | `/api/plugin/context` | Session-start context: the active project and its state | | GET | `/api/plugin/retrieve` | Records and rules matching the operator's prompt | | GET | `/api/plugin/tool-rules` | Rules matching a tool call about to run | | GET | `/api/plugin/moment-tools` | The tools whose calls can reach a moment | | POST | `/api/plugin/moment` | The rules mounted on the moments a tool call reaches | | POST | `/api/plugin/reply-rules` | Whether the reply ending a turn is held for one read | | POST | `/api/plugin/rule-opened` | Records that a session opened a rule it was shown | | GET | `/api/plugin/shape-check` | The end-of-turn question about what this turn wrote | | GET | `/api/plugin/claim-session` · `/release-session` | Bind a session to its task claims / release them at session end | | GET | `/api/plugin/processes` | Stored Processes for skill-stub sync | | GET | `/api/plugin/prior-art` | Write-path hint for the plugin hooks (params: `path`, `code`, `repo`, `shapes`, `exclude_ids`, `exclude_sync_ids`, `exclude_derive`); returns `context`, `note_ids`, `sync_note_ids`, `stamped`, `divergence`, `derive`, `derive_keys` | | GET / POST | `/api/projects//coverage`, `…/coverage/refresh` | Shape-ledger accounting (`pattern_coverage` line, counts, `derive_groups` — css groups carry `consumers`, `derive_new`, `unused_css`, `divergence`, `recheck`) | | GET / PUT | `/api/plugin/marketplace-url` | Read / set the plugin marketplace URL | ## Dashboard, Export, Trash, Users | Method | Path | Description | |--------|------|-------------| | GET | `/api/dashboard` | Home dashboard payload | | GET | `/api/export` | Personal export (`format=markdown` ZIP or `format=json`) | | GET | `/api/trash` | List trashed items, grouped by delete batch | | POST | `/api/trash/:batch/restore` | Restore a batch | | DELETE | `/api/trash/:batch` | Purge a batch (irreversible) | | GET | `/api/users/search` | Search users by prefix (for sharing) | ## Admin | Method | Path | Description | |--------|------|-------------| | GET | `/api/admin/backup` | Export backup (format v4; `?scope=user` for own data) | | POST | `/api/admin/restore` | Restore from a backup | | GET / DELETE | `/api/admin/users` · `/api/admin/users/:id` | List / delete users | | GET / PUT | `/api/admin/registration` | Get / toggle registration | | GET / PUT | `/api/admin/smtp` · POST `/api/admin/smtp/test` | SMTP config + test email | | GET | `/api/admin/logs` · `/api/admin/logs/stats` | Log entries + category counts | | GET / PUT | `/api/admin/base-url` | Get / set the public base URL | | GET / PUT | `/api/admin/db-maintenance` (+ `/health`, POST `/run`) | VACUUM schedule, health, manual run | | POST / GET / DELETE | `/api/admin/invitations` (+ `/:id`) | Create / list / revoke invite links | | GET / PUT | `/api/admin/backups` | Scheduled backups: destination, schedule and recent runs | | POST | `/api/admin/backups/check` | Ask the destination whether it would accept a backup | | POST | `/api/admin/backups/run` | Start a backup now | | GET / PUT | `/api/admin/forge-webhook` | The forge push-webhook settings | ## Webhooks | Method | Path | Description | |--------|------|-------------| | POST | `/api/webhooks/forge` | Push events from a git forge, verified with `FORGE_WEBHOOK_SECRET` **(public)** | ## Scribe MCP Claude clients connect to the built-in MCP server at `POST /mcp` (streamable HTTP, Bearer auth with an `fmcp_` key), served by `src/scribe/mcp/`. It is not a REST surface — it exposes the same data as typed tools (`create_note`, `create_task`, `start_planning`, `search`, `enter_project`, …) with server-level usage guidance delivered in the MCP `instructions` block. See [API Keys & MCP](api-keys-and-mcp.md).