docs: update comprehensive API documentation and project guides

This commit updates all documentation files throughout the project:

- Updated IMPLEMENTATION_PLAN.md with new implementation details
- Updated PROJECT_GUIDELINES.md with coding standards and practices
- Updated README.md with current project information
- Updated SCREENSHOT_AUTOMATION.md with new automation details
- Added TEST_DATA.md with test fixtures data
- Updated cover_image_serving_plan.md with static URL patterns

Documentation API updates:
- Updated API reference documentation for all endpoints including:
  - Authentication (login, logout, register, refresh_token)
  - Book matching (auto_link, bulk_link, link_book, search)
  - Collections (CRUD operations, shelf mappings, auto-assign rules)
  - Conflicts (bulk operations, resolve/dismiss)
  - Devices (registration, approval, shelf management)
  - Highlights (create, update, delete, get)
  - Kobo sync (bookmark, markup, initialization, sync)
  - KOReader sync (library, metadata, bookmarks, progress)
  - Libraries (CRUD, folders, media items, stats)
  - Media items (bulk operations, CRUD)
  - Notes (CRUD operations)
  - OPDS (acquisition, feeds, publication)
  - Progress (reading progress tracking)
  - Queue (device queue management)
  - Ratings (star ratings)
  - Scanner (watch mode, scan operations)
  - Sync protocols (Kobo, KOReader)
  - Users (profile, password, admin operations)
  - WebSocket protocols

- Updated user guides (admin, dashboard, settings, sync)
- Updated device setup guides (Kobo, KOReader)
- Updated developer guides (testing, contributing, operations)
- Updated scripts/README.md
This commit is contained in:
2026-02-27 17:06:22 -05:00
parent 6562b20ee5
commit 4d321528b2
154 changed files with 2817 additions and 2152 deletions
@@ -8,9 +8,9 @@ Delete multiple media items at once (supports ebooks, comics, manga).
## Request Body
| Field | Type | Required | Description |
|--------|------|-----------|-------------|
| media_item_ids | array of UUID | Yes | Array of media item UUIDs to delete |
| Field | Type | Required | Description |
| -------------- | ------------- | -------- | ----------------------------------- |
| media_item_ids | array of UUID | Yes | Array of media item UUIDs to delete |
### Example Request
@@ -51,24 +51,24 @@ Delete multiple media items at once (supports ebooks, comics, manga).
## Response Fields
| Field | Type | Description |
|-------|------|-------------|
| results | array | Individual result for each media item |
| results[].media_item_id | string | UUID of the media item |
| results[].status | string | "success" or "error" |
| results[].error | string | Error message (only present if status is "error") |
| total | number | Total number of media items processed |
| deleted | number | Number of media items successfully deleted |
| failed | number | Number of media items that failed to delete |
| Field | Type | Description |
| ----------------------- | ------ | ------------------------------------------------- |
| results | array | Individual result for each media item |
| results[].media_item_id | string | UUID of the media item |
| results[].status | string | "success" or "error" |
| results[].error | string | Error message (only present if status is "error") |
| total | number | Total number of media items processed |
| deleted | number | Number of media items successfully deleted |
| failed | number | Number of media items that failed to delete |
## Error Responses
| Code | Description |
|------|-------------|
| 400 | Invalid request data or empty media_item_ids array |
| 401 | Invalid or expired token |
| 403 | User does not have permission |
| 500 | Server error during deletion |
| Code | Description |
| ---- | -------------------------------------------------- |
| 400 | Invalid request data or empty media_item_ids array |
| 401 | Invalid or expired token |
| 403 | User does not have permission |
| 500 | Server error during deletion |
## Notes
@@ -8,21 +8,21 @@ Update multiple media items at once (supports ebooks, comics, manga).
## Request Body
| Field | Type | Required | Description |
|--------|------|-----------|-------------|
| media_item_updates | array of objects | Yes | Array of update operations |
| media_item_updates[].media_item_id | string (UUID) | Yes | Media item UUID to update |
| media_item_updates[].updates | object | Yes | Fields to update |
| Field | Type | Required | Description |
| ---------------------------------- | ---------------- | -------- | -------------------------- |
| media_item_updates | array of objects | Yes | Array of update operations |
| media_item_updates[].media_item_id | string (UUID) | Yes | Media item UUID to update |
| media_item_updates[].updates | object | Yes | Fields to update |
### Update Fields
| Field | Type | Required | Description |
|--------|------|-----------|-------------|
| title | string | No | Updated title |
| author | string | No | Updated author |
| genre | string | No | Updated genre |
| language | string | No | Updated language (ISO 639-1 code) |
| tags | array of strings | No | Updated tags (auto-normalized) |
| Field | Type | Required | Description |
| -------- | ---------------- | -------- | --------------------------------- |
| title | string | No | Updated title |
| author | string | No | Updated author |
| genre | string | No | Updated genre |
| language | string | No | Updated language (ISO 639-1 code) |
| tags | array of strings | No | Updated tags (auto-normalized) |
### Example Request
@@ -71,15 +71,15 @@ Update multiple media items at once (supports ebooks, comics, manga).
## Response Fields
| Field | Type | Description |
|-------|------|-------------|
| results | array | Individual result for each media item |
| results[].media_item_id | string | UUID of the media item |
| results[].status | string | "success" or "error" |
| results[].error | string | Error message (only present if status is "error") |
| total | number | Total number of media items processed |
| updated | number | Number of media items successfully updated |
| failed | number | Number of media items that failed to update |
| Field | Type | Description |
| ----------------------- | ------ | ------------------------------------------------- |
| results | array | Individual result for each media item |
| results[].media_item_id | string | UUID of the media item |
| results[].status | string | "success" or "error" |
| results[].error | string | Error message (only present if status is "error") |
| total | number | Total number of media items processed |
| updated | number | Number of media items successfully updated |
| failed | number | Number of media items that failed to update |
## Tag and Contributor Normalization
@@ -90,13 +90,13 @@ The backend automatically normalizes tags:
## Error Responses
| Code | Description |
|------|-------------|
| 400 | Invalid request data or empty media_item_updates array |
| 401 | Invalid or expired token |
| 403 | User does not have permission |
| 404 | One or more media items not found |
| 500 | Server error during update |
| Code | Description |
| ---- | ------------------------------------------------------ |
| 400 | Invalid request data or empty media_item_updates array |
| 401 | Invalid or expired token |
| 403 | User does not have permission |
| 404 | One or more media items not found |
| 500 | Server error during update |
## Notes
@@ -18,31 +18,31 @@ See [Library API documentation](../libraries/) for more details.
## Request Body
| Field | Type | Required | Description |
|--------|------|-----------|-------------|
| library_id | string (UUID) | Yes | Library UUID to add the media item to |
| title | string | Yes | Media item title (1-500 characters) |
| author | string | No | Author name |
| isbn | string | No | ISBN number |
| description | string | No | Description or summary |
| file_path | string | Yes | Path to the media file |
| file_size | integer | Yes | Size of the file in bytes |
| mime_type | string | Yes | MIME type of the file |
| cover_image_path | string | No | Path to the cover image |
| series | string | No | Series name |
| series_number | integer | No | Number in the series |
| tags | array of strings | No | Tags (auto-normalized) |
| asin | string | No | Amazon ASIN |
| date_published | string | No | Publication date |
| publisher | string | No | Publisher name |
| contributors | array of strings | No | Contributors (auto-normalized) |
| Field | Type | Required | Description |
| ---------------- | ---------------- | -------- | ------------------------------------- |
| library_id | string (UUID) | Yes | Library UUID to add the media item to |
| title | string | Yes | Media item title (1-500 characters) |
| author | string | No | Author name |
| isbn | string | No | ISBN number |
| description | string | No | Description or summary |
| file_path | string | Yes | Path to the media file |
| file_size | integer | Yes | Size of the file in bytes |
| mime_type | string | Yes | MIME type of the file |
| cover_image_path | string | No | Path to the cover image |
| series | string | No | Series name |
| series_number | integer | No | Number in the series |
| tags | array of strings | No | Tags (auto-normalized) |
| asin | string | No | Amazon ASIN |
| date_published | string | No | Publication date |
| publisher | string | No | Publisher name |
| contributors | array of strings | No | Contributors (auto-normalized) |
## Tag/Contributor Normalization
Tags and contributors are automatically normalized:
- **Tags**: Titlecased, punctuation preserved, case-insensitive deduplication
- **Contributors**: Original casing and punctuation preserved, case-insensitive deduplication
- **Contributors**: Original casing and punctuation preserved, case-insensitive deduplication
- **Search fields**: Auto-generated for case-insensitive search
### Example Request
@@ -92,12 +92,12 @@ Tags and contributors are automatically normalized:
## Error Responses
| Code | Description |
|------|-------------|
| 400 | Invalid request data OR library has no folders |
| 401 | Invalid or expired token |
| 403 | User is not an admin |
| 404 | Library not found |
| Code | Description |
| ---- | ---------------------------------------------- |
| 400 | Invalid request data OR library has no folders |
| 401 | Invalid or expired token |
| 403 | User is not an admin |
| 404 | Library not found |
### 400 - Library Has No Folders
@@ -7,15 +7,15 @@ Delete a media item from the library (Admin only).
## Path Parameters
| Parameter | Type | Required | Description |
|-----------|------|-----------|-------------|
| media_id | string | Yes | Media item UUID |
| Parameter | Type | Required | Description |
| --------- | ------ | -------- | --------------- |
| media_id | string | Yes | Media item UUID |
## Request Headers
| Header | Type | Required | Description |
|--------|------|-----------|-------------|
| Authorization | string | Yes | Bearer token |
| Header | Type | Required | Description |
| ------------- | ------ | -------- | ------------ |
| Authorization | string | Yes | Bearer token |
### Example Request
@@ -30,8 +30,8 @@ Media item deleted successfully.
## Error Responses
| Code | Description |
|------|-------------|
| 401 | Invalid or expired token |
| 403 | User is not an admin |
| 404 | Media item not found |
| Code | Description |
| ---- | ------------------------ |
| 401 | Invalid or expired token |
| 403 | User is not an admin |
| 404 | Media item not found |
@@ -8,24 +8,25 @@ Download a media item file (EPUB, PDF, etc.) from the Bookhoard server.
## Path Parameters
| Parameter | Type | Required | Description |
|-----------|------|-----------|-------------|
| uuid | string | Yes | Media item UUID |
| Parameter | Type | Required | Description |
| --------- | ------ | -------- | --------------- |
| uuid | string | Yes | Media item UUID |
## Response
**Success (200 OK)**: Binary file data
**Response Headers**:
- `Content-Type`: `application/epub+zip`, `application/pdf`, or appropriate MIME type
- `Content-Disposition`: `attachment; filename="filename.epub"`
## Error Responses
| Code | Description |
|------|-------------|
| 404 | Media item not found |
| 500 | Server error during file download |
| Code | Description |
| ---- | --------------------------------- |
| 404 | Media item not found |
| 500 | Server error during file download |
## Example
@@ -8,18 +8,18 @@ Filter and sort media items with advanced criteria.
## Request Body
| Field | Type | Required | Description |
|--------|------|-----------|-------------|
| library_id | string | Yes | Library UUID |
| author_filter | string | No | Filter by author name |
| series_filter | string | No | Filter by series name |
| genre_filter | string | No | Filter by genre |
| year_min | integer | No | Minimum copyright year |
| year_max | integer | No | Maximum copyright year |
| has_cover | boolean | No | Filter by cover image existence |
| sort | string | No | Sort field and order (e.g., "title ASC", "created_at DESC") |
| limit | integer | No | Number of results (default 20) |
| offset | integer | No | Number to skip |
| Field | Type | Required | Description |
| ------------- | ------- | -------- | ----------------------------------------------------------- |
| library_id | string | Yes | Library UUID |
| author_filter | string | No | Filter by author name |
| series_filter | string | No | Filter by series name |
| genre_filter | string | No | Filter by genre |
| year_min | integer | No | Minimum copyright year |
| year_max | integer | No | Maximum copyright year |
| has_cover | boolean | No | Filter by cover image existence |
| sort | string | No | Sort field and order (e.g., "title ASC", "created_at DESC") |
| limit | integer | No | Number of results (default 20) |
| offset | integer | No | Number to skip |
### Example Request
@@ -56,8 +56,8 @@ Filter and sort media items with advanced criteria.
## Error Responses
| Code | Description |
|------|-------------|
| 400 | Invalid filter parameters |
| 401 | Invalid or expired token |
| 403 | User does not have access to this library |
| Code | Description |
| ---- | ----------------------------------------- |
| 400 | Invalid filter parameters |
| 401 | Invalid or expired token |
| 403 | User does not have access to this library |
@@ -7,15 +7,15 @@ Retrieve details of a specific media item.
## Path Parameters
| Parameter | Type | Required | Description |
|-----------|------|-----------|-------------|
| media_id | string | Yes | Media item UUID |
| Parameter | Type | Required | Description |
| --------- | ------ | -------- | --------------- |
| media_id | string | Yes | Media item UUID |
## Request Headers
| Header | Type | Required | Description |
|--------|------|-----------|-------------|
| Authorization | string | Yes | Bearer token |
| Header | Type | Required | Description |
| ------------- | ------ | -------- | ------------ |
| Authorization | string | Yes | Bearer token |
### Example Request
@@ -37,13 +37,13 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
"file_size": 1024000,
"mime_type": "application/epub+zip",
"cover_image_path": "/path/to/cover.jpg",
"series": "Series Name",
"series_number": 1,
"tags": ["sci-fi", "space opera"],
"tags_search": ["sci fi", "space opera"],
"contributors": ["Author Name", "ACME CORP."],
"contributors_search": ["author name", "acme corp"],
"language": "en",
"series": "Series Name",
"series_number": 1,
"tags": ["sci-fi", "space opera"],
"tags_search": ["sci fi", "space opera"],
"contributors": ["Author Name", "ACME CORP."],
"contributors_search": ["author name", "acme corp"],
"language": "en",
"page_count": 350,
"genre": "Science Fiction",
"copyright_year": 2023,
@@ -53,8 +53,8 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
## Error Responses
| Code | Description |
|------|-------------|
| 401 | Invalid or expired token |
| 403 | User does not have access to this media item |
| 404 | Media item not found |
| Code | Description |
| ---- | -------------------------------------------- |
| 401 | Invalid or expired token |
| 403 | User does not have access to this media item |
| 404 | Media item not found |
@@ -7,17 +7,17 @@ Retrieve a paginated list of media items from a library.
## Query Parameters
| Parameter | Type | Required | Description |
|-----------|------|-----------|-------------|
| library_id | string | Yes | Library UUID |
| limit | integer | No | Number of items to return (max 100, default 20) |
| offset | integer | No | Number of items to skip |
| Parameter | Type | Required | Description |
| ---------- | ------- | -------- | ----------------------------------------------- |
| library_id | string | Yes | Library UUID |
| limit | integer | No | Number of items to return (max 100, default 20) |
| offset | integer | No | Number of items to skip |
## Request Headers
| Header | Type | Required | Description |
|--------|------|-----------|-------------|
| Authorization | string | Yes | Bearer token |
| Header | Type | Required | Description |
| ------------- | ------ | -------- | ------------ |
| Authorization | string | Yes | Bearer token |
### Example Request
@@ -41,13 +41,13 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
"file_size": 1024000,
"mime_type": "application/epub+zip",
"cover_image_path": "/path/to/cover.jpg",
"series": "Series Name",
"series_number": 1,
"tags": ["sci-fi", "space opera"],
"tags_search": ["sci fi", "space opera"],
"contributors": ["Author Name", "ACME CORP."],
"contributors_search": ["author name", "acme corp"],
"language": "en",
"series": "Series Name",
"series_number": 1,
"tags": ["sci-fi", "space opera"],
"tags_search": ["sci fi", "space opera"],
"contributors": ["Author Name", "ACME CORP."],
"contributors_search": ["author name", "acme corp"],
"language": "en",
"page_count": 350,
"genre": "Science Fiction",
"copyright_year": 2023,
@@ -60,8 +60,8 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
## Error Responses
| Code | Description |
|------|-------------|
| 400 | Invalid query parameters |
| 401 | Invalid or expired token |
| 403 | User does not have access to this library |
| Code | Description |
| ---- | ----------------------------------------- |
| 400 | Invalid query parameters |
| 401 | Invalid or expired token |
| 403 | User does not have access to this library |
@@ -5,6 +5,7 @@ Search for media items by title, author, series, tags, or contributors.
**Note:** Search is case-insensitive and punctuation-agnostic. The search query is matched against normalized tags_search and contributors_search fields, allowing users to find matches regardless of casing or punctuation.
Examples:
- Search "acme corp" finds items with "ACME CORP." or "Acme Corp"
- Search "oreilly" finds items with "O'Reilly Media" or "OReilly Media"
- Search "science fiction" finds items with "Science-Fiction" or "science-fiction"
@@ -14,17 +15,17 @@ Examples:
## Query Parameters
| Parameter | Type | Required | Description |
|-----------|------|-----------|-------------|
| q | string | Yes | Search query (minimum 2 characters) |
| limit | integer | No | Number of results (default 20) |
| offset | integer | No | Number to skip |
| Parameter | Type | Required | Description |
| --------- | ------- | -------- | ----------------------------------- |
| q | string | Yes | Search query (minimum 2 characters) |
| limit | integer | No | Number of results (default 20) |
| offset | integer | No | Number to skip |
## Request Headers
| Header | Type | Required | Description |
|--------|------|-----------|-------------|
| Authorization | string | Yes | Bearer token |
| Header | Type | Required | Description |
| ------------- | ------ | -------- | ------------ |
| Authorization | string | Yes | Bearer token |
### Example Request
@@ -51,7 +52,7 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
## Error Responses
| Code | Description |
|------|-------------|
| 400 | Invalid search query (too short) |
| 401 | Invalid or expired token |
| Code | Description |
| ---- | -------------------------------- |
| 400 | Invalid search query (too short) |
| 401 | Invalid or expired token |
@@ -8,27 +8,28 @@ Update media item metadata (Admin only).
## Path Parameters
| Parameter | Type | Required | Description |
|-----------|------|-----------|-------------|
| media_id | string | Yes | Media item UUID |
| Parameter | Type | Required | Description |
| --------- | ------ | -------- | --------------- |
| media_id | string | Yes | Media item UUID |
## Request Body
## Request Body
| Field | Type | Required | Description |
|--------|------|-----------|-------------|
| title | string | No | Updated title |
| author | string | No | Updated author |
| description | string | No | Updated description |
| series | string | No | Series name |
| series_number | integer | No | Number in series |
| tags | array of string | No | Updated tags (auto-normalized) |
| contributors | array of string | No | Updated contributors (auto-normalized) |
**Tag/Contributor Normalization:**
- Tags are titlecased and deduplicated (case-insensitive)
- Contributors preserve original casing and punctuation
- Punctuation-preferred deduplication (keeps "ACME CORP." over "acme corp")
- Search fields auto-generated for case-insensitive search
| Field | Type | Required | Description |
| ------------- | --------------- | -------- | -------------------------------------- |
| title | string | No | Updated title |
| author | string | No | Updated author |
| description | string | No | Updated description |
| series | string | No | Series name |
| series_number | integer | No | Number in series |
| tags | array of string | No | Updated tags (auto-normalized) |
| contributors | array of string | No | Updated contributors (auto-normalized) |
**Tag/Contributor Normalization:**
- Tags are titlecased and deduplicated (case-insensitive)
- Contributors preserve original casing and punctuation
- Punctuation-preferred deduplication (keeps "ACME CORP." over "acme corp")
- Search fields auto-generated for case-insensitive search
### Example Request
@@ -58,9 +59,9 @@ Update media item metadata (Admin only).
## Error Responses
| Code | Description |
|------|-------------|
| 400 | Invalid input data |
| 401 | Invalid or expired token |
| 403 | User is not an admin |
| 404 | Media item not found |
| Code | Description |
| ---- | ------------------------ |
| 400 | Invalid input data |
| 401 | Invalid or expired token |
| 403 | User is not an admin |
| 404 | Media item not found |