Files
FabledGrimoire/docs/api-reference.md
T
bvandeusenandClaude Opus 5.5 0f5ef0be63
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
rename(547): the server is grimoire — package, image, DB defaults, backups
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>
2026-10-22 10:50:45 -04:00

302 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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).