Documentation updates: - Update README.md title and all references - Update PROJECT_GUIDELINES.md title and guidelines - Update all documentation files in docs/ directory - Update device setup guides (Kobo, KOReader) - Update API and architecture documentation - Update completion summaries and progress reports This is part 5 of the project rename to Bookhoard.
494 lines
10 KiB
Markdown
494 lines
10 KiB
Markdown
# Collections API Documentation
|
|
|
|
Complete API reference for collection management endpoints.
|
|
|
|
**Base Path**: `/api/collections`
|
|
|
|
---
|
|
|
|
## Overview
|
|
|
|
Collections allow you to organize your books into custom categories with:
|
|
- **Auto-assignment rules**: Automatically add books matching criteria
|
|
- **View settings**: Per-device display preferences
|
|
- **Shelf mappings**: Sync to device-specific shelves (Kobo, KOReader)
|
|
|
|
---
|
|
|
|
## Endpoints
|
|
|
|
### List All Collections
|
|
|
|
**Endpoint**: `GET /api/collections`
|
|
**Authentication**: Required
|
|
**Description**: Get all collections for the authenticated user
|
|
|
|
**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
|
|
}
|
|
```
|
|
|
|
### Create Collection
|
|
|
|
**Endpoint**: `POST /api/collections`
|
|
**Authentication**: Required
|
|
**Description**: Create a new collection
|
|
|
|
**Request Body**:
|
|
```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"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**Fields**:
|
|
- `name` (required): Collection name (max 255 chars)
|
|
- `description` (optional): Collection description
|
|
- `color` (optional): Hex color code (e.g., "#FF5733")
|
|
- `icon` (optional): Emoji icon (e.g., "🚀", "📖")
|
|
- `auto_assign_rules` (optional): Array of rule objects
|
|
- `view_settings` (optional): Per-device display preferences
|
|
|
|
**Rule Object**:
|
|
- `field`: Field to match on (genre, author, series, language, publisher, copyright_year, tags)
|
|
- `operator`: Comparison operator (equals, not_equals, contains, not_contains, starts_with, ends_with, greater_than, less_than)
|
|
- `value`: Value to compare against
|
|
- `priority`: Rule priority (1 = highest)
|
|
- `enabled`: Whether rule is active
|
|
|
|
**Response** (201 Created): Collection object
|
|
|
|
### Get Collection Details
|
|
|
|
**Endpoint**: `GET /api/collections/{id}`
|
|
**Authentication**: Required
|
|
**Description**: Get single collection with all books
|
|
|
|
**Path Parameters**:
|
|
- `id`: Collection UUID
|
|
|
|
**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"
|
|
}
|
|
```
|
|
|
|
### Update Collection
|
|
|
|
**Endpoint**: `PUT /api/collections/{id}`
|
|
**Authentication**: Required
|
|
**Description**: Update collection details
|
|
|
|
**Path Parameters**:
|
|
- `id`: Collection UUID
|
|
|
|
**Request Body**: All fields are optional
|
|
```json
|
|
{
|
|
"name": "Sci-Fi Favorites",
|
|
"description": "Updated description",
|
|
"color": "#BLUE",
|
|
"icon": "🌟"
|
|
}
|
|
```
|
|
|
|
**Response** (200 OK): Updated collection object
|
|
|
|
### Delete Collection
|
|
|
|
**Endpoint**: `DELETE /api/collections/{id}`
|
|
**Authentication**: Required
|
|
**Description**: Delete a collection (books are NOT deleted)
|
|
|
|
**Path Parameters**:
|
|
- `id`: Collection UUID
|
|
|
|
**Response** (204 No Content)
|
|
|
|
---
|
|
|
|
## Collection Books
|
|
|
|
### Add Books to Collection
|
|
|
|
**Endpoint**: `POST /api/collections/{id}/books`
|
|
**Authentication**: Required
|
|
**Description**: Add one or more books to a collection
|
|
|
|
**Path Parameters**:
|
|
- `id`: Collection UUID
|
|
|
|
**Request Body**:
|
|
```json
|
|
{
|
|
"book_ids": [
|
|
"660e8400-e29b-41d4-a716-446655440000",
|
|
"770e8400-e29b-41d4-a716-446655440000",
|
|
"880e8400-e29b-41d4-a716-446655440000"
|
|
]
|
|
}
|
|
```
|
|
|
|
**Response** (204 No Content)
|
|
|
|
### Remove Book from Collection
|
|
|
|
**Endpoint**: `DELETE /api/collections/{id}/books/{bookId}`
|
|
**Authentication**: Required
|
|
**Description**: Remove a single book from a collection
|
|
|
|
**Path Parameters**:
|
|
- `id`: Collection UUID
|
|
- `bookId`: Media Item UUID
|
|
|
|
**Response** (204 No Content)
|
|
|
|
### Bulk Remove Books
|
|
|
|
**Endpoint**: `POST /api/collections/{id}/books/bulk-remove`
|
|
**Authentication**: Required
|
|
**Description**: Remove multiple books at once (efficient)
|
|
|
|
**Path Parameters**:
|
|
- `id`: Collection UUID
|
|
|
|
**Request Body**:
|
|
```json
|
|
{
|
|
"book_ids": [
|
|
"660e8400-e29b-41d4-a716-446655440000",
|
|
"770e8400-e29b-41d4-a716-446655440000"
|
|
]
|
|
}
|
|
```
|
|
|
|
**Response** (200 OK):
|
|
```json
|
|
{
|
|
"removed": 2,
|
|
"total": 2
|
|
}
|
|
```
|
|
|
|
**Example**: Removing 2 books, both successfully removed
|
|
|
|
### Get Collection Books
|
|
|
|
**Endpoint**: `GET /api/collections/{id}/books`
|
|
**Authentication**: Required
|
|
**Description**: Get all books in a collection
|
|
|
|
**Path Parameters**:
|
|
- `id`: Collection UUID
|
|
|
|
**Query Parameters**:
|
|
- `limit` (optional): Number of books to return (default: 50)
|
|
- `offset` (optional): Number of books to skip (default: 0)
|
|
|
|
**Response** (200 OK):
|
|
```json
|
|
{
|
|
"books": [
|
|
{
|
|
"media_item_id": "660e8400-e29b-41d4-a716-446655440000",
|
|
"title": "Foundation",
|
|
"author": "Isaac Asimov",
|
|
"cover_image_path": "/covers/foundation.jpg",
|
|
"added_at": "2026-02-01T10:00:00Z"
|
|
}
|
|
],
|
|
"total": 1
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Collection Rules
|
|
|
|
### Test Collection Rules
|
|
|
|
**Endpoint**: `POST /api/collections/test-rules`
|
|
**Authentication**: Required
|
|
**Description**: Test which books would match given rules (without saving)
|
|
|
|
**Request Body**:
|
|
```json
|
|
{
|
|
"rules": [
|
|
{
|
|
"field": "genre",
|
|
"operator": "equals",
|
|
"value": "Science Fiction"
|
|
},
|
|
{
|
|
"field": "author",
|
|
"operator": "contains",
|
|
"value": "Asimov"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
**Supported Fields**:
|
|
- `genre`: Book genre
|
|
- `author`: Book author
|
|
- `series`: Book series name
|
|
- `language`: Book language
|
|
- `publisher`: Publisher name
|
|
- `copyright_year`: Publication year (numeric comparison)
|
|
- `tags`: Book tags
|
|
|
|
**Supported Operators**:
|
|
- `equals`: Exact match
|
|
- `not_equals`: Not equal
|
|
- `contains`: Contains substring (case-insensitive)
|
|
- `not_contains`: Does not contain
|
|
- `starts_with`: Starts with (case-insensitive)
|
|
- `ends_with`: Ends with (case-insensitive)
|
|
- `greater_than`: Greater than (numeric)
|
|
- `less_than`: Less than (numeric)
|
|
|
|
**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 collection to verify correct book matching
|
|
|
|
---
|
|
|
|
## Device Shelf Mappings
|
|
|
|
### Get Device Shelf Mappings
|
|
|
|
**Endpoint**: `GET /api/devices/{deviceId}/collections`
|
|
**Authentication**: Required
|
|
**Description**: Get all collection-to-shelf mappings for a device
|
|
|
|
**Path Parameters**:
|
|
- `deviceId`: Device UUID
|
|
|
|
**Response** (200 OK):
|
|
```json
|
|
{
|
|
"mappings": [
|
|
{
|
|
"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"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Create Shelf Mapping
|
|
|
|
**Endpoint**: `POST /api/devices/{deviceId}/collections`
|
|
**Authentication**: Required
|
|
**Description**: Map a collection to a device shelf
|
|
|
|
**Path Parameters**:
|
|
- `deviceId`: Device UUID
|
|
|
|
**Request Body**:
|
|
```json
|
|
{
|
|
"collection_id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"device_shelf_name": "Sci-Fi",
|
|
"sync_direction": "bidirectional"
|
|
}
|
|
```
|
|
|
|
**Sync Directions**:
|
|
- `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)
|
|
|
|
**Response** (201 Created): Mapping object
|
|
|
|
### Update Shelf Mapping
|
|
|
|
**Endpoint**: `PUT /api/devices/{deviceId}/collections/{collectionId}`
|
|
**Authentication**: Required
|
|
**Description**: Update existing shelf mapping
|
|
|
|
**Path Parameters**:
|
|
- `deviceId`: Device UUID
|
|
- `collectionId`: Collection UUID
|
|
|
|
**Request Body**:
|
|
```json
|
|
{
|
|
"device_shelf_name": "Science Fiction",
|
|
"sync_direction": "book_to_hoard"
|
|
}
|
|
```
|
|
|
|
**Response** (200 OK): Updated mapping object
|
|
|
|
### Delete Shelf Mapping
|
|
|
|
**Endpoint**: `DELETE /api/devices/{deviceId}/collections/{collectionId}`
|
|
**Authentication**: Required
|
|
**Description**: Remove shelf mapping
|
|
|
|
**Path Parameters**:
|
|
- `deviceId`: Device UUID
|
|
- `collectionId`: Collection UUID
|
|
|
|
**Response** (204 No Content)
|
|
|
|
---
|
|
|
|
## Error Responses
|
|
|
|
All endpoints may return these errors:
|
|
|
|
**400 Bad Request**:
|
|
```json
|
|
{
|
|
"error": "invalid request: validation failed"
|
|
}
|
|
```
|
|
|
|
**401 Unauthorized**:
|
|
```json
|
|
{
|
|
"error": "authentication required"
|
|
}
|
|
```
|
|
|
|
**404 Not Found**:
|
|
```json
|
|
{
|
|
"error": "collection not found"
|
|
}
|
|
```
|
|
|
|
**500 Internal Server Error**:
|
|
```json
|
|
{
|
|
"error": "internal server error"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Rate Limiting
|
|
|
|
- **Authenticated**: 100 requests per minute
|
|
- **Unauthenticated**: 10 requests per minute
|
|
|
|
Headers included:
|
|
```
|
|
X-RateLimit-Limit: 100
|
|
X-RateLimit-Remaining: 95
|
|
X-RateLimit-Reset: 1643723400
|
|
```
|
|
|
|
---
|
|
|
|
## Bruno Tests
|
|
|
|
Complete API tests available in `bruno/collections/`:
|
|
|
|
- `Get Collections.bru`
|
|
- `Create Collection.bru`
|
|
- `Get Collection.bru`
|
|
- `Update Collection.bru`
|
|
- `Delete Collection.bru`
|
|
- `Add Books to Collection.bru`
|
|
- `Remove Book from Collection.bru`
|
|
- `Get Book Collections.bru`
|
|
- `Test Collection Rules.bru`
|
|
- `Bulk Remove Books.bru`
|
|
|
|
Run tests:
|
|
```bash
|
|
bruno run bruno/collections/
|
|
```
|
|
|
|
---
|
|
|
|
**Last Updated**: 2026-02-01
|
|
**Version**: 1.0
|