API Reference Version: 0.1.0
Interactive docs With the server running, the API is self-documented via OpenAPI:
URL Description http://localhost:9481/api/docsSwagger UI: interactive, try-it-out docs http://localhost:9481/api/redocReDoc: clean, readable reference http://localhost:9481/api/openapi.jsonRaw OpenAPI schema
Authentication All endpoints except /api/auth/status, /api/auth/setup, /api/auth/login, and /api/auth/config require a JWT.
Header (preferred):
Authorization: Bearer <token> Query parameter (required for browser-embedded images and file downloads):
Tokens are returned by /api/auth/login and expire after 30 days .
Roles Role Permissions adminFull access including user management and app settings gmRead + edit metadata, rescan library, manage campaigns playerRead-only access
Auth Endpoint Method Auth Description /api/auth/statusGET None Returns {"initialized": bool} /api/auth/configGET None Public auth config for the login screen /api/auth/setupPOST None First-run admin account creation. Body: {username, password} /api/auth/loginPOST None Authenticate. Body: {username, password}. Returns {token, user} /api/auth/meGET any Current user details /api/auth/openid/loginGET None Start OIDC login, redirects to IdP /api/auth/openid/callbackGET None OIDC callback /api/auth/openid/discoverPOST admin Server-side discovery fetch. Body: {issuer_url}
Users Endpoint Method Auth Description /api/usersGET admin List all users /api/usersPOST admin Create a user. Body: {username, password, role?, email?} /api/users/:idPATCH admin Update role, password, allow_explicit, or email /api/users/:idDELETE admin Delete a user /api/users/me/preferencesPATCH any Update own display_name, allow_explicit, or email /api/users/me/passwordPATCH any Change own password. Body: {current_password, new_password} /api/users/meDELETE any Delete own account
Library Endpoint Method Auth Description /api/statsGET JWT or X-API-Key Counts, page totals, library size, version /api/scan-statusGET admin Current scan state /api/rescanPOST admin Trigger a background rescan and reindex /api/cancel-scanPOST admin Gracefully stop the running scan
Stats response:
json {
"game_systems" : 12 ,
"books" : 340 ,
"maps" : 1500 ,
"tokens" : 800 ,
"audio" : 250 ,
"indexed_books" : 320 ,
"total_pages" : 45000 ,
"total_size_mb" : 18240.5
} /api/stats is the only endpoint that accepts the X-API-Key header, so it's the safe way to surface library counts on an external dashboard. Generate a key as an admin under Settings → App Settings → Stats API Key (regenerate or revoke it there at any time). See the Homepage Widget guide for a full walkthrough.
Homepage Custom API widget : add this to your Homepage services.yaml (Custom API widget docs ):
yaml - Grimoire :
href : https://grimoire.example.com
icon : grimoire.png
widget :
type : customapi
url : https://grimoire.example.com/api/stats
refreshInterval : 60000
headers :
X-API-Key : your-key-here
mappings :
- field : books
label : Books
format : number
- field : maps
label : Maps
format : number
- field : tokens
label : Tokens
format : number
- field : total_size_mb
label : Size
format : float
scale : 0.001
suffix : " GB" Homepage shows up to four fields per row; pick the counts you care about from the fields below. Use a refreshInterval of 60s or higher, /api/stats is rate limited.
Field Meaning Suggested format game_systemsNumber of game systems (top-level library folders) numberbooksTotal books (PDFs) numbermapsTotal maps numbertokensTotal tokens numberaudioTotal audio tracks numberindexed_booksBooks with a searchable full-text index numbertotal_pagesSum of all book page counts numbertotal_size_mbTotal library size in MB float, add scale: 0.001 + suffix: " GB" to show GB
Game Systems Endpoint Method Auth Description /api/systemsGET any List all systems with book counts /api/systems/:idGET any System detail + full book list /api/systems/:idPATCH gm/admin Update metadata
PATCH fields: name, slug, description, publishers, character_builder_url, cover_image, cover_book_id, tags, genre, is_explicit
Books Endpoint Method Auth Description /api/booksGET any Paginated book list. Query: system_id, category, limit (max 500), offset /api/books/:idGET any Book detail /api/books/:idPATCH gm/admin Update book metadata /api/books/:id/reindexPOST gm/admin Re-run OCR on a scanned book. Optional query ocr_dpi (72–600) re-reads it at a higher resolution than the global OCR_DPI. Clears the search index and re-queues the book (OCR runs in the background). 400 for books with an embedded text layer. /api/books/:id/rescanPOST gm/admin Re-read a single book from disk and rebuild its search index, for a file edited externally. Works for any PDF: a text-layer book is re-extracted; an image-only book is re-queued for OCR. Refreshes page count and thumbnail. Runs in the background; no-ops if a library scan is already running. 400 for non-PDFs. /api/books/:id/fileGET any Download/stream the file /api/books/:id/thumbnailGET any WebP cover thumbnail /api/books/:id/tocGET any PDF table of contents /api/books/:id/page/:numGET any Render PDF page as WebP. Query: width (default 1200, max 3000) /api/books/:id/page/:num/textGET any Plain text of a page /api/books/:id/page/:num/wordsGET any Word bounding boxes for text overlay
Maps Endpoint Method Auth Description /api/mapsGET any Paginated map list. Query: limit, offset, tag /api/maps/:idGET any Map detail /api/maps/:idPATCH gm/admin Update description, tags, map_type, grid_size /api/maps/:id/fileGET any Download/stream the map image /api/maps/:id/thumbnailGET any WebP thumbnail /api/map-foldersGET any List folder tag assignments /api/map-foldersPATCH gm/admin Set tags on a folder. Body: {path, tags}
Tokens Endpoint Method Auth Description /api/tokensGET any Paginated token list. Query: limit, offset, tag /api/tokens/:idGET any Token detail /api/tokens/:idPATCH gm/admin Update description, tags, is_explicit /api/tokens/:id/fileGET any Download the token image /api/tokens/:id/thumbnailGET any WebP thumbnail /api/token-foldersGET any List folder tag assignments /api/token-foldersPATCH gm/admin Set tags on a folder. Body: {path, tags}
Search Endpoint Method Auth Description /api/search?q=GET any FTS5 full-text search. Min 2 chars. Optional: book_id, system_id, limit
Response:
json {
"query" : "fireball" ,
"total" : 42 ,
"results" : [{ "id" : "uuid" , "title" : "..." , "game_system" : "..." , "page_number" : 42 , "snippet" : "..." }],
"maps" : [{ "id" : "uuid" , "filename" : "..." , "relative_path" : "..." , "tags" : []}],
"tokens" : [{ "id" : "uuid" , "filename" : "..." , "relative_path" : "..." , "tags" : []}]
} maps and tokens are empty when book_id or system_id is scoped.
Favorites Endpoint Method Auth Description /api/favoritesGET any List current user's favorites /api/favoritesPOST any Add a favorite (idempotent). Body: {item_type, item_id} /api/favorites/:type/:idDELETE any Remove a favorite
Item types: book, map, token, system
Bookmarks Endpoint Method Auth Description /api/bookmarks?book_id=GET any List user's bookmarks for a book /api/bookmarksPOST any Create a bookmark. Body: {book_id, page_number, label?, notes?, selected_text?} /api/bookmarks/:idPATCH any Update label or notes /api/bookmarks/:idDELETE any Delete a bookmark
Campaigns Campaign CRUD Endpoint Method Auth Description /api/campaignsGET any List own + invited campaigns /api/campaignsPOST any Create campaign /api/campaigns/:idGET owner or member Campaign detail /api/campaigns/:idPATCH owner or admin Update campaign /api/campaigns/:idDELETE owner or admin Delete campaign
Members Endpoint Method Auth Description /api/campaigns/:id/invitePOST owner or admin Invite a user. Body: {user_id} /api/campaigns/:id/members/:user_idPATCH member or owner Accept/decline or set character name /api/campaigns/:id/members/:user_idDELETE owner, admin, or self Remove member
Sessions Endpoint Method Auth Description /api/campaigns/:id/sessionsGET member or owner List sessions /api/campaigns/:id/sessionsPOST member or owner Create session. Body: {session_date, title?} /api/campaigns/:id/sessions/:sidPATCH owner or admin Update title /api/campaigns/:id/sessions/:sidDELETE owner or admin Delete session /api/campaigns/:id/sessions/:sid/notes/playerPUT member or owner Save player note. Body: {content} /api/campaigns/:id/sessions/:sid/notes/gmPUT owner or admin Save GM notes. Body: {internal_content?, external_content?}
Schedule Endpoint Method Auth Description /api/campaigns/:id/scheduleGET member or owner Schedule + next 10 dates /api/campaigns/:id/schedulePUT owner or admin Create or update schedule /api/campaigns/:id/scheduleDELETE owner or admin Remove schedule
Schedule body:
json {
"frequency" : "weekly" ,
"days" : [ 5 ],
"time_utc" : "18:00" ,
"biweekly_reference" : "2026-01-03" ,
"monthly_week" : null ,
"custom_dates" : null
} frequency values: weekly, biweekly, monthly, custom. Days are 0 (Monday) – 6 (Sunday).
Availability Endpoint Method Auth Description /api/campaigns/:id/availabilityGET member or owner Availability for next 10 scheduled sessions /api/campaigns/:id/availability/:datePUT member or owner Set own availability. Body: {status} /api/campaigns/:id/availability/:date/cancelPUT owner or admin Toggle session cancellation
Statuses: available, tentative, unavailable
Settings (admin only) Endpoint Method Description /api/settingsGET Get all application settings /api/settingsPATCH Update application settings /api/settings/uiGET UI visibility flags (any authenticated user) /api/settings/api-key/generatePOST Generate a stats API key /api/settings/api-keyDELETE Revoke the stats API key
Maintenance (admin only) Endpoint Method Description /api/maintenance/cleanup-missingPOST Remove DB records for files no longer present on disk
Logs (admin only) Endpoint Method Description /api/logsGET Retrieve recent log entries from the in-memory ring buffer
Query parameters: level (default info), limit (default 200, max 20000), offset, after_seq (cursor for live polling).
Error responses json { "detail" : "Human-readable error message" } Status Meaning 400Bad request / business rule violated 401Not authenticated 403Forbidden, insufficient role 404Not found 409Conflict, duplicate resource 422Request body failed schema validation