POST /api/libraries/:id/issues/:issueId/retry (admin, family-lens gated via the existing gateIssue) re-runs the work that produced an open issue — deliberately NOT a library-wide rescan. Two shapes mirror the two ledger entry kinds: - item-backed issues rescan their media item through the book-detail RescanMediaItem mechanism (self-resolving folders, multi-file audiobook routing, write-after-success guards) and then close the issue (RetryMediaItemIssue); - row-less import_failed issues re-import the single file through the watcher's standalone processMediaFile path (RetryFailedImport: folders resolved RescanMediaItem-style so paths stay library-root-relative), whose create-path self-heal plus an explicit path resolve closes the issue even when the content was already imported by a prior attempt. Failures return the REAL underlying error so the UI can show why the issue still exists; a vanished file is a 409 (ErrRetryFileMissing); already-resolved issues reject re-retry. Docs + bruno mirrors regenerated for the new route (the generator's seq renumbering touches three unrelated bruno files as fallout; openapi gains the path and the date bump), and the docs schema registry gains the retry entry so TestDocsMatchRoutes passes.
2431 lines
61 KiB
YAML
2431 lines
61 KiB
YAML
openapi: 3.0.3
|
|
info:
|
|
title: Bookhoard API
|
|
version: '2026.10.27'
|
|
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}/retry":
|
|
post:
|
|
tags: [libraries]
|
|
summary: "Retry 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
|