openapi: 3.0.3 info: title: Bookhoard API version: '2026.10.24' description: | Generated from the canonical API docs (docs/developer/api/**) by internal/docs (go test ./internal/docs -run TestBrunoMirrorsDocs -update). The docs site is the shape reference; this file lists the surface. servers: - url: / components: securitySchemes: bearerAuth: type: http scheme: bearer bearerFormat: JWT paths: "/api/admin/hash-conflicts": get: tags: [admin] summary: "Hash Conflicts (API)" security: - bearerAuth: [] responses: '200': description: OK "/api/analytics/device-usage": get: tags: [analytics] summary: "Get Device Usage" security: - bearerAuth: [] responses: '200': description: OK "/api/analytics/popular-books": get: tags: [analytics] summary: "Get Popular Books" security: - bearerAuth: [] responses: '200': description: OK "/api/analytics/reading-stats": get: tags: [analytics] summary: "Get Reading Statistics" security: - bearerAuth: [] responses: '200': description: OK "/api/auth/login": post: tags: [authentication] summary: "Login User" security: [] requestBody: content: application/json: example: |- { "login": "user@example.com", "password": "SecureP@ss123!" } responses: '200': description: OK "/api/auth/logout": post: tags: [authentication] summary: "Logout User" security: [] responses: '200': description: OK "/api/auth/password": put: tags: [authentication] summary: "Change Password" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "current_password": "OldPassword123!", "new_password": "NewSecureP@ss123!", "confirm_password": "NewSecureP@ss123!" } responses: '200': description: OK "/api/auth/password-rules": get: tags: [authentication] summary: "Password Rules" security: [] responses: '200': description: OK "/api/auth/profile": delete: tags: [authentication] summary: "Delete User" security: - bearerAuth: [] responses: '200': description: OK get: tags: [authentication] summary: "Get Current User Profile" security: - bearerAuth: [] responses: '200': description: OK put: tags: [authentication] summary: "Update Profile" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "username": "newusername", "email": "newemail@example.com", "first_name": "John", "last_name": "Smith", "theme": "dracula" } responses: '200': description: OK "/api/auth/refresh": post: tags: [authentication] summary: "Refresh Token" security: [] requestBody: content: application/json: example: |- { "refresh_token": "d4f5g6h7..." } responses: '200': description: OK "/api/auth/register": post: tags: [authentication] summary: "Register User" security: [] requestBody: content: application/json: example: |- { "email": "user@example.com", "username": "john", "password": "SecureP@ss123!", "first_name": "John", "last_name": "Doe" } responses: '201': description: Created "/api/auth/users": get: tags: [authentication] summary: "List Users" security: - bearerAuth: [] responses: '200': description: OK "/api/auth/users/{id}/max-devices": put: tags: [authentication] summary: "Update User Max Devices" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "max_devices": 15 } responses: '200': description: OK "/api/books/match": get: tags: [book-matching] summary: "Get Book Matches" security: - bearerAuth: [] responses: '200': description: OK "/api/collections": get: tags: [collections] summary: "List Collections" security: - bearerAuth: [] responses: '200': description: OK post: tags: [collections] summary: "Create Collection" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "name": "To Read", "description": "Books I want to read soon", "color": "#00FF00", "icon": "📖", "collection_type": "static", "auto_assign_rules": [], "view_settings": { "kobo": { "view_mode": "grid" } } } responses: '200': description: Success "/api/collections/bulk-add-books": post: tags: [collections] summary: "Bulk Add Books" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "operations": [ { "collection_id": "550e8400-e29b-41d4-a716-446655440000", "book_ids": [ "660e8400-e29b-41d4-a716-446655440001" ] } ] } responses: '200': description: Success "/api/collections/preview": post: tags: [collections] summary: "Preview Collection" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "library_id": "550e8400-e29b-41d4-a716-446655440000", "rules": [], "manual_book_ids": [], "limit": 20 } responses: '200': description: Success "/api/collections/test-rules": post: tags: [collections] summary: "Test Rule" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "rules": [ { "field": "genre", "operator": "equals", "value": "Science Fiction" }, { "field": "author", "operator": "contains", "value": "Asimov" } ] } responses: '200': description: OK "/api/collections/{id}": delete: tags: [collections] summary: "Delete Collection" security: - bearerAuth: [] responses: '204': description: No Content get: tags: [collections] summary: "Get Collection" security: - bearerAuth: [] responses: '200': description: OK put: tags: [collections] summary: "Update Collection" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "name": "To Read (2026)", "description": "Updated description", "color": "#33CCFF", "icon": "📚", "auto_assign_rules": [], "view_settings": { "hide_finished": true }, "hide_finished": ["true"], "show_up_next": ["true"] } responses: '200': description: Success "/api/collections/{id}/books": get: tags: [collections] summary: "Get Book Collections" security: - bearerAuth: [] responses: '200': description: OK post: tags: [collections] summary: "Bulk Assign Books" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "book_ids": [ "660e8400-e29b-41d4-a716-446655440000", "770e8400-e29b-41d4-a716-446655440000", "880e8400-e29b-41d4-a716-446655440000" ] } responses: '204': description: No Content "/api/collections/{id}/books/bulk-remove": post: tags: [collections] summary: "Bulk Remove Books" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "book_ids": [ "550e8400-e29b-41d4-a716-446655440000", "660e8400-e29b-41d4-a716-446655440001" ] } responses: '200': description: Success "/api/collections/{id}/items/order": put: tags: [collections] summary: "Reorder Collection Items" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "item_ids": [ "550e8400-e29b-41d4-a716-446655440000", "660e8400-e29b-41d4-a716-446655440001" ] } responses: '200': description: Success "/api/collections/{id}/rules": post: tags: [collections] summary: "Add Auto-Assign Rule" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "field": "genre", "operator": "equals", "value": "Science Fiction", "priority": 1, "enabled": true } responses: '201': description: Created "/api/collections/{id}/rules/{ruleId}": delete: tags: [collections] summary: "Remove Auto-Assign Rule" security: - bearerAuth: [] responses: '204': description: No Content put: tags: [collections] summary: "Update Collection Rule" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "enabled": false } responses: '200': description: Success "/api/conflicts": get: tags: [conflicts] summary: "List Conflicts" security: - bearerAuth: [] responses: '200': description: OK "/api/conflicts/bulk-dismiss": post: tags: [conflicts] summary: "Bulk Dismiss Conflicts" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "conflict_ids": [ "550e8400-e29b-41d4-a716-446655440000", "660e8400-e29b-41d4-a716-446655440001" ] } responses: '200': description: OK "/api/conflicts/bulk-resolve": post: tags: [conflicts] summary: "Bulk Resolve Conflicts" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "conflict_ids": [ "550e8400-e29b-41d4-a716-446655440000", "660e8400-e29b-41d4-a716-446655440001" ], "strategy": "highest_progress" } responses: '200': description: OK "/api/conflicts/dismiss-all": post: tags: [conflicts] summary: "Dismiss All Resolved" security: - bearerAuth: [] responses: '200': description: OK "/api/conflicts/{id}": delete: tags: [conflicts] summary: "Delete Conflict" security: - bearerAuth: [] responses: '204': description: No Content get: tags: [conflicts] summary: "Get Conflict Details" security: - bearerAuth: [] responses: '200': description: OK "/api/conflicts/{id}/resolve": post: tags: [conflicts] summary: "Resolve Conflict" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "winner": "kobo" } responses: '200': description: OK "/api/dashboard/preferences": get: tags: [dashboard] summary: "Get Dashboard Preferences" security: - bearerAuth: [] responses: '200': description: OK put: tags: [dashboard] summary: "Update Dashboard Preferences" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "library_id": "550e8400-e29b-41d4-a716-446655440000", "hidden_collections": ["not-started"], "collection_order": ["recently-added", "continue-reading", "recently-read"], "items_per_section": 20 } responses: '200': description: Success "/api/dashboard/restore-system-collection": post: tags: [dashboard] summary: "Restore System Collection" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "collection_name": "Continue Reading", "reset_type": "full" } responses: '200': description: Success "/api/dashboard/sections": get: tags: [dashboard] summary: "Get Dashboard Sections" security: - bearerAuth: [] responses: '200': description: OK "/api/devices": get: tags: [devices] summary: "List User Devices" security: - bearerAuth: [] responses: '200': description: OK "/api/devices/approve/{registration_id}": get: tags: [devices] summary: "Approve Device Registration" security: - bearerAuth: [] responses: '200': description: OK "/api/devices/pending": get: tags: [devices] summary: "List Pending Device Registrations:\u003c|end|\u003e\u003c|start|\u003e\u003c|start|\u003eassistant to=edit\u003c|channel|\u003eanalysis \u003c|constrain|\u003exml\u003c|message|\u003e\u003crfl:parameter name=\"path\"\u003e" security: - bearerAuth: [] responses: '200': description: OK "/api/devices/register": post: tags: [devices] summary: "Register Device" security: [] requestBody: content: application/json: example: |- { "device_name": "My Kobo Clara", "device_type": "kobo", "device_identifier": "hardware-specific-id" } responses: '201': description: Created "/api/devices/register/status": post: tags: [devices] summary: "Get Device / Check Registration Status" security: [] requestBody: content: application/json: example: |- { "registration_id": "registration-uuid" } responses: '200': description: OK "/api/devices/reject/{registration_id}": post: tags: [devices] summary: "Reject Device Registration" security: - bearerAuth: [] responses: '200': description: OK "/api/devices/{deviceId}/sync/link-book": post: tags: [book-matching] summary: "Link Book" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "device_file": { "file_path": "/books/hobbit.epub", "sha256": "abc123...", "title": "The Hobbit" }, "media_item_id": "550e8400-e29b-41d4-a716-446655440000", "confidence_score": 1.0 } responses: '200': description: OK post: tags: [devices] summary: "Link Book" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "device_file": { "file_path": "/books/1984.epub", "sha256": "abc123...", "title": "1984" }, "media_item_id": "550e8400-e29b-41d4-a716-446655440000", "confidence_score": 0.95 } responses: '200': description: Success "/api/devices/{deviceId}/sync/unlinked-books": get: tags: [book-matching] summary: "Get Unlinked Books" security: - bearerAuth: [] responses: '200': description: OK "/api/devices/{id}": delete: tags: [devices] summary: "Delete Device" security: - bearerAuth: [] responses: '204': description: No Content get: tags: [devices] summary: "Get Device" security: - bearerAuth: [] responses: '200': description: OK put: tags: [devices] summary: "Update Device" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "device_name": "My Kobo Clara", "sync_enabled": true, "auto_sync": true, "sync_frequency_minutes": 60 } responses: '200': description: OK "/api/devices/{id}/collections": get: tags: [devices] summary: "Get Device Collection Mappings" security: - bearerAuth: [] responses: '200': description: OK post: tags: [collections] summary: "Create Shelf Mapping" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "collection_id": "550e8400-e29b-41d4-a716-446655440000", "device_shelf_name": "Sci-Fi", "sync_direction": "bidirectional" } responses: '201': description: Created "/api/devices/{id}/collections/{collectionId}": delete: tags: [collections] summary: "Delete Shelf Mapping" security: - bearerAuth: [] responses: '204': description: No Content put: tags: [devices] summary: "Update Device Collection Mapping" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "device_shelf_name": "Kobo", "sync_direction": "bidirectional" } responses: '200': description: Success "/api/devices/{id}/file-aliases": get: tags: [book-matching] summary: "Get Device File Aliases" security: - bearerAuth: [] responses: '200': description: OK post: tags: [book-matching] summary: "Create Device File Alias" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "media_item_id": "550e8400-e29b-41d4-a716-446655440001", "file_name": "book.epub", "file_hash": "abc123..." } responses: '201': description: Created "/api/devices/{id}/file-aliases/{aliasId}": delete: tags: [book-matching] summary: "Delete Device File Alias" security: - bearerAuth: [] responses: '204': description: No Content put: tags: [book-matching] summary: "Update Device File Alias" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "file_name": "updated-book.epub", "file_hash": "newhash123..." } responses: '200': description: OK "/api/devices/{id}/regenerate-token": put: tags: [devices] summary: "Regenerate Device Token" security: - bearerAuth: [] responses: '200': description: Success "/api/devices/{id}/shelves": delete: tags: [devices] summary: "Remove from Shelf" security: - bearerAuth: [] responses: '200': description: OK get: tags: [devices] summary: "Get Shelf" security: - bearerAuth: [] responses: '200': description: OK post: tags: [devices] summary: "Add to Shelf" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "media_item_ids": ["550e8400-e29b-41d4-a716-446655440001"], "shelf_name": "Default", "shelf_position": 0 } responses: '200': description: OK "/api/devices/{id}/shelves/clear": delete: tags: [devices] summary: "Clear Shelf" security: - bearerAuth: [] responses: '200': description: OK "/api/devices/{id}/sidecar": get: tags: [devices] summary: "Get Device Sidecar Config" security: - bearerAuth: [] responses: '200': description: OK "/api/devices/{id}/sidecar/download": get: tags: [devices] summary: "Download Sidecar Config" security: - bearerAuth: [] responses: '200': description: OK "/api/jobs": post: tags: [jobs] summary: "Create Job" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "type": "import", "params": { "library_id": "990e8400-e29b-41d4-a716-446655440000" } } responses: '202': description: Accepted "/api/jobs/{jobId}": get: tags: [jobs] summary: "Get Job Status" security: - bearerAuth: [] responses: '200': description: OK "/api/libraries": get: tags: [libraries] summary: "List Libraries (Admin)" security: - bearerAuth: [] responses: '200': description: OK post: tags: [libraries] summary: "Create Library" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "name": "Comics Collection", "description": "Digital comics", "type": "comics" } responses: '201': description: Created "/api/libraries/browse": get: tags: [libraries] summary: "Browse Library Folders" security: - bearerAuth: [] responses: '200': description: OK "/api/libraries/scan-settings": get: tags: [libraries] summary: "Get Scan Settings" security: - bearerAuth: [] responses: '200': description: OK put: tags: [libraries] summary: "Update Scan Settings" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "scan_poll_interval_seconds": 3600, "auto_scan_enabled": true } responses: '200': description: Success "/api/libraries/types": get: tags: [libraries] summary: "Get Library Types" security: [] responses: '200': description: OK "/api/libraries/visibility": get: tags: [libraries] summary: "Get Visible Libraries" security: - bearerAuth: [] responses: '200': description: OK post: tags: [libraries] summary: "Set Library Visibility" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "library_id": "library-uuid", "is_visible": true } responses: '200': description: OK "/api/libraries/{id}": delete: tags: [libraries] summary: "Delete Library" security: - bearerAuth: [] responses: '204': description: No Content get: tags: [libraries] summary: "Get Library Details:\u003c|end|\u003e\u003c|start|\u003e assistant to=edit\u003c|channel|\u003eanalysis \u003c|constrain|\u003exml\u003c|message|\u003e\u003crfl:parameter name=\"path\"\u003e" security: - bearerAuth: [] responses: '200': description: OK put: tags: [libraries] summary: "Update Library" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "name": "My Updated Library", "description": "Updated description" } responses: '200': description: OK "/api/libraries/{id}/folders": delete: tags: [libraries] summary: "Delete Library Folder" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "folder_path": "/path/to/library/folder" } responses: '204': description: No Content get: tags: [libraries] summary: "Get Library Folders" security: - bearerAuth: [] responses: '200': description: OK post: tags: [libraries] summary: "Add Library Folder" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "folder_path": "/path/to/comics" } responses: '201': description: Created "/api/libraries/{id}/issues/list": get: tags: [libraries] summary: "List Processing Issues" security: - bearerAuth: [] responses: '200': description: OK "/api/libraries/{id}/issues/stats": get: tags: [libraries] summary: "Get Processing Issue Stats" security: - bearerAuth: [] responses: '200': description: OK "/api/libraries/{id}/issues/{issueId}": delete: tags: [libraries] summary: "Delete Processing Issue" security: - bearerAuth: [] responses: '200': description: Success "/api/libraries/{id}/issues/{issueId}/{mediaItemId}/resolve": post: tags: [libraries] summary: "Resolve Processing Issue" security: - bearerAuth: [] responses: '200': description: Success "/api/libraries/{id}/media-items": get: tags: [libraries] summary: "Get Library Media Items" security: - bearerAuth: [] responses: '200': description: OK "/api/libraries/{id}/scan": post: tags: [libraries] summary: "Scan Library" security: - bearerAuth: [] responses: '200': description: Success "/api/libraries/{id}/stats": get: tags: [libraries] summary: "Get Library Statistics" security: - bearerAuth: [] responses: '200': description: OK "/api/media-items": get: tags: [media-items] summary: "List Media Items" security: - bearerAuth: [] responses: '200': description: OK post: tags: [media-items] summary: "Create Media Item" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "library_id": "550e8400-e29b-41d4-a716-446655440000", "title": "Example Book Title", "author": "Jane Doe", "isbn": "978-0-123456-78-9", "description": "A great book about technology", "file_path": "/library/books/example.epub", "file_size": 1048576, "mime_type": "application/epub+zip", "series": "Tech Series", "series_number": 1, "tags": ["science-fiction", "technology", "ACME CORP."], "publisher": "O'Reilly Media", "contributors": ["John Smith", "ACME CORP."] } responses: '201': description: Created "/api/media-items/bulk-delete": post: tags: [media-items] summary: "Bulk Delete Media Items" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "media_item_ids": [ "550e8400-e29b-41d4-a716-446655440001", "660e8400-e29b-41d4-a716-446655440002", "770e8400-e29b-41d4-a716-446655440003" ] } responses: '200': description: OK "/api/media-items/bulk-update": post: tags: [media-items] summary: "Bulk Update Media Items" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "media_item_updates": [ { "media_item_id": "550e8400-e29b-41d4-a716-446655440001", "updates": { "title": "Updated Title", "genre": "Science Fiction", "tags": ["science fiction", "space opera", "ACME CORP."] } }, { "media_item_id": "660e8400-e29b-41d4-a716-446655440002", "updates": { "author": "Updated Author Name", "language": "en" } } ] } responses: '200': description: OK "/api/media-items/facets": get: tags: [media-items] summary: "Get Media Item Facets" security: - bearerAuth: [] responses: '200': description: OK "/api/media-items/filter-count": get: tags: [media-items] summary: "Filter Count" security: - bearerAuth: [] responses: '200': description: OK "/api/media-items/purge-archived": post: tags: [media-items] summary: "Purge Archived Media Items" security: - bearerAuth: [] responses: '200': description: Success "/api/media-items/search": get: tags: [media-items] summary: "Search Media Items (Unified):\u003c|end|\u003e\u003c|start|\u003eedit to=assistant\u003c|channel|\u003eanalysis\u003c|message|\u003eEdited docs/developer/api/media-items/create_media_item.md (1 replacement)\u003c|end|\u003e\u003c|start|\u003eedit to=assistant\u003c|channel|\u003eanalysis\u003c|message|\u003eEdited docs/developer/api/media-items/update_media_item.md (1 replacement)\u003c|end|\u003e\u003c|start|\u003eedit to=assistant\u003c|channel|\u003eanalysis\u003c|channel|\u003eEdited docs/developer/api/media-items/delete_media_item.md (1 replacement)\u003c|end|\u003e\u003c|start|\u003eedit to=assistant\u003c|channel|\u003eanalysis\u003c|message|\u003eEdited docs/developer/api/media-items/search_media_items.md (1 replacement)" security: - bearerAuth: [] responses: '200': description: OK "/api/media-items/{id}": delete: tags: [media-items] summary: "Delete Media Item" security: - bearerAuth: [] responses: '204': description: No Content get: tags: [media-items] summary: "Get Media Item" security: - bearerAuth: [] responses: '200': description: OK put: tags: [media-items] summary: "Update Media Item" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "title": "Updated Title", "author": "Updated Author", "description": "Updated description", "series": "Series", "series_number": 2 } responses: '200': description: OK "/api/media-items/{id}/annotations/deleted": get: tags: [media-items] summary: "Deleted Annotations History" security: - bearerAuth: [] responses: '200': description: OK "/api/media-items/{id}/annotations/{annotationId}": delete: tags: [media-items] summary: "Purge Deleted Annotation" security: - bearerAuth: [] responses: '200': description: Success "/api/media-items/{id}/annotations/{annotationId}/restore": post: tags: [media-items] summary: "Restore Deleted Annotation" security: - bearerAuth: [] responses: '200': description: Success "/api/media-items/{id}/audio-speed": put: tags: [media-items] summary: "Set Audio Speed" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "speed": 1.5 } responses: '200': description: Success "/api/media-items/{id}/audio/{trackIndex}": get: tags: [media-items] summary: "Get Audio Track" security: - bearerAuth: [] responses: '200': description: OK "/api/media-items/{id}/bookmarks": get: tags: [media-items] summary: "Get Media Bookmarks" security: - bearerAuth: [] responses: '200': description: OK post: tags: [media-items] summary: "Create Media Bookmark" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "title": "Chapter 3", "position": "kindle:pos:1:2", "notes": "revisit this", "cfi_position": "epubcfi(/6/4)", "page_number": 42, "chapter_number": 3, "percentage": 35.5, "chapter_reference": 3, "origin": "android" } responses: '200': description: Success "/api/media-items/{id}/bookmarks/{bookmarkId}": delete: tags: [media-items] summary: "Delete Media Bookmark" security: - bearerAuth: [] responses: '204': description: No Content put: tags: [media-items] summary: "Update Media Bookmark" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "title": "Chapter 3 (renamed)", "notes": "updated note", "position": "kindle:pos:1:2" } responses: '200': description: Success "/api/media-items/{id}/chapters": get: tags: [media-items] summary: "Get Audio Chapters" security: - bearerAuth: [] responses: '200': description: OK "/api/media-items/{id}/download": get: tags: [media-items] summary: "Download Media Item File" security: - bearerAuth: [] responses: '200': description: OK "/api/media-items/{id}/highlights": get: tags: [media-items] summary: "Get Highlights" security: - bearerAuth: [] responses: '200': description: OK post: tags: [media-items] summary: "Create Highlight" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "selection_text": "Highlighted text...", "start_position": "epubcfi(/6/4/2:15)", "end_position": "epubcfi(/6/4/2:20)", "color": "#ffff00", "percentage_start": 0.45, "percentage_end": 0.47 } responses: '201': description: Created "/api/media-items/{id}/highlights/{highlightId}": delete: tags: [media-items] summary: "Delete Highlight" security: - bearerAuth: [] responses: '204': description: No Content get: tags: [media-items] summary: "Get Media Highlight" security: - bearerAuth: [] responses: '200': description: OK put: tags: [media-items] summary: "Update Highlight" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "selection_text": "Updated text", "color": "#00ff00" } responses: '200': description: OK "/api/media-items/{id}/merge": post: tags: [media-items] summary: "Merge Archived Media Item" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "target_id": "550e8400-e29b-41d4-a716-446655440000" } responses: '200': description: Success "/api/media-items/{id}/notes": get: tags: [media-items] summary: "Get Notes" security: - bearerAuth: [] responses: '200': description: OK post: tags: [media-items] summary: "Create Note" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "content": "This is a note", "position": "epubcfi(/6/4/2:15)", "origin": "web" } responses: '201': description: Created "/api/media-items/{id}/notes/{noteId}": delete: tags: [media-items] summary: "Delete Note" security: - bearerAuth: [] responses: '204': description: No Content get: tags: [media-items] summary: "Get Media Note" security: - bearerAuth: [] responses: '200': description: OK put: tags: [media-items] summary: "Update Note" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "content": "Updated note content", "position": "epubcfi(/6/4/2:20)" } responses: '200': description: OK "/api/media-items/{id}/progress": delete: tags: [media-items] summary: "Delete Media Item Progress" security: - bearerAuth: [] responses: '200': description: OK get: tags: [media-items] summary: "Get Media Item Progress" security: - bearerAuth: [] responses: '200': description: OK put: tags: [media-items] summary: "Update Media Item Progress" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "percentage": 0.0415, "context_text": "was at war with one of these Powers it was generally at peace with the other. But what was strange w", "epubcfi": "epubcfi(/6/4!/4/8[_idContainer003]/62/1:456)" } responses: '200': description: OK "/api/media-items/{id}/rating": delete: tags: [media-items] summary: "Delete Rating" security: - bearerAuth: [] responses: '200': description: OK get: tags: [media-items] summary: "Get Rating" security: - bearerAuth: [] responses: '200': description: OK post: tags: [media-items] summary: "Create Rating" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "rating": 8 } responses: '201': description: Created put: tags: [media-items] summary: "Update Rating" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "rating": 8, "review": "Great book! Very enjoyable read." } responses: '200': description: OK "/api/media-items/{id}/rescan": post: tags: [media-items] summary: "Rescan Media Item" security: - bearerAuth: [] responses: '200': description: Success "/api/media-items/{id}/review": delete: tags: [media-items] summary: "Delete Media Review" security: - bearerAuth: [] responses: '200': description: Success get: tags: [media-items] summary: "Get Media Review" security: - bearerAuth: [] responses: '200': description: OK post: tags: [media-items] summary: "Upsert Media Review" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "review": "A slow start, but the second act earns it." } responses: '200': description: Success "/api/media-items/{id}/unarchive": post: tags: [media-items] summary: "Unarchive Media Item" security: - bearerAuth: [] responses: '204': description: No Content "/api/progress/{id}/history": get: tags: [progress] summary: "Get Progress History" security: - bearerAuth: [] responses: '200': description: OK "/api/queue/devices/{device_id}/clear": delete: tags: [queue] summary: "Clear Device Queue" security: - bearerAuth: [] responses: '200': description: OK "/api/queue/devices/{device_id}/items": get: tags: [queue] summary: "List Device Queue Items" security: - bearerAuth: [] responses: '200': description: OK "/api/queue/devices/{device_id}/stats": get: tags: [queue] summary: "Get Device Queue Statistics" security: - bearerAuth: [] responses: '200': description: OK "/api/queue/items": get: tags: [queue] summary: "List All Queue Items (Admin)" security: - bearerAuth: [] responses: '200': description: OK "/api/queue/items/{item_id}": delete: tags: [queue] summary: "Delete Queue Item" security: - bearerAuth: [] responses: '204': description: No Content "/api/queue/items/{item_id}/retry": post: tags: [queue] summary: "Retry Queue Item" security: - bearerAuth: [] responses: '200': description: OK "/api/saved-filters": get: tags: [saved-filters] summary: "List Saved Filters" security: - bearerAuth: [] responses: '200': description: OK post: tags: [saved-filters] summary: "Create Saved Filter" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "name": "My Filter", "resource_type": "media-items", "filters": {} } responses: '200': description: Success "/api/saved-filters/{id}": delete: tags: [saved-filters] summary: "Delete Saved Filter" security: - bearerAuth: [] responses: '200': description: Success get: tags: [saved-filters] summary: "Get Saved Filter" security: - bearerAuth: [] responses: '200': description: OK put: tags: [saved-filters] summary: "Update Saved Filter" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "name": "Renamed Filter", "resource_type": "media-items", "filters": {} } responses: '200': description: Success "/api/scanner/active": get: tags: [scanner] summary: "Get Active Scans" security: - bearerAuth: [] responses: '200': description: OK "/api/scanner/active-summary": get: tags: [scanner] summary: "Get Scan Summary" security: - bearerAuth: [] responses: '200': description: OK "/api/scanner/cancel/{jobId}": post: tags: [scanner] summary: "Cancel Scan" security: - bearerAuth: [] responses: '200': description: Success "/api/scanner/scan": post: tags: [scanner] summary: "Scan Library" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "library_id": "550e8400-e29b-41d4-a716-446655440000", "force": false } responses: '202': description: Accepted "/api/scanner/start": post: tags: [scanner] summary: "Start Scanner" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "folder_paths": ["/data/books"] } responses: '200': description: OK "/api/scanner/status/{jobId}": get: tags: [scanner] summary: "Get Scan Status" security: - bearerAuth: [] responses: '200': description: OK "/api/scanner/stop": post: tags: [scanner] summary: "Stop Scanner" security: - bearerAuth: [] responses: '200': description: OK "/api/scanner/watch/start": post: tags: [scanner] summary: "Start Watch Mode" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "library_id": "550e8400-e29b-41d4-a716-446655440000" } responses: '200': description: OK "/api/scanner/watch/status": get: tags: [scanner] summary: "Get Watch Mode Status" security: - bearerAuth: [] responses: '200': description: OK "/api/scanner/watch/stop": post: tags: [scanner] summary: "Stop Watch Mode" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "library_id": "550e8400-e29b-41d4-a716-446655440000" } responses: '200': description: OK "/api/series": get: tags: [series] summary: "List Series" security: - bearerAuth: [] responses: '200': description: OK "/api/series/books": get: tags: [series] summary: "Get Series Books" security: - bearerAuth: [] responses: '200': description: OK "/api/stats/books/{id}": get: tags: [stats] summary: "Get Book Stats" security: - bearerAuth: [] responses: '200': description: OK "/api/stats/library-usage": get: tags: [stats] summary: "Get Library Usage Statistics" security: - bearerAuth: [] responses: '200': description: OK "/api/stats/summary": get: tags: [stats] summary: "Get Reading Summary" security: - bearerAuth: [] responses: '200': description: OK "/api/stats/this-week": get: tags: [stats] summary: "Get This Week's Stats" security: - bearerAuth: [] responses: '200': description: OK "/api/sync/auto-link-books": post: tags: [book-matching] summary: "Auto Link Books" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "confidence_threshold": 0.8, "limit": 100 } responses: '200': description: OK "/api/sync/books/query": post: tags: [book-matching] summary: "Search Books for Matching" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "identifiers": ["isbn:978-0345391802", "uuid:abc-123"], "sha256": "a1b2c3d4e5f6abc123...", "title": "The Hobbit", "author": "J.R.R. Tolkien", "file_size": 2456789 } responses: '200': description: OK "/api/sync/bulk-link-books": post: tags: [book-matching] summary: "Bulk Link Books" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "links": [ { "unlinked_book_id": "770e8400-e29b-41d4-a716-446655440002", "media_item_id": "660e8400-e29b-41d4-a716-446655440001", "confidence_score": 0.95 }, { "unlinked_book_id": "880e8400-e29b-41d4-a716-446655440003", "media_item_id": "990e8400-e29b-41d4-a716-446655440004", "confidence_score": 0.87 } ] } responses: '200': description: OK "/api/sync/kobo/{token}/bookmark": post: tags: [kobo] summary: "Bookmark Sync" description: 'Device token: Bearer header (KOReader) or ?token= query (Kobo/OPDS).' requestBody: content: application/json: example: |- { "bookmarks": [ { "BookmarkID": "bookmark123", "ContentID": "book-uuid", "StartPosition": 1234, "Text": "Chapter 5", "DateCreated": "2026-02-08T10:00:00Z" } ] } responses: '200': description: OK "/api/sync/kobo/{token}/markup": post: tags: [kobo] summary: "Markup Sync" description: 'Device token: Bearer header (KOReader) or ?token= query (Kobo/OPDS).' requestBody: content: application/json: example: |- { "bookmarks": [ { "BookmarkID": "bookmark123", "ContentID": "book-uuid", "StartPosition": 1234, "EndPosition": 1456, "Text": "Highlighted text from book", "Annotation": "My annotation", "DateCreated": "2026-02-08T10:00:00Z", "Chapter": "Chapter 1", "Hidden": false } ] } responses: '200': description: OK "/api/sync/kobo/{token}/sync-from-server": post: tags: [kobo] summary: "Sync From Server" description: 'Device token: Bearer header (KOReader) or ?token= query (Kobo/OPDS).' requestBody: content: application/json: example: |- { "book_ids": ["content-id-1", "content-id-2"], "full_sync": false } responses: '200': description: OK "/api/sync/kobo/{token}/v1/analytics/gettests": post: tags: [kobo] summary: "Analytics GetTests" description: 'Device token: Bearer header (KOReader) or ?token= query (Kobo/OPDS).' requestBody: content: application/json: example: |- { "data": {} } responses: '200': description: OK "/api/sync/kobo/{token}/v1/initialization": get: tags: [kobo] summary: "Kobo Initialization" description: 'Device token: Bearer header (KOReader) or ?token= query (Kobo/OPDS).' responses: '200': description: OK "/api/sync/koreader/bookmarks": post: tags: [koreader] summary: "Sync Bookmarks" description: 'Device token: Bearer header (KOReader) or ?token= query (Kobo/OPDS).' requestBody: content: application/json: example: |- { "book_sha256": "64-hex-char-sha256", "bookmarks": [ { "chapter": 3, "datetime": "2026-08-20T10:00:00Z", "pos0": "/body/Doc[4]/Sec[2]", "page": 25, "text": "", "type": "bookmark", "percentage": 0.125 } ], "highlights": [ { "datetime": "2026-08-20T10:05:00Z", "pos0": "/body/Doc[4]/Sec[2]/text()[3]:0", "pos1": "/body/Doc[4]/Sec[2]/text()[3]:42", "text": "Text to remember", "notes": "Why this matters", "type": "highlight", "color": "blue", "dedup_key": "echo-key-from-server" } ] } responses: '200': description: OK "/api/sync/koreader/library": get: tags: [koreader] summary: "Get Library" description: 'Device token: Bearer header (KOReader) or ?token= query (Kobo/OPDS).' responses: '200': description: OK "/api/sync/koreader/metadata/{uuid}": get: tags: [koreader] summary: "Get Metadata" description: 'Device token: Bearer header (KOReader) or ?token= query (Kobo/OPDS).' responses: '200': description: OK "/api/sync/koreader/progress": post: tags: [koreader] summary: "Sync Progress" description: 'Device token: Bearer header (KOReader) or ?token= query (Kobo/OPDS).' requestBody: content: application/json: example: |- { "books": [ { "uuid": "774641f9-317b-4087-8e04-53bb4392ae56", "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "title": "1984", "authors": ["George Orwell"], "percentage": 0.045, "context_text": "from day to day, but there was none in which Goldstein was not the principal figure. He was the prim", "page": 14, "total_pages": 311, "epubcfi": "/body/DocFragment[1]/body/p[29]/text().598", "device_info": { "koreader_version": "v2026.07.1", "device_model": "emulator" } } ], "sync_mode": "immediate" } responses: '202': description: Accepted "/api/sync/koreader/rating": get: tags: [koreader] summary: "Get KOReader Rating" description: 'Device token: Bearer header (KOReader) or ?token= query (Kobo/OPDS).' responses: '200': description: OK post: tags: [koreader] summary: "Set KOReader Rating" description: 'Device token: Bearer header (KOReader) or ?token= query (Kobo/OPDS).' requestBody: content: application/json: example: |- { "rating": 8 } responses: '200': description: Success "/api/sync/koreader/resolve": get: tags: [koreader] summary: "Resolve Book:\u003c|end|\u003e\u003c|start|\u003e assistant to=edit\u003c|channel|\u003eanalysis \u003c|constrain|\u003exml\u003c|message|\u003e\u003crfl:parameter name=\"path\"\u003e" description: 'Device token: Bearer header (KOReader) or ?token= query (Kobo/OPDS).' responses: '200': description: OK "/api/sync/koreader/review": get: tags: [koreader] summary: "Get KOReader Review" description: 'Device token: Bearer header (KOReader) or ?token= query (Kobo/OPDS).' responses: '200': description: OK post: tags: [koreader] summary: "Set KOReader Review" description: 'Device token: Bearer header (KOReader) or ?token= query (Kobo/OPDS).' requestBody: content: application/json: example: |- { "review": "A slow start, but the second act earns it." } responses: '200': description: Success "/api/sync/koreader/stats": post: tags: [koreader] summary: "Push KOReader Stats" description: 'Device token: Bearer header (KOReader) or ?token= query (Kobo/OPDS).' requestBody: content: application/json: example: |- { "total_seconds": 3600 } responses: '200': description: Success "/api/sync/unlinked-books/{id}/suggestions": get: tags: [book-matching] summary: "Get Unlinked Book Suggestions" security: - bearerAuth: [] responses: '200': description: OK "/api/system/config": get: tags: [system] summary: "Get System Configuration" security: - bearerAuth: [] responses: '200': description: OK put: tags: [system] summary: "Update System Configuration" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "base_url": "https://books.example.com", "default_timezone": "UTC" } responses: '200': description: Success "/api/system/settings": get: tags: [system] summary: "Get System Settings" security: - bearerAuth: [] responses: '200': description: OK put: tags: [system] summary: "Update System Setting" security: - bearerAuth: [] requestBody: content: application/json: example: |- { "key": "scan_poll_interval_seconds", "value": "60" } responses: '200': description: Success "/opds/devices/{deviceId}/catalog": get: tags: [opds] summary: "OPDS Feeds" description: 'Device token: Bearer header (KOReader) or ?token= query (Kobo/OPDS).' responses: '200': description: OK "/opds/devices/{deviceId}/cover/{bookId}": get: tags: [opds] summary: "OPDS Publication" description: 'Device token: Bearer header (KOReader) or ?token= query (Kobo/OPDS).' responses: '200': description: OK "/opds/devices/{deviceId}/download/{bookId}": get: tags: [opds] summary: "OPDS Acquisition" description: 'Device token: Bearer header (KOReader) or ?token= query (Kobo/OPDS).' responses: '200': description: OK