CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 12s
CI & Build / TypeScript typecheck (push) Successful in 56s
CI & Build / integration (push) Successful in 1m4s
CI & Build / Python tests (push) Successful in 1m55s
CI & Build / Build & push image (push) Successful in 44s
Step 2 of the Scribe -> Grimoire rename. - src/scribe -> src/grimoire, and every import, patch target, module path, hypercorn entry point and `python -m grimoire.restore` with it; pyproject, uv.lock and the frontend package are named grimoire. - Image git.fabledsword.com/bvandeusen/fabledgrimoire; CI's Postgres service runs as grimoire / grimoire_test. - Compose files default the DB user, database and (prod) volume to grimoire, each overridable from .env, so an install created as Scribe keeps its data by setting POSTGRES_USER, POSTGRES_DB and PGDATA_VOLUME. - Backups are written as grimoire-<ts>.tar with format grimoire-backup-tar. Archives named scribe-* with the scribe-backup-tar manifest still restore and are still counted at the destination (folder and S3), with tests. - Exports, the MCP auth realm, the ASGI scope key and the persistent logger carry the new name. Kept on purpose: the secret-sealing key label stays "scribe.secrets.v1", because every stored secret was derived under it. Plugin identity (plugin name, hooks, env vars, .scribe marker, skills) is step 3. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
302 lines
16 KiB
Markdown
302 lines
16 KiB
Markdown
# 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 <key>` (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 |
|
||
|
||
## Settings
|
||
|
||
| Method | Path | Description |
|
||
|--------|------|-------------|
|
||
| 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/<id>/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)** |
|
||
|
||
## Grimoire MCP
|
||
|
||
Claude clients connect to the built-in MCP server at `POST /mcp` (streamable HTTP,
|
||
Bearer auth with an `fmcp_` key), served by `src/grimoire/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).
|