From ec74650c1822823608cdf687ff6248d5dfb395ac Mon Sep 17 00:00:00 2001 From: John O'Keefe Date: Mon, 2 Feb 2026 15:54:59 -0500 Subject: [PATCH] docs: add collections API endpoint files (Phase 2 completion) --- docs/api/collections/add_auto_assign_rule.md | 85 ++++++++++++++++ docs/api/collections/bulk_assign.md | 52 ++++++++++ docs/api/collections/create_collection.md | 96 +++++++++++++++++++ docs/api/collections/create_shelf_mapping.md | 69 +++++++++++++ docs/api/collections/delete_collection.md | 27 ++++++ docs/api/collections/delete_shelf_mapping.md | 34 +++++++ docs/api/collections/get_collection.md | 54 +++++++++++ docs/api/collections/list_collections.md | 57 +++++++++++ .../collections/remove_auto_assign_rule.md | 28 ++++++ docs/api/collections/test_rule.md | 71 ++++++++++++++ docs/api/collections/update_collection.md | 63 ++++++++++++ 11 files changed, 636 insertions(+) create mode 100644 docs/api/collections/add_auto_assign_rule.md create mode 100644 docs/api/collections/bulk_assign.md create mode 100644 docs/api/collections/create_collection.md create mode 100644 docs/api/collections/create_shelf_mapping.md create mode 100644 docs/api/collections/delete_collection.md create mode 100644 docs/api/collections/delete_shelf_mapping.md create mode 100644 docs/api/collections/get_collection.md create mode 100644 docs/api/collections/list_collections.md create mode 100644 docs/api/collections/remove_auto_assign_rule.md create mode 100644 docs/api/collections/test_rule.md create mode 100644 docs/api/collections/update_collection.md diff --git a/docs/api/collections/add_auto_assign_rule.md b/docs/api/collections/add_auto_assign_rule.md new file mode 100644 index 0000000..641019d --- /dev/null +++ b/docs/api/collections/add_auto_assign_rule.md @@ -0,0 +1,85 @@ +# Add Auto-Assign Rule + +Add an automatic book assignment rule to a collection. + +**Endpoint**: `POST /api/collections/{id}/rules` +**Auth**: Required +**Content-Type**: `application/json` + +## Path Parameters + +| Parameter | Type | Required | Description | +|-----------|------|-----------|-------------| +| id | string (UUID) | Yes | Collection UUID | + +## Request Body + +| Field | Type | Required | Description | +|--------|------|-----------|-------------| +| field | string | Yes | Field to match on (genre, author, series, language, publisher, copyright_year, tags) | +| operator | string | Yes | Comparison operator (equals, not_equals, contains, not_contains, starts_with, ends_with, greater_than, less_than) | +| value | string/number | Yes | Value to compare against | +| priority | integer | No | Rule priority (1 = highest, default: 1) | +| enabled | boolean | No | Whether rule is active (default: true) | + +### Supported Fields + +| Field | Type | Description | +|-------|------|-------------| +| genre | string | Book genre | +| author | string | Book author | +| series | string | Book series name | +| language | string | Book language | +| publisher | string | Publisher name | +| copyright_year | number | Publication year (numeric comparison) | +| tags | string | Book tags | + +### Supported Operators + +| Operator | Type | Description | +|----------|------|-------------| +| equals | all | Exact match | +| not_equals | all | Not equal | +| contains | string | Contains substring (case-insensitive) | +| not_contains | string | Does not contain | +| starts_with | string | Starts with (case-insensitive) | +| ends_with | string | Ends with (case-insensitive) | +| greater_than | number | Greater than | +| less_than | number | Less than | + +### Example Request + +```json +{ + "field": "genre", + "operator": "equals", + "value": "Science Fiction", + "priority": 1, + "enabled": true +} +``` + +## Response (201 Created) + +```json +{ + "id": "rule-uuid-here", + "field": "genre", + "operator": "equals", + "value": "Science Fiction", + "priority": 1, + "enabled": true, + "created_at": "2026-02-01T10:00:00Z" +} +``` + +## Error Responses + +| Code | Description | +|------|-------------| +| 400 | Invalid request (validation failed) | +| 401 | Authentication required | +| 404 | Collection not found | +| 500 | Internal server error | + +## Try It Out diff --git a/docs/api/collections/bulk_assign.md b/docs/api/collections/bulk_assign.md new file mode 100644 index 0000000..cb9477b --- /dev/null +++ b/docs/api/collections/bulk_assign.md @@ -0,0 +1,52 @@ +# Bulk Assign Books + +Add multiple books to a collection at once. + +**Endpoint**: `POST /api/collections/{id}/books` +**Auth**: Required +**Content-Type**: `application/json` + +## Path Parameters + +| Parameter | Type | Required | Description | +|-----------|------|-----------|-------------| +| id | string (UUID) | Yes | Collection UUID | + +## Request Body + +| Field | Type | Required | Description | +|--------|------|-----------|-------------| +| book_ids | array of UUID | Yes | Array of book IDs to add | + +### Example Request + +```json +{ + "book_ids": [ + "660e8400-e29b-41d4-a716-446655440000", + "770e8400-e29b-41d4-a716-446655440000", + "880e8400-e29b-41d4-a716-446655440000" + ] +} +``` + +## Response (204 No Content) + +Books added to collection successfully. No response body. + +## Notes + +- Books already in the collection are ignored +- This is more efficient than adding books individually +- Maximum 1000 books per request + +## Error Responses + +| Code | Description | +|------|-------------| +| 400 | Invalid request (validation failed) | +| 401 | Authentication required | +| 404 | Collection or book(s) not found | +| 500 | Internal server error | + +## Try It Out diff --git a/docs/api/collections/create_collection.md b/docs/api/collections/create_collection.md new file mode 100644 index 0000000..e0177b8 --- /dev/null +++ b/docs/api/collections/create_collection.md @@ -0,0 +1,96 @@ +# Create Collection + +Create a new collection. + +**Endpoint**: `POST /api/collections` +**Auth**: Required +**Content-Type**: `application/json` + +## Request Body + +| Field | Type | Required | Description | +|--------|------|-----------|-------------| +| name | string | Yes | Collection name (max 255 chars) | +| description | string | No | Collection description | +| color | string | No | Hex color code (e.g., "#FF5733") | +| icon | string | No | Emoji icon (e.g., "🚀", "📖") | +| auto_assign_rules | array | No | Array of rule objects | +| view_settings | object | No | Per-device display preferences | + +### Auto-Assign Rule Object + +| Field | Type | Required | Description | +|--------|------|-----------|-------------| +| field | string | Yes | Field to match on (genre, author, series, language, publisher, copyright_year, tags) | +| operator | string | Yes | Comparison operator (equals, not_equals, contains, not_contains, starts_with, ends_with, greater_than, less_than) | +| value | string/number | Yes | Value to compare against | +| priority | integer | No | Rule priority (1 = highest, default: 1) | +| enabled | boolean | No | Whether rule is active (default: true) | + +### Example Request + +```json +{ + "name": "To Read", + "description": "Books I want to read soon", + "color": "#00FF00", + "icon": "📖", + "auto_assign_rules": [ + { + "field": "tags", + "operator": "contains", + "value": "to-read", + "priority": 1, + "enabled": true + } + ], + "view_settings": { + "kobo": { + "view_mode": "grid" + }, + "koreader": { + "view_mode": "list" + } + } +} +``` + +## Response (201 Created) + +```json +{ + "id": "550e8400-e29b-41d4-a716-446655440000", + "name": "To Read", + "description": "Books I want to read soon", + "color": "#00FF00", + "icon": "📖", + "auto_assign_rules": [ + { + "field": "tags", + "operator": "contains", + "value": "to-read", + "priority": 1, + "enabled": true + } + ], + "view_settings": { + "kobo": { + "view_mode": "grid" + }, + "koreader": { + "view_mode": "list" + } + }, + "created_at": "2026-02-01T10:00:00Z" +} +``` + +## Error Responses + +| Code | Description | +|------|-------------| +| 400 | Invalid request (validation failed) | +| 401 | Authentication required | +| 500 | Internal server error | + +## Try It Out diff --git a/docs/api/collections/create_shelf_mapping.md b/docs/api/collections/create_shelf_mapping.md new file mode 100644 index 0000000..9ba0781 --- /dev/null +++ b/docs/api/collections/create_shelf_mapping.md @@ -0,0 +1,69 @@ +# Create Shelf Mapping + +Map a collection to a device shelf for syncing. + +**Endpoint**: `POST /api/devices/{deviceId}/collections` +**Auth**: Required +**Content-Type**: `application/json` + +## Path Parameters + +| Parameter | Type | Required | Description | +|-----------|------|-----------|-------------| +| deviceId | string (UUID) | Yes | Device UUID | + +## Request Body + +| Field | Type | Required | Description | +|--------|------|-----------|-------------| +| collection_id | string (UUID) | Yes | Collection UUID to map | +| device_shelf_name | string | Yes | Name of the shelf on the device | +| sync_direction | string | No | Sync direction (default: "bidirectional") | + +### Sync Directions + +| Direction | Description | +|-----------|-------------| +| bidirectional | Sync both ways between Bookhoard and device | +| book_to_hoard | Bookhoard → Device only | +| device_to_hoard | Device → Bookhoard only | +| none | No sync (mapping only for reference) | + +### Example Request + +```json +{ + "collection_id": "550e8400-e29b-41d4-a716-446655440000", + "device_shelf_name": "Sci-Fi", + "sync_direction": "bidirectional" +} +``` + +## Response (201 Created) + +```json +{ + "id": "990e8400-e29b-41d4-a716-446655440000", + "collection_id": "550e8400-e29b-41d4-a716-446655440000", + "collection_name": "Science Fiction", + "device_shelf_name": "Sci-Fi", + "sync_direction": "bidirectional", + "created_at": "2026-02-01T10:00:00Z" +} +``` + +## Use Case + +Collections can be synced to device-specific shelves (Kobo, KOReader). This allows automatic organization of books on your e-reader based on your Bookhoard collections. + +## Error Responses + +| Code | Description | +|------|-------------| +| 400 | Invalid request (validation failed) | +| 401 | Authentication required | +| 404 | Device or collection not found | +| 409 | Mapping already exists | +| 500 | Internal server error | + +## Try It Out diff --git a/docs/api/collections/delete_collection.md b/docs/api/collections/delete_collection.md new file mode 100644 index 0000000..56ec1c6 --- /dev/null +++ b/docs/api/collections/delete_collection.md @@ -0,0 +1,27 @@ +# Delete Collection + +Delete a collection. Books are NOT deleted. + +**Endpoint**: `DELETE /api/collections/{id}` +**Auth**: Required +**Content-Type**: `application/json` + +## Path Parameters + +| Parameter | Type | Required | Description | +|-----------|------|-----------|-------------| +| id | string (UUID) | Yes | Collection UUID | + +## Response (204 No Content) + +Collection deleted successfully. No response body. + +## Error Responses + +| Code | Description | +|------|-------------| +| 401 | Authentication required | +| 404 | Collection not found | +| 500 | Internal server error | + +## Try It Out diff --git a/docs/api/collections/delete_shelf_mapping.md b/docs/api/collections/delete_shelf_mapping.md new file mode 100644 index 0000000..26ef452 --- /dev/null +++ b/docs/api/collections/delete_shelf_mapping.md @@ -0,0 +1,34 @@ +# Delete Shelf Mapping + +Remove a collection-to-shelf mapping for a device. + +**Endpoint**: `DELETE /api/devices/{deviceId}/collections/{collectionId}` +**Auth**: Required +**Content-Type**: `application/json` + +## Path Parameters + +| Parameter | Type | Required | Description | +|-----------|------|-----------|-------------| +| deviceId | string (UUID) | Yes | Device UUID | +| collectionId | string (UUID) | Yes | Collection UUID | + +## Response (204 No Content) + +Shelf mapping deleted successfully. No response body. + +## Notes + +- Deleting a mapping does NOT delete the collection +- Deleting a mapping does NOT delete books from the device +- It only removes the association between the collection and device shelf + +## Error Responses + +| Code | Description | +|------|-------------| +| 401 | Authentication required | +| 404 | Device or collection not found | +| 500 | Internal server error | + +## Try It Out diff --git a/docs/api/collections/get_collection.md b/docs/api/collections/get_collection.md new file mode 100644 index 0000000..a9b6305 --- /dev/null +++ b/docs/api/collections/get_collection.md @@ -0,0 +1,54 @@ +# Get Collection + +Get single collection with all books. + +**Endpoint**: `GET /api/collections/{id}` +**Auth**: Required +**Content-Type**: `application/json` + +## Path Parameters + +| Parameter | Type | Required | Description | +|-----------|------|-----------|-------------| +| id | string (UUID) | Yes | Collection UUID | + +## Query Parameters + +| Parameter | Type | Required | Description | +|-----------|------|-----------|-------------| +| include_books | boolean | No | Include books in response (default: true) | +| limit | integer | No | Number of books to return (default: 50) | +| offset | integer | No | Number of books to skip (default: 0) | + +## Response (200 OK) + +```json +{ + "id": "550e8400-e29b-41d4-a716-446655440000", + "name": "Science Fiction", + "description": "My sci-fi collection", + "color": "#FF5733", + "icon": "🚀", + "books": [ + { + "media_item_id": "660e8400-e29b-41d4-a716-446655440000", + "title": "Foundation", + "author": "Isaac Asimov", + "cover_image_path": "/covers/foundation.jpg" + } + ], + "auto_assign_rules": [], + "view_settings": {}, + "created_at": "2026-02-01T10:00:00Z" +} +``` + +## Error Responses + +| Code | Description | +|------|-------------| +| 401 | Authentication required | +| 404 | Collection not found | +| 500 | Internal server error | + +## Try It Out diff --git a/docs/api/collections/list_collections.md b/docs/api/collections/list_collections.md new file mode 100644 index 0000000..76786a2 --- /dev/null +++ b/docs/api/collections/list_collections.md @@ -0,0 +1,57 @@ +# List Collections + +Get all collections for the authenticated user. + +**Endpoint**: `GET /api/collections` +**Auth**: Required +**Content-Type**: `application/json` + +## Query Parameters + +| Parameter | Type | Required | Description | +|-----------|------|-----------|-------------| +| limit | integer | No | Number of collections to return (default: 50) | +| offset | integer | No | Number of collections to skip (default: 0) | + +## Response (200 OK) + +```json +{ + "collections": [ + { + "id": "550e8400-e29b-41d4-a716-446655440000", + "name": "Science Fiction", + "description": "My sci-fi collection", + "color": "#FF5733", + "icon": "🚀", + "auto_assign_rules": [ + { + "field": "genre", + "operator": "equals", + "value": "Science Fiction", + "priority": 1, + "enabled": true + } + ], + "view_settings": { + "kobo": { + "view_mode": "grid", + "sort_order": "name", + "items_per_page": 24 + } + }, + "created_at": "2026-02-01T10:00:00Z" + } + ], + "total": 1 +} +``` + +## Error Responses + +| Code | Description | +|------|-------------| +| 401 | Authentication required | +| 500 | Internal server error | + +## Try It Out diff --git a/docs/api/collections/remove_auto_assign_rule.md b/docs/api/collections/remove_auto_assign_rule.md new file mode 100644 index 0000000..d52743d --- /dev/null +++ b/docs/api/collections/remove_auto_assign_rule.md @@ -0,0 +1,28 @@ +# Remove Auto-Assign Rule + +Remove an automatic book assignment rule from a collection. + +**Endpoint**: `DELETE /api/collections/{collectionId}/rules/{ruleId}` +**Auth**: Required +**Content-Type**: `application/json` + +## Path Parameters + +| Parameter | Type | Required | Description | +|-----------|------|-----------|-------------| +| collectionId | string (UUID) | Yes | Collection UUID | +| ruleId | string (UUID) | Yes | Rule UUID | + +## Response (204 No Content) + +Rule deleted successfully. No response body. + +## Error Responses + +| Code | Description | +|------|-------------| +| 401 | Authentication required | +| 404 | Collection or rule not found | +| 500 | Internal server error | + +## Try It Out diff --git a/docs/api/collections/test_rule.md b/docs/api/collections/test_rule.md new file mode 100644 index 0000000..b9126b9 --- /dev/null +++ b/docs/api/collections/test_rule.md @@ -0,0 +1,71 @@ +# Test Rule + +Test which books would match given rules without saving. + +**Endpoint**: `POST /api/collections/test-rules` +**Auth**: Required +**Content-Type**: `application/json` + +## Request Body + +| Field | Type | Required | Description | +|--------|------|-----------|-------------| +| rules | array | Yes | Array of rule objects to test | + +### Rule Object + +| Field | Type | Required | Description | +|--------|------|-----------|-------------| +| field | string | Yes | Field to match on (genre, author, series, language, publisher, copyright_year, tags) | +| operator | string | Yes | Comparison operator (equals, not_equals, contains, not_contains, starts_with, ends_with, greater_than, less_than) | +| value | string/number | Yes | Value to compare against | + +### Example Request + +```json +{ + "rules": [ + { + "field": "genre", + "operator": "equals", + "value": "Science Fiction" + }, + { + "field": "author", + "operator": "contains", + "value": "Asimov" + } + ] +} +``` + +## Response (200 OK) + +```json +{ + "matches": [ + { + "media_item_id": "660e8400-e29b-41d4-a716-446655440000", + "title": "Foundation", + "author": "Isaac Asimov", + "cover_image_path": "/covers/foundation.jpg", + "match_reason": "Matched rule: genre equals Science Fiction" + } + ], + "total": 42 +} +``` + +## Use Case + +Test rules before creating a collection to verify correct book matching. This endpoint shows which books would be added without actually modifying any collections. + +## Error Responses + +| Code | Description | +|------|-------------| +| 400 | Invalid request (validation failed) | +| 401 | Authentication required | +| 500 | Internal server error | + +## Try It Out diff --git a/docs/api/collections/update_collection.md b/docs/api/collections/update_collection.md new file mode 100644 index 0000000..2d751c7 --- /dev/null +++ b/docs/api/collections/update_collection.md @@ -0,0 +1,63 @@ +# Update Collection + +Update collection details. + +**Endpoint**: `PUT /api/collections/{id}` +**Auth**: Required +**Content-Type**: `application/json` + +## Path Parameters + +| Parameter | Type | Required | Description | +|-----------|------|-----------|-------------| +| id | string (UUID) | Yes | Collection UUID | + +## Request Body + +All fields are optional. Include only fields you want to update. + +| Field | Type | Required | Description | +|--------|------|-----------|-------------| +| name | string | No | Collection name (max 255 chars) | +| description | string | No | Collection description | +| color | string | No | Hex color code (e.g., "#FF5733") | +| icon | string | No | Emoji icon (e.g., "🚀", "📖") | +| auto_assign_rules | array | No | Array of rule objects (replaces existing rules) | +| view_settings | object | No | Per-device display preferences | + +### Example Request + +```json +{ + "name": "Sci-Fi Favorites", + "description": "Updated description", + "color": "#7aa2f7", + "icon": "🌟" +} +``` + +## Response (200 OK) + +```json +{ + "id": "550e8400-e29b-41d4-a716-446655440000", + "name": "Sci-Fi Favorites", + "description": "Updated description", + "color": "#7aa2f7", + "icon": "🌟", + "auto_assign_rules": [], + "view_settings": {}, + "created_at": "2026-02-01T10:00:00Z" +} +``` + +## Error Responses + +| Code | Description | +|------|-------------| +| 400 | Invalid request (validation failed) | +| 401 | Authentication required | +| 404 | Collection not found | +| 500 | Internal server error | + +## Try It Out