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:
@@ -4,6 +4,7 @@
|
||||
> For updated, split endpoint documentation with interactive API explorer, see [API Documentation Portal](api/api-reference.md).
|
||||
>
|
||||
> **Use the split docs for:**
|
||||
>
|
||||
> - Easier navigation by category
|
||||
> - Interactive API explorer
|
||||
> - Endpoint-specific examples
|
||||
@@ -65,6 +66,7 @@ Content-Type: application/json
|
||||
```
|
||||
|
||||
**Response** (201):
|
||||
|
||||
```json
|
||||
{
|
||||
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
||||
@@ -93,6 +95,7 @@ Content-Type: application/json
|
||||
```
|
||||
|
||||
**Response** (200):
|
||||
|
||||
```json
|
||||
{
|
||||
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
||||
@@ -118,6 +121,7 @@ Content-Type: application/json
|
||||
```
|
||||
|
||||
**Response** (200):
|
||||
|
||||
```json
|
||||
{
|
||||
"token": "new-jwt-token",
|
||||
@@ -144,6 +148,7 @@ Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
**Response** (200):
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "uuid",
|
||||
@@ -219,6 +224,7 @@ Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
**Response** (200):
|
||||
|
||||
```json
|
||||
{
|
||||
"libraries": [
|
||||
@@ -290,11 +296,13 @@ Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
**Query Parameters**:
|
||||
|
||||
- `library_id` (required): UUID of library
|
||||
- `limit`: Number of items to return (max 100, default 20)
|
||||
- `offset`: Number of items to skip
|
||||
|
||||
**Response** (200):
|
||||
|
||||
```json
|
||||
{
|
||||
"media_items": [
|
||||
@@ -337,11 +345,13 @@ Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
**Query Parameters**:
|
||||
|
||||
- `q` (required): Search query (minimum 2 characters)
|
||||
- `limit`: Number of results (default 20)
|
||||
- `offset`: Number to skip
|
||||
|
||||
**Response** (200):
|
||||
|
||||
```json
|
||||
{
|
||||
"results": [
|
||||
@@ -409,6 +419,7 @@ Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
**Response** (200):
|
||||
|
||||
```json
|
||||
{
|
||||
"media_item_id": "uuid",
|
||||
@@ -452,6 +463,7 @@ Content-Type: application/json
|
||||
```
|
||||
|
||||
**Response** (200):
|
||||
|
||||
```json
|
||||
{
|
||||
"sync_status": "success",
|
||||
@@ -478,6 +490,7 @@ Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
**Response** (200):
|
||||
|
||||
```json
|
||||
{
|
||||
"notes": [
|
||||
@@ -541,6 +554,7 @@ Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
**Response** (200):
|
||||
|
||||
```json
|
||||
{
|
||||
"highlights": [
|
||||
@@ -611,6 +625,7 @@ Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
**Response** (200):
|
||||
|
||||
```json
|
||||
{
|
||||
"rating": 8,
|
||||
@@ -668,6 +683,7 @@ Content-Type: application/json
|
||||
```
|
||||
|
||||
**Response** (201):
|
||||
|
||||
```json
|
||||
{
|
||||
"device_id": "uuid",
|
||||
@@ -690,6 +706,7 @@ Content-Type: application/json
|
||||
```
|
||||
|
||||
**Response** (200):
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "pending|approved|expired",
|
||||
@@ -711,6 +728,7 @@ Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
**Response** (200):
|
||||
|
||||
```json
|
||||
{
|
||||
"devices": [
|
||||
@@ -760,10 +778,12 @@ Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
**Query Parameters**:
|
||||
|
||||
- `start_date` (optional): Start date (ISO 8601 format)
|
||||
- `end_date` (optional): End date (ISO 8601 format)
|
||||
|
||||
**Response** (200):
|
||||
|
||||
```json
|
||||
{
|
||||
"pages_read": 1250,
|
||||
@@ -782,6 +802,7 @@ Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
**Response** (200):
|
||||
|
||||
```json
|
||||
{
|
||||
"devices": [
|
||||
@@ -805,9 +826,11 @@ Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
**Query Parameters**:
|
||||
|
||||
- `limit` (optional): Number of results (default: 10)
|
||||
|
||||
**Response** (200):
|
||||
|
||||
```json
|
||||
{
|
||||
"books": [
|
||||
@@ -842,6 +865,7 @@ Content-Type: application/json
|
||||
```
|
||||
|
||||
**Response** (200):
|
||||
|
||||
```json
|
||||
{
|
||||
"matches": [
|
||||
@@ -875,6 +899,7 @@ Content-Type: application/json
|
||||
```
|
||||
|
||||
**Response** (200):
|
||||
|
||||
```json
|
||||
{
|
||||
"results": [
|
||||
@@ -904,6 +929,7 @@ Content-Type: application/json
|
||||
```
|
||||
|
||||
**Response** (200):
|
||||
|
||||
```json
|
||||
{
|
||||
"auto_linked": 15,
|
||||
@@ -927,6 +953,7 @@ Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
**Response** (200):
|
||||
|
||||
```json
|
||||
{
|
||||
"unlinked_book_id": "uuid-1",
|
||||
@@ -950,6 +977,7 @@ Authorization: Bearer <token>
|
||||
For complete collection management documentation, see **[COLLECTIONS_API.md](COLLECTIONS_API.md)**.
|
||||
|
||||
**Quick Reference**:
|
||||
|
||||
- `GET /api/collections` - List all collections
|
||||
- `POST /api/collections` - Create new collection
|
||||
- `GET /api/collections/{id}` - Get collection details
|
||||
@@ -960,6 +988,7 @@ For complete collection management documentation, see **[COLLECTIONS_API.md](COL
|
||||
- `GET /api/collections/{id}/books` - Get books in collection
|
||||
|
||||
**Features**:
|
||||
|
||||
- Auto-assign rules based on genre, author, series, tags, language, publisher, year
|
||||
- Device shelf mappings (Kobo shelves, KOReader categories)
|
||||
- Test rules before applying
|
||||
@@ -974,37 +1003,39 @@ GET /opds/devices/{deviceId}/catalog?page={page}&per_page={per_page}
|
||||
```
|
||||
|
||||
**Query Parameters**:
|
||||
|
||||
- `page` (optional): Page number (default: 1)
|
||||
- `per_page` (optional): Items per page (default: 50, max: 200)
|
||||
|
||||
**Response** (200 - OPDS 1.2 XML):
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<feed xmlns="http://www.w3.org/2005/Atom"
|
||||
<feed xmlns="http://www.w3.org/2005/Atom"
|
||||
xmlns:opds="http://opds-spec.org/2010/"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<id>urn:uuid:device-id</id>
|
||||
<title>Bookhoard Library</title>
|
||||
<updated>2026-02-01T12:00:00Z</updated>
|
||||
|
||||
|
||||
<link rel="self" href="http://localhost:8765/opds/devices/kobo-id/catalog"/>
|
||||
<link rel="search" href="http://localhost:8765/opds/devices/kobo-id/search"/>
|
||||
<link rel="start" href="http://localhost:8765/opds/devices/kobo-id/nav"/>
|
||||
|
||||
|
||||
<entry>
|
||||
<id>urn:uuid:bookhoard-uuid-123</id>
|
||||
<dc:title>The Hobbit</dc:title>
|
||||
<dc:creator>J.R.R. Tolkien</dc:creator>
|
||||
<updated>2026-02-01T10:00:00Z</updated>
|
||||
|
||||
<link href="http://localhost:8765/opds/devices/kobo-id/download/uuid-123"
|
||||
type="application/epub+zip"
|
||||
|
||||
<link href="http://localhost:8765/opds/devices/kobo-id/download/uuid-123"
|
||||
type="application/epub+zip"
|
||||
rel="http://opds-spec.org/acquisition/open-access"/>
|
||||
|
||||
<link href="http://localhost:8765/opds/devices/kobo-id/download/uuid-123?format=kepub"
|
||||
type="application/vnd.kobo+xml+zip"
|
||||
|
||||
<link href="http://localhost:8765/opds/devices/kobo-id/download/uuid-123?format=kepub"
|
||||
type="application/vnd.kobo+xml+zip"
|
||||
rel="alternate"/>
|
||||
|
||||
|
||||
<dc:identifier id="bookhoard">uuid-123</dc:identifier>
|
||||
<meta property="bookhoard:sha256">abc123...</meta>
|
||||
</entry>
|
||||
@@ -1018,9 +1049,11 @@ GET /opds/devices/{deviceId}/download/{bookId}?format={format}
|
||||
```
|
||||
|
||||
**Query Parameters**:
|
||||
|
||||
- `format` (optional): Book format - `epub` (default), `kepub`
|
||||
|
||||
**Response** (200):
|
||||
|
||||
- Headers:
|
||||
- `Content-Type`: `application/epub+zip` or `application/vnd.kobo+xml+zip`
|
||||
- `Content-Disposition`: attachment; filename="The Hobbit.epub"
|
||||
@@ -1043,6 +1076,7 @@ GET /opds/devices/{deviceId}/formats/{bookId}
|
||||
```
|
||||
|
||||
**Response** (200):
|
||||
|
||||
```json
|
||||
{
|
||||
"media_item_id": "uuid-123",
|
||||
@@ -1109,6 +1143,7 @@ Content-Type: application/json
|
||||
```
|
||||
|
||||
**Response** (202):
|
||||
|
||||
```json
|
||||
{
|
||||
"sync_status": "accepted",
|
||||
@@ -1133,6 +1168,7 @@ Authorization: Bearer <device_token>
|
||||
```
|
||||
|
||||
**Response** (200):
|
||||
|
||||
```json
|
||||
{
|
||||
"uuid": "book-uuid",
|
||||
@@ -1186,6 +1222,7 @@ Content-Type: application/json
|
||||
```
|
||||
|
||||
**Response** (200):
|
||||
|
||||
```json
|
||||
{
|
||||
"Status": "Success",
|
||||
@@ -1202,6 +1239,7 @@ Authorization: Bearer <device_token>
|
||||
```
|
||||
|
||||
**Response** (200):
|
||||
|
||||
```json
|
||||
{
|
||||
"library_sync": [
|
||||
@@ -1229,6 +1267,7 @@ Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
**Response** (200):
|
||||
|
||||
```json
|
||||
{
|
||||
"book_id": "book-uuid",
|
||||
@@ -1307,10 +1346,12 @@ Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
**Query Parameters**:
|
||||
|
||||
- `status`: "unresolved|all" (default: "unresolved")
|
||||
- `type`: "progress|note|highlight|all" (default: "all")
|
||||
|
||||
**Response** (200):
|
||||
|
||||
```json
|
||||
{
|
||||
"conflicts": [
|
||||
@@ -1373,6 +1414,7 @@ Content-Type: application/json
|
||||
```
|
||||
|
||||
**Response** (200):
|
||||
|
||||
```json
|
||||
{
|
||||
"conflict_resolved": true,
|
||||
@@ -1408,6 +1450,7 @@ Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
**Response** (200):
|
||||
|
||||
```json
|
||||
{
|
||||
"items": [
|
||||
@@ -1473,6 +1516,7 @@ Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
**Response** (200):
|
||||
|
||||
```json
|
||||
{
|
||||
"pending": 15,
|
||||
@@ -1494,6 +1538,7 @@ WS /ws/sync?token=<token>
|
||||
### Message Format
|
||||
|
||||
**Client → Server (Heartbeat)**:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "ping"
|
||||
@@ -1501,6 +1546,7 @@ WS /ws/sync?token=<token>
|
||||
```
|
||||
|
||||
**Server → Client (Progress Update)**:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "progress_update",
|
||||
@@ -1523,6 +1569,7 @@ WS /ws/sync?token=<token>
|
||||
```
|
||||
|
||||
**Server → Client (Conflict Detected)**:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "conflict",
|
||||
@@ -1536,6 +1583,7 @@ WS /ws/sync?token=<token>
|
||||
```
|
||||
|
||||
**Server → Client (Pong)**:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "pong"
|
||||
@@ -1571,16 +1619,19 @@ All endpoints return standardized error responses:
|
||||
### Rate Limiting
|
||||
|
||||
**Per-Device Limits**:
|
||||
|
||||
- Sync requests: 60/minute
|
||||
- Progress updates: 120/minute
|
||||
- Metadata requests: 30/minute
|
||||
|
||||
**Per-User Limits**:
|
||||
|
||||
- All requests: 300/minute
|
||||
- Conflict resolutions: 10/minute
|
||||
- Device registrations: 5/hour
|
||||
|
||||
**Rate Limit Headers**:
|
||||
|
||||
```
|
||||
X-RateLimit-Limit: 60
|
||||
X-RateLimit-Remaining: 45
|
||||
@@ -1612,16 +1663,19 @@ bruno/
|
||||
## Testing with Bruno OpenCollection YAML
|
||||
|
||||
Install Bruno CLI:
|
||||
|
||||
```bash
|
||||
npm install -g @usebruno/cli
|
||||
```
|
||||
|
||||
Run all tests:
|
||||
|
||||
```bash
|
||||
bruno run
|
||||
```
|
||||
|
||||
Run specific collection:
|
||||
|
||||
```bash
|
||||
bruno run bruno/devices/
|
||||
```
|
||||
|
||||
@@ -7,17 +7,17 @@ List all users in the system (admin only).
|
||||
|
||||
## Query Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| limit | integer | No | Maximum number of users to return (default: 50) |
|
||||
| offset | integer | No | Number of users to skip (default: 0) |
|
||||
| search | string | No | Search by email or username |
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ------- | -------- | ----------------------------------------------- |
|
||||
| limit | integer | No | Maximum number of users to return (default: 50) |
|
||||
| offset | integer | No | Number of users to skip (default: 0) |
|
||||
| search | string | No | Search by email or username |
|
||||
|
||||
## Request Headers
|
||||
|
||||
| Header | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| Authorization | string | Yes | Bearer token (must have admin role) |
|
||||
| Header | Type | Required | Description |
|
||||
| ------------- | ------ | -------- | ----------------------------------- |
|
||||
| Authorization | string | Yes | Bearer token (must have admin role) |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -53,26 +53,26 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
|
||||
### Response Fields
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `id` | string | User ID (UUID) |
|
||||
| `email` | string | Email address |
|
||||
| `username` | string | Username |
|
||||
| `first_name` | string | First name (optional) |
|
||||
| `last_name` | string | Last name (optional) |
|
||||
| `role` | string | User role (`"user"` or `"admin"`) |
|
||||
| `theme` | string | Theme preference (optional) |
|
||||
| `max_devices` | integer | Maximum number of devices allowed |
|
||||
| `device_count` | integer | Current number of registered devices |
|
||||
| `created_at` | string | Account creation timestamp (ISO 8601) |
|
||||
| `updated_at` | string | Last update timestamp (ISO 8601) |
|
||||
| `total` | integer | Total number of users matching query |
|
||||
| `limit` | integer | Limit applied to this request |
|
||||
| `offset` | integer | Offset applied to this request |
|
||||
| Field | Type | Description |
|
||||
| -------------- | ------- | ------------------------------------- |
|
||||
| `id` | string | User ID (UUID) |
|
||||
| `email` | string | Email address |
|
||||
| `username` | string | Username |
|
||||
| `first_name` | string | First name (optional) |
|
||||
| `last_name` | string | Last name (optional) |
|
||||
| `role` | string | User role (`"user"` or `"admin"`) |
|
||||
| `theme` | string | Theme preference (optional) |
|
||||
| `max_devices` | integer | Maximum number of devices allowed |
|
||||
| `device_count` | integer | Current number of registered devices |
|
||||
| `created_at` | string | Account creation timestamp (ISO 8601) |
|
||||
| `updated_at` | string | Last update timestamp (ISO 8601) |
|
||||
| `total` | integer | Total number of users matching query |
|
||||
| `limit` | integer | Limit applied to this request |
|
||||
| `offset` | integer | Offset applied to this request |
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | User does not have admin privileges |
|
||||
| Code | Description |
|
||||
| ---- | ----------------------------------- |
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | User does not have admin privileges |
|
||||
|
||||
@@ -8,15 +8,15 @@ Update the maximum number of devices a user can register (admin only).
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| id | string (UUID) | Yes | User UUID |
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ------------- | -------- | ----------- |
|
||||
| id | string (UUID) | Yes | User UUID |
|
||||
|
||||
## Request Body
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| max_devices | integer | Yes | Maximum number of devices (1-100) |
|
||||
| Field | Type | Required | Description |
|
||||
| ----------- | ------- | -------- | --------------------------------- |
|
||||
| max_devices | integer | Yes | Maximum number of devices (1-100) |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -41,9 +41,9 @@ Update the maximum number of devices a user can register (admin only).
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 400 | Invalid max_devices value (must be 1-100) |
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | User does not have admin privileges |
|
||||
| 404 | User not found |
|
||||
| Code | Description |
|
||||
| ---- | ----------------------------------------- |
|
||||
| 400 | Invalid max_devices value (must be 1-100) |
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | User does not have admin privileges |
|
||||
| 404 | User not found |
|
||||
|
||||
@@ -7,16 +7,16 @@ Retrieve reading statistics for a date range.
|
||||
|
||||
## Query Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| start_date | string | No | Start date (ISO 8601 format) |
|
||||
| end_date | string | No | End date (ISO 8601 format) |
|
||||
| Parameter | Type | Required | Description |
|
||||
| ---------- | ------ | -------- | ---------------------------- |
|
||||
| start_date | string | No | Start date (ISO 8601 format) |
|
||||
| end_date | string | No | End date (ISO 8601 format) |
|
||||
|
||||
## Request Headers
|
||||
|
||||
| Header | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| Authorization | string | Yes | Bearer token |
|
||||
| Header | Type | Required | Description |
|
||||
| ------------- | ------ | -------- | ------------ |
|
||||
| Authorization | string | Yes | Bearer token |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -39,7 +39,7 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 400 | Invalid date format |
|
||||
| 401 | Invalid or expired token |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------ |
|
||||
| 400 | Invalid date format |
|
||||
| 401 | Invalid or expired token |
|
||||
|
||||
@@ -255,7 +255,7 @@ See [WebSocket API](websocket/)
|
||||
## Documentation
|
||||
|
||||
- GET /docs - Documentation home
|
||||
- GET /docs/* - Show documentation pages
|
||||
- GET /docs/\* - Show documentation pages
|
||||
- GET /docs/api/search - Search API documentation
|
||||
- GET /docs/search-index.json - Search index for documentation search
|
||||
|
||||
|
||||
@@ -8,10 +8,10 @@ Authenticate with email and password.
|
||||
|
||||
## Request Body
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| login | string | Yes | User's email address or username |
|
||||
| password | string | Yes | User's password |
|
||||
| Field | Type | Required | Description |
|
||||
| -------- | ------ | -------- | -------------------------------- |
|
||||
| login | string | Yes | User's email address or username |
|
||||
| password | string | Yes | User's password |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -42,6 +42,7 @@ Authenticate with email and password.
|
||||
```
|
||||
|
||||
**Set-Cookie Header**:
|
||||
|
||||
```
|
||||
Set-Cookie: token=eyJhbG...; Max-Age=604800; Path=/; HttpOnly
|
||||
```
|
||||
@@ -50,8 +51,8 @@ Set-Cookie: token=eyJhbG...; Max-Age=604800; Path=/; HttpOnly
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Invalid email or password |
|
||||
| 400 | Missing required fields |
|
||||
| 429 | Too many login attempts |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------- |
|
||||
| 401 | Invalid email or password |
|
||||
| 400 | Missing required fields |
|
||||
| 429 | Too many login attempts |
|
||||
|
||||
@@ -8,9 +8,9 @@ Invalidate the current JWT token.
|
||||
|
||||
## Request Headers
|
||||
|
||||
| Header | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| Authorization | string | Yes | Bearer token (e.g., `Bearer eyJhbG...`) |
|
||||
| Header | Type | Required | Description |
|
||||
| ------------- | ------ | -------- | --------------------------------------- |
|
||||
| Authorization | string | Yes | Bearer token (e.g., `Bearer eyJhbG...`) |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -25,7 +25,7 @@ No response body.
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | Token already invalidated |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------- |
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | Token already invalidated |
|
||||
|
||||
@@ -42,6 +42,7 @@ When a user registers or logs in:
|
||||
4. Server returns JSON response with both tokens and user profile
|
||||
|
||||
**Request**:
|
||||
|
||||
```json
|
||||
POST /api/auth/login
|
||||
{
|
||||
@@ -51,6 +52,7 @@ POST /api/auth/login
|
||||
```
|
||||
|
||||
**Response**:
|
||||
|
||||
```json
|
||||
{
|
||||
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
||||
@@ -67,6 +69,7 @@ POST /api/auth/login
|
||||
```
|
||||
|
||||
**Set-Cookie Header**:
|
||||
|
||||
```
|
||||
Set-Cookie: token=eyJhbG...; Max-Age=604800; Path=/; HttpOnly
|
||||
```
|
||||
@@ -94,6 +97,7 @@ POST /api/auth/refresh
|
||||
```
|
||||
|
||||
**Response**:
|
||||
|
||||
```json
|
||||
{
|
||||
"access_token": "new-jwt-token",
|
||||
@@ -135,6 +139,7 @@ When an API call receives a 401 Unauthorized response:
|
||||
```
|
||||
|
||||
The frontend toast.js interceptor:
|
||||
|
||||
1. Clears invalid tokens from localStorage
|
||||
2. Shows an error toast notification
|
||||
3. Allows user to re-authenticate
|
||||
@@ -149,10 +154,12 @@ The frontend toast.js interceptor:
|
||||
## Token Storage Recommendations
|
||||
|
||||
### Browser Applications
|
||||
|
||||
- **Backend**: Automatically manages HTTP-only cookie
|
||||
- **Frontend**: Store tokens in localStorage for API calls
|
||||
|
||||
### Mobile Applications
|
||||
|
||||
- Store access token in secure storage (Keychain/Keystore)
|
||||
- Store refresh token in secure storage
|
||||
- Handle 401 responses by prompting user to re-authenticate
|
||||
@@ -160,6 +167,7 @@ The frontend toast.js interceptor:
|
||||
## Constants Reference
|
||||
|
||||
All session durations use constants defined in:
|
||||
|
||||
- `internal/handlers/auth.go` - SessionDuration, SessionDurationSec
|
||||
- `internal/handlers/refresh_token.go` - SessionDurationSec (mirrored)
|
||||
|
||||
|
||||
@@ -8,9 +8,9 @@ Obtain a new JWT access token using a refresh token.
|
||||
|
||||
## Request Body
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| refresh_token | string | Yes | Valid refresh token (UUID) |
|
||||
| Field | Type | Required | Description |
|
||||
| ------------- | ------ | -------- | -------------------------- |
|
||||
| refresh_token | string | Yes | Valid refresh token (UUID) |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -36,7 +36,7 @@ The new access token is valid for 7 days from the time of refresh.
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Invalid or expired refresh token |
|
||||
| 400 | Missing refresh token or invalid format |
|
||||
| Code | Description |
|
||||
| ---- | --------------------------------------- |
|
||||
| 401 | Invalid or expired refresh token |
|
||||
| 400 | Missing refresh token or invalid format |
|
||||
|
||||
@@ -8,13 +8,13 @@ Create a new user account.
|
||||
|
||||
## Request Body
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| email | string | Yes | User's email address |
|
||||
| username | string | Yes | Desired username (3-50 chars) |
|
||||
| password | string | Yes | Password (min 8 chars, must meet complexity requirements) |
|
||||
| first_name | string | No | User's first name |
|
||||
| last_name | string | No | User's last name |
|
||||
| Field | Type | Required | Description |
|
||||
| ---------- | ------ | -------- | --------------------------------------------------------- |
|
||||
| email | string | Yes | User's email address |
|
||||
| username | string | Yes | Desired username (3-50 chars) |
|
||||
| password | string | Yes | Password (min 8 chars, must meet complexity requirements) |
|
||||
| first_name | string | No | User's first name |
|
||||
| last_name | string | No | User's last name |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -50,6 +50,7 @@ Create a new user account.
|
||||
```
|
||||
|
||||
**Set-Cookie Header**:
|
||||
|
||||
```
|
||||
Set-Cookie: token=eyJhbG...; Max-Age=604800; Path=/; HttpOnly
|
||||
```
|
||||
@@ -60,7 +61,7 @@ Set-Cookie: token=eyJhbG...; Max-Age=604800; Path=/; HttpOnly
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 400 | Invalid email format, weak password, or missing fields |
|
||||
| 409 | Email or username already exists |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------------------------------------ |
|
||||
| 400 | Invalid email format, weak password, or missing fields |
|
||||
| 409 | Email or username already exists |
|
||||
|
||||
@@ -8,10 +8,10 @@ Automatically link books to media items based on matching metadata.
|
||||
|
||||
## Request Body
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| device_id | string (UUID) | Yes | Device UUID |
|
||||
| threshold | float | No | Match confidence threshold (0.0-1.0, default: 0.7) |
|
||||
| Field | Type | Required | Description |
|
||||
| --------- | ------------- | -------- | -------------------------------------------------- |
|
||||
| device_id | string (UUID) | Yes | Device UUID |
|
||||
| threshold | float | No | Match confidence threshold (0.0-1.0, default: 0.7) |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -41,8 +41,8 @@ Automatically link books to media items based on matching metadata.
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 400 | Invalid request data |
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Device not found |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------ |
|
||||
| 400 | Invalid request data |
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Device not found |
|
||||
|
||||
@@ -8,9 +8,9 @@ Link multiple books to media items at once.
|
||||
|
||||
## Request Body
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| links | array | Yes | Array of book-media link objects |
|
||||
| Field | Type | Required | Description |
|
||||
| ----- | ----- | -------- | -------------------------------- |
|
||||
| links | array | Yes | Array of book-media link objects |
|
||||
|
||||
Each link object contains:
|
||||
| Field | Type | Required | Description |
|
||||
@@ -50,8 +50,8 @@ Each link object contains:
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 400 | Invalid request data |
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Device, book, or media item not found |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------------------- |
|
||||
| 400 | Invalid request data |
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Device, book, or media item not found |
|
||||
|
||||
@@ -8,17 +8,17 @@ Create a new file alias for a device.
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| id | string (UUID) | Yes | Device UUID |
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ------------- | -------- | ----------- |
|
||||
| id | string (UUID) | Yes | Device UUID |
|
||||
|
||||
## Request Body
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| media_item_id | string (UUID) | Yes | Media item UUID |
|
||||
| file_name | string | Yes | Name of the file |
|
||||
| file_hash | string | No | SHA256 hash of the file (optional) |
|
||||
| Field | Type | Required | Description |
|
||||
| ------------- | ------------- | -------- | ---------------------------------- |
|
||||
| media_item_id | string (UUID) | Yes | Media item UUID |
|
||||
| file_name | string | Yes | Name of the file |
|
||||
| file_hash | string | No | SHA256 hash of the file (optional) |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -45,9 +45,9 @@ Create a new file alias for a device.
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 400 | Invalid request data |
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Device or media item not found |
|
||||
| 409 | File alias already exists |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------------ |
|
||||
| 400 | Invalid request data |
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Device or media item not found |
|
||||
| 409 | File alias already exists |
|
||||
|
||||
@@ -7,16 +7,16 @@ Delete a device file alias.
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| id | string (UUID) | Yes | Device UUID |
|
||||
| aliasId | string (UUID) | Yes | File alias UUID |
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ------------- | -------- | --------------- |
|
||||
| id | string (UUID) | Yes | Device UUID |
|
||||
| aliasId | string (UUID) | Yes | File alias UUID |
|
||||
|
||||
## Request Headers
|
||||
|
||||
| Header | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| Authorization | string | Yes | Bearer token |
|
||||
| Header | Type | Required | Description |
|
||||
| ------------- | ------ | -------- | ------------ |
|
||||
| Authorization | string | Yes | Bearer token |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -31,7 +31,7 @@ File alias deleted successfully.
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Device or file alias not found |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------------ |
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Device or file alias not found |
|
||||
|
||||
@@ -7,16 +7,16 @@ Get potential book matches for a given query.
|
||||
|
||||
## Query Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| q | string | Yes | Search query (title, author, etc.) |
|
||||
| limit | integer | No | Maximum number of matches to return (default: 10) |
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ------- | -------- | ------------------------------------------------- |
|
||||
| q | string | Yes | Search query (title, author, etc.) |
|
||||
| limit | integer | No | Maximum number of matches to return (default: 10) |
|
||||
|
||||
## Request Headers
|
||||
|
||||
| Header | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| Authorization | string | Yes | Bearer token |
|
||||
| Header | Type | Required | Description |
|
||||
| ------------- | ------ | -------- | ------------ |
|
||||
| Authorization | string | Yes | Bearer token |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -46,7 +46,7 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 400 | Missing required query parameter |
|
||||
| 401 | Invalid or expired token |
|
||||
| Code | Description |
|
||||
| ---- | -------------------------------- |
|
||||
| 400 | Missing required query parameter |
|
||||
| 401 | Invalid or expired token |
|
||||
|
||||
@@ -7,15 +7,15 @@ Get all file aliases for a specific device.
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| id | string (UUID) | Yes | Device UUID |
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ------------- | -------- | ----------- |
|
||||
| id | string (UUID) | Yes | Device UUID |
|
||||
|
||||
## Request Headers
|
||||
|
||||
| Header | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| Authorization | string | Yes | Bearer token |
|
||||
| Header | Type | Required | Description |
|
||||
| ------------- | ------ | -------- | ------------ |
|
||||
| Authorization | string | Yes | Bearer token |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -44,7 +44,7 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Device not found |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------ |
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Device not found |
|
||||
|
||||
@@ -7,22 +7,22 @@ Get suggested matches for unlinked books on a device.
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| id | string (UUID) | Yes | Device UUID |
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ------------- | -------- | ----------- |
|
||||
| id | string (UUID) | Yes | Device UUID |
|
||||
|
||||
## Query Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| limit | integer | No | Maximum number of suggestions per book (default: 5) |
|
||||
| threshold | float | No | Minimum confidence threshold (default: 0.5) |
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ------- | -------- | --------------------------------------------------- |
|
||||
| limit | integer | No | Maximum number of suggestions per book (default: 5) |
|
||||
| threshold | float | No | Minimum confidence threshold (default: 0.5) |
|
||||
|
||||
## Request Headers
|
||||
|
||||
| Header | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| Authorization | string | Yes | Bearer token |
|
||||
| Header | Type | Required | Description |
|
||||
| ------------- | ------ | -------- | ------------ |
|
||||
| Authorization | string | Yes | Bearer token |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -61,7 +61,7 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Device not found |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------ |
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Device not found |
|
||||
|
||||
@@ -7,22 +7,22 @@ Get all books that haven't been linked to media items yet for a specific device.
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| deviceId | string (UUID) | Yes | Device UUID |
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ------------- | -------- | ----------- |
|
||||
| deviceId | string (UUID) | Yes | Device UUID |
|
||||
|
||||
## Query Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| limit | integer | No | Maximum number of items to return (default: 50) |
|
||||
| offset | integer | No | Number of items to skip (default: 0) |
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ------- | -------- | ----------------------------------------------- |
|
||||
| limit | integer | No | Maximum number of items to return (default: 50) |
|
||||
| offset | integer | No | Number of items to skip (default: 0) |
|
||||
|
||||
## Request Headers
|
||||
|
||||
| Header | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| Authorization | string | Yes | Bearer token |
|
||||
| Header | Type | Required | Description |
|
||||
| ------------- | ------ | -------- | ------------ |
|
||||
| Authorization | string | Yes | Bearer token |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -52,7 +52,7 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Device not found |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------ |
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Device not found |
|
||||
|
||||
@@ -8,12 +8,12 @@ Link a device book to a Bookhoard media item. Supports bulk linking.
|
||||
|
||||
## Manual Link Request Body
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| links | array | Yes | List of book links |
|
||||
| links[].unlinked_book_id | string | Yes | Device book UUID |
|
||||
| links[].media_item_id | string | Yes | Bookhoard media item UUID |
|
||||
| links[].confidence_score | float | No | Match confidence (0-1) |
|
||||
| Field | Type | Required | Description |
|
||||
| ------------------------ | ------ | -------- | ------------------------- |
|
||||
| links | array | Yes | List of book links |
|
||||
| links[].unlinked_book_id | string | Yes | Device book UUID |
|
||||
| links[].media_item_id | string | Yes | Bookhoard media item UUID |
|
||||
| links[].confidence_score | float | No | Match confidence (0-1) |
|
||||
|
||||
### Example Manual Link Request
|
||||
|
||||
@@ -31,10 +31,10 @@ Link a device book to a Bookhoard media item. Supports bulk linking.
|
||||
|
||||
## Auto-Link Request Body
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| confidence_threshold | float | No | Minimum confidence for auto-link (default: 0.8) |
|
||||
| limit | integer | No | Maximum books to auto-link (default: 50) |
|
||||
| Field | Type | Required | Description |
|
||||
| -------------------- | ------- | -------- | ----------------------------------------------- |
|
||||
| confidence_threshold | float | No | Minimum confidence for auto-link (default: 0.8) |
|
||||
| limit | integer | No | Maximum books to auto-link (default: 50) |
|
||||
|
||||
### Example Auto-Link Request
|
||||
|
||||
@@ -81,8 +81,8 @@ Link a device book to a Bookhoard media item. Supports bulk linking.
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 400 | Invalid link data |
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Media item not found |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------ |
|
||||
| 400 | Invalid link data |
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Media item not found |
|
||||
|
||||
@@ -8,13 +8,13 @@ Query books to find potential matches for linking.
|
||||
|
||||
## Request Body
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| identifiers | array | No | List of identifiers (ISBN, UUID) |
|
||||
| sha256 | string | No | SHA256 hash of book file |
|
||||
| title | string | No | Book title |
|
||||
| author | string | No | Book author |
|
||||
| file_size | integer | No | File size in bytes |
|
||||
| Field | Type | Required | Description |
|
||||
| ----------- | ------- | -------- | -------------------------------- |
|
||||
| identifiers | array | No | List of identifiers (ISBN, UUID) |
|
||||
| sha256 | string | No | SHA256 hash of book file |
|
||||
| title | string | No | Book title |
|
||||
| author | string | No | Book author |
|
||||
| file_size | integer | No | File size in bytes |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -46,7 +46,7 @@ Query books to find potential matches for linking.
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 400 | Invalid query parameters |
|
||||
| 401 | Invalid or expired token |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------ |
|
||||
| 400 | Invalid query parameters |
|
||||
| 401 | Invalid or expired token |
|
||||
|
||||
@@ -8,17 +8,17 @@ Update an existing device file alias.
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| id | string (UUID) | Yes | Device UUID |
|
||||
| aliasId | string (UUID) | Yes | File alias UUID |
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ------------- | -------- | --------------- |
|
||||
| id | string (UUID) | Yes | Device UUID |
|
||||
| aliasId | string (UUID) | Yes | File alias UUID |
|
||||
|
||||
## Request Body
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| file_name | string | No | New file name |
|
||||
| file_hash | string | No | New file hash |
|
||||
| Field | Type | Required | Description |
|
||||
| --------- | ------ | -------- | ------------- |
|
||||
| file_name | string | No | New file name |
|
||||
| file_hash | string | No | New file hash |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -44,8 +44,8 @@ Update an existing device file alias.
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 400 | Invalid request data |
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Device or file alias not found |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------------ |
|
||||
| 400 | Invalid request data |
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Device or file alias not found |
|
||||
|
||||
@@ -8,44 +8,44 @@ Add an automatic book assignment rule to a collection.
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| id | string (UUID) | Yes | Collection UUID |
|
||||
| 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) |
|
||||
| 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 |
|
||||
| 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 |
|
||||
| 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 |
|
||||
| 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
|
||||
|
||||
@@ -75,11 +75,11 @@ Add an automatic book assignment rule to a collection.
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 400 | Invalid request (validation failed) |
|
||||
| 401 | Authentication required |
|
||||
| 404 | Collection not found |
|
||||
| 500 | Internal server error |
|
||||
| Code | Description |
|
||||
| ---- | ----------------------------------- |
|
||||
| 400 | Invalid request (validation failed) |
|
||||
| 401 | Authentication required |
|
||||
| 404 | Collection not found |
|
||||
| 500 | Internal server error |
|
||||
|
||||
## Try It Out
|
||||
|
||||
@@ -8,15 +8,15 @@ Add multiple books to a collection at once.
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| id | string (UUID) | Yes | Collection UUID |
|
||||
| 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 |
|
||||
| Field | Type | Required | Description |
|
||||
| -------- | ------------- | -------- | ------------------------ |
|
||||
| book_ids | array of UUID | Yes | Array of book IDs to add |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -42,11 +42,11 @@ Books added to collection successfully. No response body.
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 400 | Invalid request (validation failed) |
|
||||
| 401 | Authentication required |
|
||||
| 404 | Collection or book(s) not found |
|
||||
| 500 | Internal server error |
|
||||
| Code | Description |
|
||||
| ---- | ----------------------------------- |
|
||||
| 400 | Invalid request (validation failed) |
|
||||
| 401 | Authentication required |
|
||||
| 404 | Collection or book(s) not found |
|
||||
| 500 | Internal server error |
|
||||
|
||||
## Try It Out
|
||||
|
||||
@@ -8,24 +8,24 @@ Create a new collection.
|
||||
|
||||
## 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 |
|
||||
| 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) |
|
||||
| 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
|
||||
|
||||
@@ -87,10 +87,10 @@ Create a new collection.
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 400 | Invalid request (validation failed) |
|
||||
| 401 | Authentication required |
|
||||
| 500 | Internal server error |
|
||||
| Code | Description |
|
||||
| ---- | ----------------------------------- |
|
||||
| 400 | Invalid request (validation failed) |
|
||||
| 401 | Authentication required |
|
||||
| 500 | Internal server error |
|
||||
|
||||
## Try It Out
|
||||
|
||||
@@ -8,26 +8,26 @@ Map a collection to a device shelf for syncing.
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| deviceId | string (UUID) | Yes | Device UUID |
|
||||
| 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") |
|
||||
| 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) |
|
||||
| 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
|
||||
|
||||
@@ -58,12 +58,12 @@ Collections can be synced to device-specific shelves (Kobo, KOReader). This allo
|
||||
|
||||
## 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 |
|
||||
| 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
|
||||
|
||||
@@ -8,9 +8,9 @@ Delete a collection. Books are NOT deleted.
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| id | string (UUID) | Yes | Collection UUID |
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ------------- | -------- | --------------- |
|
||||
| id | string (UUID) | Yes | Collection UUID |
|
||||
|
||||
## Response (204 No Content)
|
||||
|
||||
@@ -18,10 +18,10 @@ Collection deleted successfully. No response body.
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Authentication required |
|
||||
| 404 | Collection not found |
|
||||
| 500 | Internal server error |
|
||||
| Code | Description |
|
||||
| ---- | ----------------------- |
|
||||
| 401 | Authentication required |
|
||||
| 404 | Collection not found |
|
||||
| 500 | Internal server error |
|
||||
|
||||
## Try It Out
|
||||
|
||||
@@ -8,10 +8,10 @@ Remove a collection-to-shelf mapping for a device.
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| deviceId | string (UUID) | Yes | Device UUID |
|
||||
| collectionId | string (UUID) | Yes | Collection UUID |
|
||||
| Parameter | Type | Required | Description |
|
||||
| ------------ | ------------- | -------- | --------------- |
|
||||
| deviceId | string (UUID) | Yes | Device UUID |
|
||||
| collectionId | string (UUID) | Yes | Collection UUID |
|
||||
|
||||
## Response (204 No Content)
|
||||
|
||||
@@ -25,10 +25,10 @@ Shelf mapping deleted successfully. No response body.
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Authentication required |
|
||||
| 404 | Device or collection not found |
|
||||
| 500 | Internal server error |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------------ |
|
||||
| 401 | Authentication required |
|
||||
| 404 | Device or collection not found |
|
||||
| 500 | Internal server error |
|
||||
|
||||
## Try It Out
|
||||
|
||||
@@ -8,17 +8,17 @@ Get single collection with all books.
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| id | string (UUID) | Yes | Collection UUID |
|
||||
| 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) |
|
||||
| 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)
|
||||
|
||||
@@ -45,10 +45,10 @@ Get single collection with all books.
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Authentication required |
|
||||
| 404 | Collection not found |
|
||||
| 500 | Internal server error |
|
||||
| Code | Description |
|
||||
| ---- | ----------------------- |
|
||||
| 401 | Authentication required |
|
||||
| 404 | Collection not found |
|
||||
| 500 | Internal server error |
|
||||
|
||||
## Try It Out
|
||||
|
||||
@@ -8,10 +8,10 @@ Get all collections for the authenticated user.
|
||||
|
||||
## 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) |
|
||||
| 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)
|
||||
|
||||
@@ -49,9 +49,9 @@ Get all collections for the authenticated user.
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Authentication required |
|
||||
| 500 | Internal server error |
|
||||
| Code | Description |
|
||||
| ---- | ----------------------- |
|
||||
| 401 | Authentication required |
|
||||
| 500 | Internal server error |
|
||||
|
||||
## Try It Out
|
||||
|
||||
@@ -8,10 +8,10 @@ Remove an automatic book assignment rule from a collection.
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| collectionId | string (UUID) | Yes | Collection UUID |
|
||||
| ruleId | string (UUID) | Yes | Rule UUID |
|
||||
| Parameter | Type | Required | Description |
|
||||
| ------------ | ------------- | -------- | --------------- |
|
||||
| collectionId | string (UUID) | Yes | Collection UUID |
|
||||
| ruleId | string (UUID) | Yes | Rule UUID |
|
||||
|
||||
## Response (204 No Content)
|
||||
|
||||
@@ -19,10 +19,10 @@ Rule deleted successfully. No response body.
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Authentication required |
|
||||
| 404 | Collection or rule not found |
|
||||
| 500 | Internal server error |
|
||||
| Code | Description |
|
||||
| ---- | ---------------------------- |
|
||||
| 401 | Authentication required |
|
||||
| 404 | Collection or rule not found |
|
||||
| 500 | Internal server error |
|
||||
|
||||
## Try It Out
|
||||
|
||||
@@ -8,17 +8,17 @@ Test which books would match given rules without saving.
|
||||
|
||||
## Request Body
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| rules | array | Yes | Array of rule objects to test |
|
||||
| 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 |
|
||||
| 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
|
||||
|
||||
@@ -62,10 +62,10 @@ Test rules before creating a collection to verify correct book matching. This en
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 400 | Invalid request (validation failed) |
|
||||
| 401 | Authentication required |
|
||||
| 500 | Internal server error |
|
||||
| Code | Description |
|
||||
| ---- | ----------------------------------- |
|
||||
| 400 | Invalid request (validation failed) |
|
||||
| 401 | Authentication required |
|
||||
| 500 | Internal server error |
|
||||
|
||||
## Try It Out
|
||||
|
||||
@@ -8,22 +8,22 @@ Update collection details.
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| id | string (UUID) | Yes | Collection UUID |
|
||||
| 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 |
|
||||
| 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
|
||||
|
||||
@@ -53,11 +53,11 @@ All fields are optional. Include only fields you want to update.
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 400 | Invalid request (validation failed) |
|
||||
| 401 | Authentication required |
|
||||
| 404 | Collection not found |
|
||||
| 500 | Internal server error |
|
||||
| Code | Description |
|
||||
| ---- | ----------------------------------- |
|
||||
| 400 | Invalid request (validation failed) |
|
||||
| 401 | Authentication required |
|
||||
| 404 | Collection not found |
|
||||
| 500 | Internal server error |
|
||||
|
||||
## Try It Out
|
||||
|
||||
@@ -8,9 +8,9 @@ Dismiss multiple conflicts at once.
|
||||
|
||||
## Request Body
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| conflict_ids | array of UUID | Yes | Array of conflict UUIDs to dismiss |
|
||||
| Field | Type | Required | Description |
|
||||
| ------------ | ------------- | -------- | ---------------------------------- |
|
||||
| conflict_ids | array of UUID | Yes | Array of conflict UUIDs to dismiss |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -34,7 +34,7 @@ Dismiss multiple conflicts at once.
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 400 | Invalid request body |
|
||||
| 401 | Invalid or expired token |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------ |
|
||||
| 400 | Invalid request body |
|
||||
| 401 | Invalid or expired token |
|
||||
|
||||
@@ -8,10 +8,10 @@ Resolve multiple conflicts at once using a specified strategy.
|
||||
|
||||
## Request Body
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| conflict_ids | array of UUID | Yes | Array of conflict UUIDs to resolve |
|
||||
| resolution | string | Yes | Resolution strategy: "device", "server", or "highest_progress" |
|
||||
| Field | Type | Required | Description |
|
||||
| ------------ | ------------- | -------- | -------------------------------------------------------------- |
|
||||
| conflict_ids | array of UUID | Yes | Array of conflict UUIDs to resolve |
|
||||
| resolution | string | Yes | Resolution strategy: "device", "server", or "highest_progress" |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -37,8 +37,8 @@ Resolve multiple conflicts at once using a specified strategy.
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 400 | Invalid request body |
|
||||
| 401 | Invalid or expired token |
|
||||
| 400 | Invalid resolution strategy |
|
||||
| Code | Description |
|
||||
| ---- | --------------------------- |
|
||||
| 400 | Invalid request body |
|
||||
| 401 | Invalid or expired token |
|
||||
| 400 | Invalid resolution strategy |
|
||||
|
||||
@@ -7,15 +7,15 @@ Delete a specific conflict record.
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| id | string (UUID) | Yes | Conflict UUID |
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ------------- | -------- | ------------- |
|
||||
| id | string (UUID) | Yes | Conflict UUID |
|
||||
|
||||
## Request Headers
|
||||
|
||||
| Header | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| Authorization | string | Yes | Bearer token |
|
||||
| Header | Type | Required | Description |
|
||||
| ------------- | ------ | -------- | ------------ |
|
||||
| Authorization | string | Yes | Bearer token |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -30,7 +30,7 @@ Conflict deleted successfully.
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Conflict not found |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------ |
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Conflict not found |
|
||||
|
||||
@@ -7,9 +7,9 @@ Dismiss all resolved conflicts.
|
||||
|
||||
## Request Headers
|
||||
|
||||
| Header | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| Authorization | string | Yes | Bearer token |
|
||||
| Header | Type | Required | Description |
|
||||
| ------------- | ------ | -------- | ------------ |
|
||||
| Authorization | string | Yes | Bearer token |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -29,6 +29,6 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Invalid or expired token |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------ |
|
||||
| 401 | Invalid or expired token |
|
||||
|
||||
@@ -7,15 +7,15 @@ Get detailed information about a specific conflict.
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| id | string (UUID) | Yes | Conflict UUID |
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ------------- | -------- | ------------- |
|
||||
| id | string (UUID) | Yes | Conflict UUID |
|
||||
|
||||
## Request Headers
|
||||
|
||||
| Header | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| Authorization | string | Yes | Bearer token |
|
||||
| Header | Type | Required | Description |
|
||||
| ------------- | ------ | -------- | ------------ |
|
||||
| Authorization | string | Yes | Bearer token |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -69,7 +69,7 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Conflict not found |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------ |
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Conflict not found |
|
||||
|
||||
@@ -7,18 +7,18 @@ List all sync conflicts for the current user.
|
||||
|
||||
## Query Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| status | string | No | Filter by status (active, resolved, dismissed) |
|
||||
| media_item_id | string (UUID) | No | Filter by media item |
|
||||
| limit | integer | No | Maximum number of conflicts to return (default: 50) |
|
||||
| offset | integer | No | Number of conflicts to skip (default: 0) |
|
||||
| Parameter | Type | Required | Description |
|
||||
| ------------- | ------------- | -------- | --------------------------------------------------- |
|
||||
| status | string | No | Filter by status (active, resolved, dismissed) |
|
||||
| media_item_id | string (UUID) | No | Filter by media item |
|
||||
| limit | integer | No | Maximum number of conflicts to return (default: 50) |
|
||||
| offset | integer | No | Number of conflicts to skip (default: 0) |
|
||||
|
||||
## Request Headers
|
||||
|
||||
| Header | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| Authorization | string | Yes | Bearer token |
|
||||
| Header | Type | Required | Description |
|
||||
| ------------- | ------ | -------- | ------------ |
|
||||
| Authorization | string | Yes | Bearer token |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -60,6 +60,6 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Invalid or expired token |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------ |
|
||||
| 401 | Invalid or expired token |
|
||||
|
||||
@@ -8,15 +8,15 @@ Resolve a specific conflict by choosing which version to keep.
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| id | string (UUID) | Yes | Conflict UUID |
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ------------- | -------- | ------------- |
|
||||
| id | string (UUID) | Yes | Conflict UUID |
|
||||
|
||||
## Request Body
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| resolution | string | Yes | Resolution strategy: "device", "server", or "highest_progress" |
|
||||
| Field | Type | Required | Description |
|
||||
| ---------- | ------ | -------- | -------------------------------------------------------------- |
|
||||
| resolution | string | Yes | Resolution strategy: "device", "server", or "highest_progress" |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -38,9 +38,9 @@ Resolve a specific conflict by choosing which version to keep.
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 400 | Invalid resolution strategy |
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Conflict not found |
|
||||
| 400 | Conflict already resolved |
|
||||
| Code | Description |
|
||||
| ---- | --------------------------- |
|
||||
| 400 | Invalid resolution strategy |
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Conflict not found |
|
||||
| 400 | Conflict already resolved |
|
||||
|
||||
@@ -9,6 +9,7 @@ Evaluates filter rules and returns matching items without saving the collection.
|
||||
**Endpoint:** `POST /api/collections/preview`
|
||||
|
||||
**Request Body:**
|
||||
|
||||
```json
|
||||
{
|
||||
"library_id": "uuid",
|
||||
@@ -28,23 +29,24 @@ Evaluates filter rules and returns matching items without saving the collection.
|
||||
|
||||
**Available Filter Fields:**
|
||||
|
||||
| Field | Type | Operators |
|
||||
|-------|------|-----------|
|
||||
| `title` | text | contains, equals, starts_with, ends_with, regex |
|
||||
| `author` | text | contains, equals |
|
||||
| `genre` | select | equals, not_equals, in, not_in |
|
||||
| `series` | text | is_set, is_not_set, equals, contains |
|
||||
| `progress` | number | equals, not_equals, greater_than, less_than, between, is_set, is_not_set |
|
||||
| `rating` | number | equals, not_equals, greater_than, less_than, is_set, is_not_set |
|
||||
| `date_added` | date | equals, not_equals, before, after, between, last_x_days |
|
||||
| `last_read` | date | equals, before, after, between, last_x_days, is_set, is_not_set |
|
||||
| `publisher` | text | contains, equals |
|
||||
| `language` | select | equals, not_equals, in |
|
||||
| `format` | select | equals, in |
|
||||
| `tags` | text | contains, not_contains, equals |
|
||||
| `narrators` | text | contains, equals, is_set, is_not_set |
|
||||
| Field | Type | Operators |
|
||||
| ------------ | ------ | ------------------------------------------------------------------------ |
|
||||
| `title` | text | contains, equals, starts_with, ends_with, regex |
|
||||
| `author` | text | contains, equals |
|
||||
| `genre` | select | equals, not_equals, in, not_in |
|
||||
| `series` | text | is_set, is_not_set, equals, contains |
|
||||
| `progress` | number | equals, not_equals, greater_than, less_than, between, is_set, is_not_set |
|
||||
| `rating` | number | equals, not_equals, greater_than, less_than, is_set, is_not_set |
|
||||
| `date_added` | date | equals, not_equals, before, after, between, last_x_days |
|
||||
| `last_read` | date | equals, before, after, between, last_x_days, is_set, is_not_set |
|
||||
| `publisher` | text | contains, equals |
|
||||
| `language` | select | equals, not_equals, in |
|
||||
| `format` | select | equals, in |
|
||||
| `tags` | text | contains, not_contains, equals |
|
||||
| `narrators` | text | contains, equals, is_set, is_not_set |
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"items": [
|
||||
@@ -65,6 +67,7 @@ Creates a new custom collection with filter rules and/or manual book selection.
|
||||
**Endpoint:** `POST /api/collections`
|
||||
|
||||
**Request Body:**
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "My Custom Section",
|
||||
@@ -89,6 +92,7 @@ Creates a new custom collection with filter rules and/or manual book selection.
|
||||
**TypeScript:** `web/src/custom-section-builder.ts`
|
||||
|
||||
Key features:
|
||||
|
||||
- 14 filter fields with various operators
|
||||
- Live preview functionality
|
||||
- Search + multi-select for manual book addition
|
||||
@@ -97,6 +101,7 @@ Key features:
|
||||
## Example Use Cases
|
||||
|
||||
### Sci-Fi Favorites
|
||||
|
||||
```json
|
||||
{
|
||||
"rules": [
|
||||
@@ -110,6 +115,7 @@ Key features:
|
||||
```
|
||||
|
||||
### High Rated Books
|
||||
|
||||
```json
|
||||
{
|
||||
"rules": [
|
||||
@@ -123,6 +129,7 @@ Key features:
|
||||
```
|
||||
|
||||
### Long Books (Manual Selection)
|
||||
|
||||
```json
|
||||
{
|
||||
"manual_book_ids": ["uuid1", "uuid2", "uuid3"]
|
||||
@@ -130,6 +137,7 @@ Key features:
|
||||
```
|
||||
|
||||
### Recently Finished Audiobooks
|
||||
|
||||
```json
|
||||
{
|
||||
"rules": [
|
||||
|
||||
@@ -10,26 +10,27 @@ Retrieve all dashboard sections for a specific library, including system collect
|
||||
|
||||
### Query Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|--------|----------|-----------------------------------------------|
|
||||
| library_id| string | Yes | Library UUID to fetch sections for |
|
||||
| limit | number | No | Items per section (default: 20, max: 100) |
|
||||
| Parameter | Type | Required | Description |
|
||||
| ---------- | ------ | -------- | ----------------------------------------- |
|
||||
| library_id | string | Yes | Library UUID to fetch sections for |
|
||||
| limit | number | No | Items per section (default: 20, max: 100) |
|
||||
|
||||
### Response
|
||||
|
||||
Returns array of sections in user's customized order (respects `collection_order` and `hidden_collections` preferences).
|
||||
|
||||
**Section Types**:
|
||||
|
||||
- `is_system: true`: System collections (4 pre-seeded defaults)
|
||||
- `is_system: false`: User-created collections with `show_on_dashboard: true`
|
||||
|
||||
**System Collections**:
|
||||
| ID | Title | Icon | Description |
|
||||
| ID | Title | Icon | Description |
|
||||
|-----------------|------------------|------|--------------------------------------------------|
|
||||
| continue-reading| Continue Reading | 📖 | Books with progress > 0% and < 100% |
|
||||
| recently-added | Recently Added | 🆕 | Newest items in library |
|
||||
| recently-read | Recently Read | ✅ | Books with progress = 100% |
|
||||
| not-started | Not Started | 📕 | Books with no reading progress |
|
||||
| continue-reading| Continue Reading | 📖 | Books with progress > 0% and < 100% |
|
||||
| recently-added | Recently Added | 🆕 | Newest items in library |
|
||||
| recently-read | Recently Read | ✅ | Books with progress = 100% |
|
||||
| not-started | Not Started | 📕 | Books with no reading progress |
|
||||
|
||||
### Example Response
|
||||
|
||||
@@ -115,6 +116,7 @@ Reset a system collection to its default state (removes user customizations).
|
||||
```
|
||||
|
||||
Valid `collection_name` values:
|
||||
|
||||
- `continue-reading`
|
||||
- `recently-added`
|
||||
- `recently-read`
|
||||
@@ -130,12 +132,12 @@ Valid `collection_name` values:
|
||||
|
||||
### Error Responses
|
||||
|
||||
| Status | Description |
|
||||
|--------|--------------------------------|
|
||||
| 400 | Missing library_id |
|
||||
| 400 | Invalid library_id |
|
||||
| 400 | Invalid collection_name |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Failed to load sections |
|
||||
| 500 | Failed to save preferences |
|
||||
| 500 | Failed to restore collection |
|
||||
| Status | Description |
|
||||
| ------ | ---------------------------- |
|
||||
| 400 | Missing library_id |
|
||||
| 400 | Invalid library_id |
|
||||
| 400 | Invalid collection_name |
|
||||
| 401 | Unauthorized |
|
||||
| 500 | Failed to load sections |
|
||||
| 500 | Failed to save preferences |
|
||||
| 500 | Failed to restore collection |
|
||||
|
||||
@@ -8,15 +8,15 @@ Add a media item to a device's shelf (Kobo reading shelf).
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| id | string (UUID) | Yes | Device UUID |
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ------------- | -------- | ----------- |
|
||||
| id | string (UUID) | Yes | Device UUID |
|
||||
|
||||
## Request Body
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| media_item_id | string (UUID) | Yes | Media item UUID to add to shelf |
|
||||
| Field | Type | Required | Description |
|
||||
| ------------- | ------------- | -------- | ------------------------------- |
|
||||
| media_item_id | string (UUID) | Yes | Media item UUID to add to shelf |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -38,9 +38,9 @@ Add a media item to a device's shelf (Kobo reading shelf).
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 400 | Invalid request data |
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Device or media item not found |
|
||||
| 409 | Item already on shelf |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------------ |
|
||||
| 400 | Invalid request data |
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Device or media item not found |
|
||||
| 409 | Item already on shelf |
|
||||
|
||||
@@ -7,15 +7,15 @@ Approve a pending device registration request.
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| registration_id | string (UUID) | Yes | Registration request UUID |
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------------- | ------------- | -------- | ------------------------- |
|
||||
| registration_id | string (UUID) | Yes | Registration request UUID |
|
||||
|
||||
## Request Headers
|
||||
|
||||
| Header | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| Authorization | string | Yes | Bearer token (must have admin role) |
|
||||
| Header | Type | Required | Description |
|
||||
| ------------- | ------ | -------- | ----------------------------------- |
|
||||
| Authorization | string | Yes | Bearer token (must have admin role) |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -30,7 +30,7 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
{
|
||||
"message": "device approved successfully",
|
||||
"device_name": "string",
|
||||
"device_type": "string",
|
||||
"device_type": "string",
|
||||
"registration_id": "uuid",
|
||||
"approved": true
|
||||
}
|
||||
@@ -38,9 +38,9 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | User does not have admin privileges |
|
||||
| 404 | Registration not found |
|
||||
| 400 | Registration already processed |
|
||||
| Code | Description |
|
||||
| ---- | ----------------------------------- |
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | User does not have admin privileges |
|
||||
| 404 | Registration not found |
|
||||
| 400 | Registration already processed |
|
||||
|
||||
@@ -7,15 +7,15 @@ Remove all items from a device's shelf.
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| id | string (UUID) | Yes | Device UUID |
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ------------- | -------- | ----------- |
|
||||
| id | string (UUID) | Yes | Device UUID |
|
||||
|
||||
## Request Headers
|
||||
|
||||
| Header | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| Authorization | string | Yes | Bearer token |
|
||||
| Header | Type | Required | Description |
|
||||
| ------------- | ------ | -------- | ------------ |
|
||||
| Authorization | string | Yes | Bearer token |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -30,7 +30,7 @@ Shelf cleared successfully.
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Device not found |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------ |
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Device not found |
|
||||
|
||||
@@ -7,15 +7,15 @@ Delete a device and revoke its access.
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| id | string (UUID) | Yes | Device UUID |
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ------------- | -------- | ----------- |
|
||||
| id | string (UUID) | Yes | Device 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 @@ Device deleted successfully.
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | Device does not belong to user |
|
||||
| 404 | Device not found |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------------ |
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | Device does not belong to user |
|
||||
| 404 | Device not found |
|
||||
|
||||
@@ -8,9 +8,9 @@ Check device registration status or get device details.
|
||||
|
||||
## Request Body (Status Check)
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| registration_id | string | Yes | Registration UUID |
|
||||
| Field | Type | Required | Description |
|
||||
| --------------- | ------ | -------- | ----------------- |
|
||||
| registration_id | string | Yes | Registration UUID |
|
||||
|
||||
### Example Request (Status Check)
|
||||
|
||||
@@ -52,7 +52,7 @@ Check device registration status or get device details.
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Invalid or expired token (for device details) |
|
||||
| 404 | Device or registration not found |
|
||||
| Code | Description |
|
||||
| ---- | --------------------------------------------- |
|
||||
| 401 | Invalid or expired token (for device details) |
|
||||
| 404 | Device or registration not found |
|
||||
|
||||
@@ -7,15 +7,15 @@ Get all items on a device's shelf.
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| id | string (UUID) | Yes | Device UUID |
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ------------- | -------- | ----------- |
|
||||
| id | string (UUID) | Yes | Device UUID |
|
||||
|
||||
## Request Headers
|
||||
|
||||
| Header | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| Authorization | string | Yes | Bearer token |
|
||||
| Header | Type | Required | Description |
|
||||
| ------------- | ------ | -------- | ------------ |
|
||||
| Authorization | string | Yes | Bearer token |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -44,7 +44,7 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Device not found |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------ |
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Device not found |
|
||||
|
||||
@@ -7,9 +7,9 @@ Retrieve all devices registered to the current user.
|
||||
|
||||
## Request Headers
|
||||
|
||||
| Header | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| Authorization | string | Yes | Bearer token |
|
||||
| Header | Type | Required | Description |
|
||||
| ------------- | ------ | -------- | ------------ |
|
||||
| Authorization | string | Yes | Bearer token |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -39,6 +39,6 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Invalid or expired token |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------ |
|
||||
| 401 | Invalid or expired token |
|
||||
|
||||
@@ -7,9 +7,9 @@ List all pending device registration requests.
|
||||
|
||||
## Request Headers
|
||||
|
||||
| Header | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| Authorization | string | Yes | Bearer token (must have admin role) |
|
||||
| Header | Type | Required | Description |
|
||||
| ------------- | ------ | -------- | ----------------------------------- |
|
||||
| Authorization | string | Yes | Bearer token (must have admin role) |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -37,7 +37,7 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | User does not have admin privileges |
|
||||
| Code | Description |
|
||||
| ---- | ----------------------------------- |
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | User does not have admin privileges |
|
||||
|
||||
@@ -8,11 +8,11 @@ Register a new device for sync.
|
||||
|
||||
## Request Body
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| device_name | string | Yes | Device name |
|
||||
| device_type | string | Yes | Device type: kobo, koreader, web, mobile |
|
||||
| device_identifier | string | Yes | Hardware-specific ID |
|
||||
| Field | Type | Required | Description |
|
||||
| ----------------- | ------ | -------- | ---------------------------------------- |
|
||||
| device_name | string | Yes | Device name |
|
||||
| device_type | string | Yes | Device type: kobo, koreader, web, mobile |
|
||||
| device_identifier | string | Yes | Hardware-specific ID |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -38,7 +38,7 @@ Register a new device for sync.
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 400 | Invalid device data |
|
||||
| 409 | Device already registered |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------- |
|
||||
| 400 | Invalid device data |
|
||||
| 409 | Device already registered |
|
||||
|
||||
@@ -7,15 +7,15 @@ Reject a pending device registration request.
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| registration_id | string (UUID) | Yes | Registration request UUID |
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------------- | ------------- | -------- | ------------------------- |
|
||||
| registration_id | string (UUID) | Yes | Registration request UUID |
|
||||
|
||||
## Request Headers
|
||||
|
||||
| Header | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| Authorization | string | Yes | Bearer token (must have admin role) |
|
||||
| Header | Type | Required | Description |
|
||||
| ------------- | ------ | -------- | ----------------------------------- |
|
||||
| Authorization | string | Yes | Bearer token (must have admin role) |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -34,9 +34,9 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | User does not have admin privileges |
|
||||
| 404 | Registration not found |
|
||||
| 400 | Registration already processed |
|
||||
| Code | Description |
|
||||
| ---- | ----------------------------------- |
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | User does not have admin privileges |
|
||||
| 404 | Registration not found |
|
||||
| 400 | Registration already processed |
|
||||
|
||||
@@ -8,15 +8,15 @@ Remove a media item from a device's shelf.
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| id | string (UUID) | Yes | Device UUID |
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ------------- | -------- | ----------- |
|
||||
| id | string (UUID) | Yes | Device UUID |
|
||||
|
||||
## Request Body
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| media_item_id | string (UUID) | Yes | Media item UUID to remove from shelf |
|
||||
| Field | Type | Required | Description |
|
||||
| ------------- | ------------- | -------- | ------------------------------------ |
|
||||
| media_item_id | string (UUID) | Yes | Media item UUID to remove from shelf |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -32,8 +32,8 @@ Item removed from shelf successfully.
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 400 | Invalid request data |
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Device or shelf item not found |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------------ |
|
||||
| 400 | Invalid request data |
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Device or shelf item not found |
|
||||
|
||||
@@ -7,15 +7,15 @@ Revoke access to a device.
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| device_id | string | Yes | Device UUID |
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ------ | -------- | ----------- |
|
||||
| device_id | string | Yes | Device 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 @@ Device revoked successfully.
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | User does not own this device |
|
||||
| 404 | Device not found |
|
||||
| Code | Description |
|
||||
| ---- | ----------------------------- |
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | User does not own this device |
|
||||
| 404 | Device not found |
|
||||
|
||||
@@ -8,16 +8,16 @@ Update a device's information.
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| id | string (UUID) | Yes | Device UUID |
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ------------- | -------- | ----------- |
|
||||
| id | string (UUID) | Yes | Device UUID |
|
||||
|
||||
## Request Body
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| name | string | No | Device display name |
|
||||
| device_type | string | No | Device type (kobo, koreader, etc.) |
|
||||
| Field | Type | Required | Description |
|
||||
| ----------- | ------ | -------- | ---------------------------------- |
|
||||
| name | string | No | Device display name |
|
||||
| device_type | string | No | Device type (kobo, koreader, etc.) |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -44,9 +44,9 @@ Update a device's information.
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 400 | Invalid request data |
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | Device does not belong to user |
|
||||
| 404 | Device not found |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------------ |
|
||||
| 400 | Invalid request data |
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | Device does not belong to user |
|
||||
| 404 | Device not found |
|
||||
|
||||
@@ -8,20 +8,20 @@ Create a new highlight for a 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 Body
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| selection_text | string | Yes | Highlighted text |
|
||||
| start_position | string | No | Start position (e.g., epubcfi) |
|
||||
| end_position | string | No | End position (e.g., epubcfi) |
|
||||
| color | string | No | Highlight color (hex, default: "#ffff00") |
|
||||
| percentage_start | float | No | Start percentage (0-1) |
|
||||
| percentage_end | float | No | End percentage (0-1) |
|
||||
| Field | Type | Required | Description |
|
||||
| ---------------- | ------ | -------- | ----------------------------------------- |
|
||||
| selection_text | string | Yes | Highlighted text |
|
||||
| start_position | string | No | Start position (e.g., epubcfi) |
|
||||
| end_position | string | No | End position (e.g., epubcfi) |
|
||||
| color | string | No | Highlight color (hex, default: "#ffff00") |
|
||||
| percentage_start | float | No | Start percentage (0-1) |
|
||||
| percentage_end | float | No | End percentage (0-1) |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -55,8 +55,8 @@ Create a new highlight for a media item.
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 400 | Invalid highlight data |
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Media item not found |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------ |
|
||||
| 400 | Invalid highlight data |
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Media item not found |
|
||||
|
||||
@@ -7,15 +7,15 @@ Delete a highlight.
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| highlight_id | string | Yes | Highlight UUID |
|
||||
| Parameter | Type | Required | Description |
|
||||
| ------------ | ------ | -------- | -------------- |
|
||||
| highlight_id | string | Yes | Highlight 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 @@ Highlight deleted successfully.
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | User does not own this highlight |
|
||||
| 404 | Highlight not found |
|
||||
| Code | Description |
|
||||
| ---- | -------------------------------- |
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | User does not own this highlight |
|
||||
| 404 | Highlight not found |
|
||||
|
||||
@@ -7,15 +7,15 @@ Retrieve all highlights for 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
|
||||
|
||||
@@ -51,7 +51,7 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Media item not found |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------ |
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Media item not found |
|
||||
|
||||
@@ -8,16 +8,16 @@ Update an existing highlight.
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| highlight_id | string | Yes | Highlight UUID |
|
||||
| Parameter | Type | Required | Description |
|
||||
| ------------ | ------ | -------- | -------------- |
|
||||
| highlight_id | string | Yes | Highlight UUID |
|
||||
|
||||
## Request Body
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| selection_text | string | No | Updated highlighted text |
|
||||
| color | string | No | Updated highlight color (hex) |
|
||||
| Field | Type | Required | Description |
|
||||
| -------------- | ------ | -------- | ----------------------------- |
|
||||
| selection_text | string | No | Updated highlighted text |
|
||||
| color | string | No | Updated highlight color (hex) |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -43,9 +43,9 @@ Update an existing highlight.
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 400 | Invalid highlight data |
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | User does not own this highlight |
|
||||
| 404 | Highlight not found |
|
||||
| Code | Description |
|
||||
| ---- | -------------------------------- |
|
||||
| 400 | Invalid highlight data |
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | User does not own this highlight |
|
||||
| 404 | Highlight not found |
|
||||
|
||||
@@ -11,9 +11,9 @@ This endpoint requires device authentication (not user JWT). This is a Kobo comp
|
||||
|
||||
## Request Body
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| (varies) | object | No | Kobo analytics data (format varies) |
|
||||
| Field | Type | Required | Description |
|
||||
| -------- | ------ | -------- | ----------------------------------- |
|
||||
| (varies) | object | No | Kobo analytics data (format varies) |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -33,9 +33,9 @@ This endpoint requires device authentication (not user JWT). This is a Kobo comp
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Device authentication failed |
|
||||
| Code | Description |
|
||||
| ---- | ---------------------------- |
|
||||
| 401 | Device authentication failed |
|
||||
|
||||
## Notes
|
||||
|
||||
|
||||
@@ -11,19 +11,19 @@ This endpoint requires device authentication (not user JWT). Kobo devices authen
|
||||
|
||||
## Request Body
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| bookmarks | array | Yes | Array of bookmark objects |
|
||||
| Field | Type | Required | Description |
|
||||
| --------- | ----- | -------- | ------------------------- |
|
||||
| bookmarks | array | Yes | Array of bookmark objects |
|
||||
|
||||
### Bookmark Object
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| BookmarkID | string | Yes | Unique bookmark ID |
|
||||
| ContentID | string | Yes | Book content ID |
|
||||
| StartPosition | integer | Yes | Bookmark position |
|
||||
| Text | string | No | Bookmark text |
|
||||
| DateCreated | string | Yes | ISO 8601 timestamp |
|
||||
| Field | Type | Required | Description |
|
||||
| ------------- | ------- | -------- | ------------------ |
|
||||
| BookmarkID | string | Yes | Unique bookmark ID |
|
||||
| ContentID | string | Yes | Book content ID |
|
||||
| StartPosition | integer | Yes | Bookmark position |
|
||||
| Text | string | No | Bookmark text |
|
||||
| DateCreated | string | Yes | ISO 8601 timestamp |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -52,8 +52,8 @@ This endpoint requires device authentication (not user JWT). Kobo devices authen
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Device authentication failed |
|
||||
| 400 | Invalid request data |
|
||||
| 404 | Device or book not found |
|
||||
| Code | Description |
|
||||
| ---- | ---------------------------- |
|
||||
| 401 | Device authentication failed |
|
||||
| 400 | Invalid request data |
|
||||
| 404 | Device or book not found |
|
||||
|
||||
@@ -11,11 +11,11 @@ This endpoint requires device authentication (not user JWT). Kobo devices authen
|
||||
|
||||
## Request Headers
|
||||
|
||||
| Header | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| X-Device-ID | string | Yes | Device UUID |
|
||||
| X-Device-Key | string | Yes | Device authentication key |
|
||||
| X-Kobo-UserKey | string | No | Kobo user key (if available) |
|
||||
| Header | Type | Required | Description |
|
||||
| -------------- | ------ | -------- | ---------------------------- |
|
||||
| X-Device-ID | string | Yes | Device UUID |
|
||||
| X-Device-Key | string | Yes | Device authentication key |
|
||||
| X-Kobo-UserKey | string | No | Kobo user key (if available) |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -39,10 +39,10 @@ X-Device-Key: device-auth-key
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Device authentication failed |
|
||||
| 404 | Device not found |
|
||||
| Code | Description |
|
||||
| ---- | ---------------------------- |
|
||||
| 401 | Device authentication failed |
|
||||
| 404 | Device not found |
|
||||
|
||||
## Notes
|
||||
|
||||
|
||||
@@ -11,23 +11,23 @@ This endpoint requires device authentication (not user JWT). Kobo devices authen
|
||||
|
||||
## Request Body
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| bookmarks | array | Yes | Array of bookmark/markup objects |
|
||||
| Field | Type | Required | Description |
|
||||
| --------- | ----- | -------- | -------------------------------- |
|
||||
| bookmarks | array | Yes | Array of bookmark/markup objects |
|
||||
|
||||
### Bookmark Object
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| BookmarkID | string | Yes | Unique bookmark ID |
|
||||
| ContentID | string | Yes | Book content ID |
|
||||
| StartPosition | integer | Yes | Highlight start position |
|
||||
| EndPosition | integer | No | Highlight end position |
|
||||
| Text | string | No | Highlighted text |
|
||||
| Annotation | string | No | User annotation |
|
||||
| DateCreated | string | Yes | ISO 8601 timestamp |
|
||||
| Chapter | string | No | Chapter title |
|
||||
| Hidden | boolean | No | Whether bookmark is hidden |
|
||||
| Field | Type | Required | Description |
|
||||
| ------------- | ------- | -------- | -------------------------- |
|
||||
| BookmarkID | string | Yes | Unique bookmark ID |
|
||||
| ContentID | string | Yes | Book content ID |
|
||||
| StartPosition | integer | Yes | Highlight start position |
|
||||
| EndPosition | integer | No | Highlight end position |
|
||||
| Text | string | No | Highlighted text |
|
||||
| Annotation | string | No | User annotation |
|
||||
| DateCreated | string | Yes | ISO 8601 timestamp |
|
||||
| Chapter | string | No | Chapter title |
|
||||
| Hidden | boolean | No | Whether bookmark is hidden |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -60,8 +60,8 @@ This endpoint requires device authentication (not user JWT). Kobo devices authen
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Device authentication failed |
|
||||
| 400 | Invalid request data |
|
||||
| 404 | Device or book not found |
|
||||
| Code | Description |
|
||||
| ---- | ---------------------------- |
|
||||
| 401 | Device authentication failed |
|
||||
| 400 | Invalid request data |
|
||||
| 404 | Device or book not found |
|
||||
|
||||
@@ -11,19 +11,16 @@ This endpoint requires device authentication (not user JWT). Kobo devices authen
|
||||
|
||||
## Request Body
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| book_ids | array of string | No | Array of ContentIDs to sync |
|
||||
| full_sync | boolean | No | Whether to perform full sync (default: false) |
|
||||
| Field | Type | Required | Description |
|
||||
| --------- | --------------- | -------- | --------------------------------------------- |
|
||||
| book_ids | array of string | No | Array of ContentIDs to sync |
|
||||
| full_sync | boolean | No | Whether to perform full sync (default: false) |
|
||||
|
||||
### Example Request
|
||||
|
||||
```json
|
||||
{
|
||||
"book_ids": [
|
||||
"content-id-1",
|
||||
"content-id-2"
|
||||
],
|
||||
"book_ids": ["content-id-1", "content-id-2"],
|
||||
"full_sync": false
|
||||
}
|
||||
```
|
||||
@@ -53,10 +50,10 @@ This endpoint requires device authentication (not user JWT). Kobo devices authen
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Device authentication failed |
|
||||
| 404 | Device not found |
|
||||
| Code | Description |
|
||||
| ---- | ---------------------------- |
|
||||
| 401 | Device authentication failed |
|
||||
| 404 | Device not found |
|
||||
|
||||
## Notes
|
||||
|
||||
|
||||
@@ -11,10 +11,10 @@ This endpoint requires device authentication (not user JWT). Devices authenticat
|
||||
|
||||
## Request Headers
|
||||
|
||||
| Header | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| X-Device-ID | string | Yes | Device UUID |
|
||||
| X-Device-Key | string | Yes | Device authentication key |
|
||||
| Header | Type | Required | Description |
|
||||
| ------------ | ------ | -------- | ------------------------- |
|
||||
| X-Device-ID | string | Yes | Device UUID |
|
||||
| X-Device-Key | string | Yes | Device authentication key |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -43,7 +43,7 @@ X-Device-Key: device-auth-key
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Device authentication failed |
|
||||
| 404 | Device not found |
|
||||
| Code | Description |
|
||||
| ---- | ---------------------------- |
|
||||
| 401 | Device authentication failed |
|
||||
| 404 | Device not found |
|
||||
|
||||
@@ -7,9 +7,9 @@ Get metadata for a book from KOReader device.
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| uuid | string (UUID) | Yes | Book UUID |
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ------------- | -------- | ----------- |
|
||||
| uuid | string (UUID) | Yes | Book UUID |
|
||||
|
||||
## Device Authentication
|
||||
|
||||
@@ -17,10 +17,10 @@ This endpoint requires device authentication (not user JWT). Devices authenticat
|
||||
|
||||
## Request Headers
|
||||
|
||||
| Header | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| X-Device-ID | string | Yes | Device UUID |
|
||||
| X-Device-Key | string | Yes | Device authentication key |
|
||||
| Header | Type | Required | Description |
|
||||
| ------------ | ------ | -------- | ------------------------- |
|
||||
| X-Device-ID | string | Yes | Device UUID |
|
||||
| X-Device-Key | string | Yes | Device authentication key |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -45,7 +45,7 @@ X-Device-Key: device-auth-key
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Device authentication failed |
|
||||
| 404 | Book or device not found |
|
||||
| Code | Description |
|
||||
| ---- | ---------------------------- |
|
||||
| 401 | Device authentication failed |
|
||||
| 404 | Book or device not found |
|
||||
|
||||
@@ -11,23 +11,23 @@ This endpoint requires device authentication (not user JWT). Devices authenticat
|
||||
|
||||
## Request Body
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| device_id | string (UUID) | Yes | Device UUID |
|
||||
| bookmarks | array | Yes | Array of bookmark objects |
|
||||
| Field | Type | Required | Description |
|
||||
| --------- | ------------- | -------- | ------------------------- |
|
||||
| device_id | string (UUID) | Yes | Device UUID |
|
||||
| bookmarks | array | Yes | Array of bookmark objects |
|
||||
|
||||
### Bookmark Object
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| book | string | Yes | Book identifier |
|
||||
| chapter | string | No | Chapter title |
|
||||
| page | integer | No | Page number |
|
||||
| position | float | Yes | Position in document (0-1) |
|
||||
| notes | string | No | Bookmark notes |
|
||||
| highlighted_text | string | No | Highlighted text |
|
||||
| time | string | Yes | ISO 8601 timestamp |
|
||||
| created_at | string | Yes | ISO 8601 timestamp |
|
||||
| Field | Type | Required | Description |
|
||||
| ---------------- | ------- | -------- | -------------------------- |
|
||||
| book | string | Yes | Book identifier |
|
||||
| chapter | string | No | Chapter title |
|
||||
| page | integer | No | Page number |
|
||||
| position | float | Yes | Position in document (0-1) |
|
||||
| notes | string | No | Bookmark notes |
|
||||
| highlighted_text | string | No | Highlighted text |
|
||||
| time | string | Yes | ISO 8601 timestamp |
|
||||
| created_at | string | Yes | ISO 8601 timestamp |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -60,8 +60,8 @@ This endpoint requires device authentication (not user JWT). Devices authenticat
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Device authentication failed |
|
||||
| 400 | Invalid request data |
|
||||
| 404 | Device not found |
|
||||
| Code | Description |
|
||||
| ---- | ---------------------------- |
|
||||
| 401 | Device authentication failed |
|
||||
| 400 | Invalid request data |
|
||||
| 404 | Device not found |
|
||||
|
||||
@@ -11,21 +11,21 @@ This endpoint requires device authentication (not user JWT). Devices authenticat
|
||||
|
||||
## Request Body
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| device_id | string (UUID) | Yes | Device UUID |
|
||||
| progress | array | Yes | Array of progress objects |
|
||||
| Field | Type | Required | Description |
|
||||
| --------- | ------------- | -------- | ------------------------- |
|
||||
| device_id | string (UUID) | Yes | Device UUID |
|
||||
| progress | array | Yes | Array of progress objects |
|
||||
|
||||
### Progress Object
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| book | string | Yes | Book identifier (filename or UUID) |
|
||||
| percent | float | Yes | Progress percentage (0-100) |
|
||||
| page | integer | No | Current page number |
|
||||
| total_pages | integer | No | Total pages in document |
|
||||
| date_read | string | No | ISO 8601 timestamp of last read |
|
||||
| updated_at | string | Yes | ISO 8601 timestamp |
|
||||
| Field | Type | Required | Description |
|
||||
| ----------- | ------- | -------- | ---------------------------------- |
|
||||
| book | string | Yes | Book identifier (filename or UUID) |
|
||||
| percent | float | Yes | Progress percentage (0-100) |
|
||||
| page | integer | No | Current page number |
|
||||
| total_pages | integer | No | Total pages in document |
|
||||
| date_read | string | No | ISO 8601 timestamp of last read |
|
||||
| updated_at | string | Yes | ISO 8601 timestamp |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -56,8 +56,8 @@ This endpoint requires device authentication (not user JWT). Devices authenticat
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Device authentication failed |
|
||||
| 400 | Invalid request data |
|
||||
| 404 | Device not found |
|
||||
| Code | Description |
|
||||
| ---- | ---------------------------- |
|
||||
| 401 | Device authentication failed |
|
||||
| 400 | Invalid request data |
|
||||
| 404 | Device not found |
|
||||
|
||||
@@ -8,15 +8,15 @@ Add a folder to an existing library (Admin only).
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| library_id | string | Yes | Library UUID |
|
||||
| Parameter | Type | Required | Description |
|
||||
| ---------- | ------ | -------- | ------------ |
|
||||
| library_id | string | Yes | Library UUID |
|
||||
|
||||
## Request Body
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| folder_path | string | Yes | Absolute path to folder |
|
||||
| Field | Type | Required | Description |
|
||||
| ----------- | ------ | -------- | ----------------------- |
|
||||
| folder_path | string | Yes | Absolute path to folder |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -39,9 +39,9 @@ Add a folder to an existing library (Admin only).
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 400 | Invalid folder path |
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | User is not an admin |
|
||||
| 404 | Library not found |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------ |
|
||||
| 400 | Invalid folder path |
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | User is not an admin |
|
||||
| 404 | Library not found |
|
||||
|
||||
@@ -7,15 +7,15 @@ Browse server directories for folder selection in library management.
|
||||
|
||||
## Query Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| path | string | No | Directory path to browse (default: "/") |
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ------ | -------- | --------------------------------------- |
|
||||
| path | string | No | Directory path to browse (default: "/") |
|
||||
|
||||
## Request Headers
|
||||
|
||||
| Header | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| Authorization | string | Yes | Bearer token (admin only) |
|
||||
| Header | Type | Required | Description |
|
||||
| ------------- | ------ | -------- | ------------------------- |
|
||||
| Authorization | string | Yes | Bearer token (admin only) |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -36,13 +36,13 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 400 | Path traversal attempt or invalid path |
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | User is not an admin |
|
||||
| 400 | Path does not exist |
|
||||
| 400 | Path is not a directory |
|
||||
| Code | Description |
|
||||
| ---- | -------------------------------------- |
|
||||
| 400 | Path traversal attempt or invalid path |
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | User is not an admin |
|
||||
| 400 | Path does not exist |
|
||||
| 400 | Path is not a directory |
|
||||
|
||||
## Security
|
||||
|
||||
|
||||
@@ -8,11 +8,11 @@ Create a new library (Admin only).
|
||||
|
||||
## Request Body
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| name | string | Yes | Library name |
|
||||
| description | string | No | Library description |
|
||||
| type | string | Yes | Library type (e.g., "ebooks", "comics", "audiobooks") |
|
||||
| Field | Type | Required | Description |
|
||||
| ----------- | ------ | -------- | ----------------------------------------------------- |
|
||||
| name | string | Yes | Library name |
|
||||
| description | string | No | Library description |
|
||||
| type | string | Yes | Library type (e.g., "ebooks", "comics", "audiobooks") |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -38,8 +38,8 @@ Create a new library (Admin only).
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 400 | Invalid input data |
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | User is not an admin |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------ |
|
||||
| 400 | Invalid input data |
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | User is not an admin |
|
||||
|
||||
@@ -7,15 +7,15 @@ Delete a library and all associated data.
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| id | string (UUID) | Yes | Library UUID |
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ------------- | -------- | ------------ |
|
||||
| id | string (UUID) | Yes | Library UUID |
|
||||
|
||||
## Request Headers
|
||||
|
||||
| Header | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| Authorization | string | Yes | Bearer token (must have admin role) |
|
||||
| Header | Type | Required | Description |
|
||||
| ------------- | ------ | -------- | ----------------------------------- |
|
||||
| Authorization | string | Yes | Bearer token (must have admin role) |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -30,8 +30,8 @@ Library deleted successfully.
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | User does not have admin privileges |
|
||||
| 404 | Library not found |
|
||||
| Code | Description |
|
||||
| ---- | ----------------------------------- |
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | User does not have admin privileges |
|
||||
| 404 | Library not found |
|
||||
|
||||
@@ -8,15 +8,15 @@ Delete a folder from a library.
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| id | string (UUID) | Yes | Library UUID |
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ------------- | -------- | ------------ |
|
||||
| id | string (UUID) | Yes | Library UUID |
|
||||
|
||||
## Request Body
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| folder_path | string | Yes | Absolute path to the folder to delete |
|
||||
| Field | Type | Required | Description |
|
||||
| ----------- | ------ | -------- | ------------------------------------- |
|
||||
| folder_path | string | Yes | Absolute path to the folder to delete |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -32,9 +32,9 @@ Library folder deleted successfully.
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 400 | Invalid request data |
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | User does not have admin privileges |
|
||||
| 404 | Library or folder not found |
|
||||
| Code | Description |
|
||||
| ---- | ----------------------------------- |
|
||||
| 400 | Invalid request data |
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | User does not have admin privileges |
|
||||
| 404 | Library or folder not found |
|
||||
|
||||
@@ -7,15 +7,15 @@ Retrieve details of a specific library.
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| library_id | string | Yes | Library UUID |
|
||||
| Parameter | Type | Required | Description |
|
||||
| ---------- | ------ | -------- | ------------ |
|
||||
| library_id | string | Yes | Library UUID |
|
||||
|
||||
## Request Headers
|
||||
|
||||
| Header | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| Authorization | string | Yes | Bearer token |
|
||||
| Header | Type | Required | Description |
|
||||
| ------------- | ------ | -------- | ------------ |
|
||||
| Authorization | string | Yes | Bearer token |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -44,8 +44,8 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | User does not have access to this library |
|
||||
| 404 | Library not found |
|
||||
| Code | Description |
|
||||
| ---- | ----------------------------------------- |
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | User does not have access to this library |
|
||||
| 404 | Library not found |
|
||||
|
||||
@@ -7,24 +7,24 @@ Get all media items in a specific library.
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| id | string (UUID) | Yes | Library UUID |
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ------------- | -------- | ------------ |
|
||||
| id | string (UUID) | Yes | Library UUID |
|
||||
|
||||
## Query Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| limit | integer | No | Maximum number of items to return (default: 50) |
|
||||
| offset | integer | No | Number of items to skip (default: 0) |
|
||||
| sort_by | string | No | Sort field (title, created_at, etc.) |
|
||||
| sort_order | string | No | Sort order (asc, desc) |
|
||||
| Parameter | Type | Required | Description |
|
||||
| ---------- | ------- | -------- | ----------------------------------------------- |
|
||||
| limit | integer | No | Maximum number of items to return (default: 50) |
|
||||
| offset | integer | No | Number of items to skip (default: 0) |
|
||||
| sort_by | string | No | Sort field (title, created_at, etc.) |
|
||||
| sort_order | string | No | Sort order (asc, desc) |
|
||||
|
||||
## Request Headers
|
||||
|
||||
| Header | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| Authorization | string | Yes | Bearer token (must have admin role) |
|
||||
| Header | Type | Required | Description |
|
||||
| ------------- | ------ | -------- | ----------------------------------- |
|
||||
| Authorization | string | Yes | Bearer token (must have admin role) |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -54,8 +54,8 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | User does not have admin privileges |
|
||||
| 404 | Library not found |
|
||||
| Code | Description |
|
||||
| ---- | ----------------------------------- |
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | User does not have admin privileges |
|
||||
| 404 | Library not found |
|
||||
|
||||
@@ -7,15 +7,15 @@ Get statistics for a specific library.
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| id | string (UUID) | Yes | Library UUID |
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ------------- | -------- | ------------ |
|
||||
| id | string (UUID) | Yes | Library UUID |
|
||||
|
||||
## Request Headers
|
||||
|
||||
| Header | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| Authorization | string | Yes | Bearer token (must have admin role) |
|
||||
| Header | Type | Required | Description |
|
||||
| ------------- | ------ | -------- | ----------------------------------- |
|
||||
| Authorization | string | Yes | Bearer token (must have admin role) |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -43,8 +43,8 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | User does not have admin privileges |
|
||||
| 404 | Library not found |
|
||||
| Code | Description |
|
||||
| ---- | ----------------------------------- |
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | User does not have admin privileges |
|
||||
| 404 | Library not found |
|
||||
|
||||
@@ -7,9 +7,9 @@ Retrieve all libraries visible to the current user.
|
||||
|
||||
## Request Headers
|
||||
|
||||
| Header | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| Authorization | string | Yes | Bearer token |
|
||||
| Header | Type | Required | Description |
|
||||
| ------------- | ------ | -------- | ------------ |
|
||||
| Authorization | string | Yes | Bearer token |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -36,6 +36,6 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Invalid or expired token |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------ |
|
||||
| 401 | Invalid or expired token |
|
||||
|
||||
@@ -8,11 +8,11 @@ Set library visibility for a specific user (Admin only).
|
||||
|
||||
## Request Body
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| user_id | string | Yes | User UUID |
|
||||
| library_id | string | Yes | Library UUID |
|
||||
| is_visible | boolean | Yes | Whether library is visible to user |
|
||||
| Field | Type | Required | Description |
|
||||
| ---------- | ------- | -------- | ---------------------------------- |
|
||||
| user_id | string | Yes | User UUID |
|
||||
| library_id | string | Yes | Library UUID |
|
||||
| is_visible | boolean | Yes | Whether library is visible to user |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -36,9 +36,9 @@ Set library visibility for a specific user (Admin only).
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 400 | Invalid input data |
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | User is not an admin |
|
||||
| 404 | User or library not found |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------- |
|
||||
| 400 | Invalid input data |
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | User is not an admin |
|
||||
| 404 | User or library not found |
|
||||
|
||||
@@ -8,16 +8,16 @@ Update a library's information.
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| id | string (UUID) | Yes | Library UUID |
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ------------- | -------- | ------------ |
|
||||
| id | string (UUID) | Yes | Library UUID |
|
||||
|
||||
## Request Body
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| name | string | No | Library name |
|
||||
| library_type_id | integer | No | Library type ID |
|
||||
| Field | Type | Required | Description |
|
||||
| --------------- | ------- | -------- | --------------- |
|
||||
| name | string | No | Library name |
|
||||
| library_type_id | integer | No | Library type ID |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -42,9 +42,9 @@ Update a library's information.
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 400 | Invalid request data |
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | User does not have admin privileges |
|
||||
| 404 | Library not found |
|
||||
| Code | Description |
|
||||
| ---- | ----------------------------------- |
|
||||
| 400 | Invalid request data |
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | User does not have admin privileges |
|
||||
| 404 | Library not found |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -8,18 +8,18 @@ Create a new note for a 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 Body
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| content | string | Yes | Note content |
|
||||
| position | string | No | Location reference (e.g., epubcfi) |
|
||||
| percentage_location | float | No | Location as percentage (0-1) |
|
||||
| epubcfi_location | string | No | EPUB CFI location |
|
||||
| Field | Type | Required | Description |
|
||||
| ------------------- | ------ | -------- | ---------------------------------- |
|
||||
| content | string | Yes | Note content |
|
||||
| position | string | No | Location reference (e.g., epubcfi) |
|
||||
| percentage_location | float | No | Location as percentage (0-1) |
|
||||
| epubcfi_location | string | No | EPUB CFI location |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -49,8 +49,8 @@ Create a new note for a media item.
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 400 | Invalid note data |
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Media item not found |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------ |
|
||||
| 400 | Invalid note data |
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Media item not found |
|
||||
|
||||
@@ -7,15 +7,15 @@ Delete a note.
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| note_id | string | Yes | Note UUID |
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ------ | -------- | ----------- |
|
||||
| note_id | string | Yes | Note 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 @@ Note deleted successfully.
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | User does not own this note |
|
||||
| 404 | Note not found |
|
||||
| Code | Description |
|
||||
| ---- | --------------------------- |
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | User does not own this note |
|
||||
| 404 | Note not found |
|
||||
|
||||
@@ -7,15 +7,15 @@ Retrieve all notes for 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
|
||||
|
||||
@@ -48,7 +48,7 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Media item not found |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------ |
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Media item not found |
|
||||
|
||||
@@ -8,16 +8,16 @@ Update an existing note.
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| note_id | string | Yes | Note UUID |
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ------ | -------- | ----------- |
|
||||
| note_id | string | Yes | Note UUID |
|
||||
|
||||
## Request Body
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| content | string | No | Updated note content |
|
||||
| position | string | No | Updated location reference |
|
||||
| Field | Type | Required | Description |
|
||||
| -------- | ------ | -------- | -------------------------- |
|
||||
| content | string | No | Updated note content |
|
||||
| position | string | No | Updated location reference |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -43,9 +43,9 @@ Update an existing note.
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 400 | Invalid note data |
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | User does not own this note |
|
||||
| 404 | Note not found |
|
||||
| Code | Description |
|
||||
| ---- | --------------------------- |
|
||||
| 400 | Invalid note data |
|
||||
| 401 | Invalid or expired token |
|
||||
| 403 | User does not own this note |
|
||||
| 404 | Note not found |
|
||||
|
||||
@@ -9,9 +9,9 @@ Download books and list available formats.
|
||||
|
||||
### Query Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| format | string | No | Book format: `epub` (default), `kepub` |
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ------ | -------- | -------------------------------------- |
|
||||
| format | string | No | Book format: `epub` (default), `kepub` |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -22,6 +22,7 @@ GET /opds/devices/kobo-id/download/uuid-123?format=kepub
|
||||
### Response (200 OK)
|
||||
|
||||
**Headers:**
|
||||
|
||||
- `Content-Type`: `application/epub+zip` or `application/vnd.kobo+xml+zip`
|
||||
- `Content-Disposition`: attachment; filename="The Hobbit.epub"
|
||||
- `X-Bookhoard-UUID`: uuid-123
|
||||
|
||||
@@ -9,10 +9,10 @@ Bookhoard provides OPDS 1.2 feeds for device compatibility.
|
||||
|
||||
### Query Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| page | integer | No | Page number (default: 1) |
|
||||
| per_page | integer | No | Items per page (default: 50, max: 200) |
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ------- | -------- | -------------------------------------- |
|
||||
| page | integer | No | Page number (default: 1) |
|
||||
| per_page | integer | No | Items per page (default: 50, max: 200) |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -24,31 +24,31 @@ GET /opds/devices/kobo-id/catalog?page=1&per_page=50
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<feed xmlns="http://www.w3.org/2005/Atom"
|
||||
<feed xmlns="http://www.w3.org/2005/Atom"
|
||||
xmlns:opds="http://opds-spec.org/2010/"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<id>urn:uuid:device-id</id>
|
||||
<title>Bookhoard Library</title>
|
||||
<updated>2026-02-01T12:00:00Z</updated>
|
||||
|
||||
|
||||
<link rel="self" href="http://localhost:8765/opds/devices/kobo-id/catalog"/>
|
||||
<link rel="search" href="http://localhost:8765/opds/devices/kobo-id/search"/>
|
||||
<link rel="start" href="http://localhost:8765/opds/devices/kobo-id/nav"/>
|
||||
|
||||
|
||||
<entry>
|
||||
<id>urn:uuid:bookhoard-uuid-123</id>
|
||||
<dc:title>The Hobbit</dc:title>
|
||||
<dc:creator>J.R.R. Tolkien</dc:creator>
|
||||
<updated>2026-02-01T10:00:00Z</updated>
|
||||
|
||||
<link href="http://localhost:8765/opds/devices/kobo-id/download/uuid-123"
|
||||
type="application/epub+zip"
|
||||
|
||||
<link href="http://localhost:8765/opds/devices/kobo-id/download/uuid-123"
|
||||
type="application/epub+zip"
|
||||
rel="http://opds-spec.org/acquisition/open-access"/>
|
||||
|
||||
<link href="http://localhost:8765/opds/devices/kobo-id/download/uuid-123?format=kepub"
|
||||
type="application/vnd.kobo+xml+zip"
|
||||
|
||||
<link href="http://localhost:8765/opds/devices/kobo-id/download/uuid-123?format=kepub"
|
||||
type="application/vnd.kobo+xml+zip"
|
||||
rel="alternate"/>
|
||||
|
||||
|
||||
<dc:identifier id="bookhoard">uuid-123</dc:identifier>
|
||||
<meta property="bookhoard:sha256">abc123...</meta>
|
||||
</entry>
|
||||
@@ -62,9 +62,9 @@ GET /opds/devices/kobo-id/catalog?page=1&per_page=50
|
||||
|
||||
### Query Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| q | string | Yes | Search query |
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ------ | -------- | ------------ |
|
||||
| q | string | Yes | Search query |
|
||||
|
||||
### Example Request
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ GET /opds/devices/kobo-id/nav
|
||||
### Response (200 OK - OPDS 1.2 Navigation XML)
|
||||
|
||||
Returns OPDS navigation feed with links to:
|
||||
|
||||
- Root catalog
|
||||
- Search
|
||||
- Collections/shelves
|
||||
|
||||
@@ -7,15 +7,15 @@ Delete reading progress for a 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
|
||||
|
||||
@@ -30,7 +30,7 @@ Progress deleted successfully.
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Media item not found |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------ |
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Media item not found |
|
||||
|
||||
@@ -7,15 +7,15 @@ Retrieve reading progress for 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
|
||||
|
||||
@@ -46,7 +46,7 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Media item not found |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------ |
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Media item not found |
|
||||
|
||||
@@ -7,22 +7,22 @@ Get historical reading progress data for a media item.
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| id | string (UUID) | Yes | Media item UUID |
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ------------- | -------- | --------------- |
|
||||
| id | string (UUID) | Yes | Media item UUID |
|
||||
|
||||
## Query Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| limit | integer | No | Maximum number of history entries (default: 100) |
|
||||
| offset | integer | No | Number of entries to skip (default: 0) |
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ------- | -------- | ------------------------------------------------ |
|
||||
| limit | integer | No | Maximum number of history entries (default: 100) |
|
||||
| offset | integer | No | Number of entries to skip (default: 0) |
|
||||
|
||||
## Request Headers
|
||||
|
||||
| Header | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| Authorization | string | Yes | Bearer token |
|
||||
| Header | Type | Required | Description |
|
||||
| ------------- | ------ | -------- | ------------ |
|
||||
| Authorization | string | Yes | Bearer token |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -63,7 +63,7 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Media item not found |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------ |
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Media item not found |
|
||||
|
||||
@@ -7,15 +7,15 @@ Get universal (device-agnostic) reading progress for a media item.
|
||||
|
||||
## Path Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|-----------|-------------|
|
||||
| id | string (UUID) | Yes | Media item UUID |
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ------------- | -------- | --------------- |
|
||||
| id | string (UUID) | 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
|
||||
|
||||
@@ -44,7 +44,7 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Media item not found |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------ |
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Media item not found |
|
||||
|
||||
@@ -8,25 +8,25 @@ Update reading progress for a media item. This will sync across all devices via
|
||||
|
||||
## 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
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------|------|-----------|-------------|
|
||||
| source | string | Yes | Progress source (e.g., "web", "koreader", "kobo") |
|
||||
| location | object | Yes | Location information |
|
||||
| location.percentage | float | No | Progress percentage (0-1) |
|
||||
| location.epubcfi | string | No | EPUB CFI location |
|
||||
| location.character | integer | No | Character offset |
|
||||
| location.chapter | integer | No | Chapter number |
|
||||
| location.page | integer | No | Current page |
|
||||
| location.total_pages | integer | No | Total pages |
|
||||
| device_metadata | object | No | Device metadata |
|
||||
| device_metadata.device_type | string | No | Device type |
|
||||
| device_metadata.user_agent | string | No | User agent string |
|
||||
| Field | Type | Required | Description |
|
||||
| --------------------------- | ------- | -------- | ------------------------------------------------- |
|
||||
| source | string | Yes | Progress source (e.g., "web", "koreader", "kobo") |
|
||||
| location | object | Yes | Location information |
|
||||
| location.percentage | float | No | Progress percentage (0-1) |
|
||||
| location.epubcfi | string | No | EPUB CFI location |
|
||||
| location.character | integer | No | Character offset |
|
||||
| location.chapter | integer | No | Chapter number |
|
||||
| location.page | integer | No | Current page |
|
||||
| location.total_pages | integer | No | Total pages |
|
||||
| device_metadata | object | No | Device metadata |
|
||||
| device_metadata.device_type | string | No | Device type |
|
||||
| device_metadata.user_agent | string | No | User agent string |
|
||||
|
||||
### Example Request
|
||||
|
||||
@@ -61,8 +61,8 @@ Update reading progress for a media item. This will sync across all devices via
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| 400 | Invalid location data |
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Media item not found |
|
||||
| Code | Description |
|
||||
| ---- | ------------------------ |
|
||||
| 400 | Invalid location data |
|
||||
| 401 | Invalid or expired token |
|
||||
| 404 | Media item not found |
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user