diff --git a/docs/developer/api/api-reference.md b/docs/developer/api/api-reference.md index 85727f3..031f54b 100644 --- a/docs/developer/api/api-reference.md +++ b/docs/developer/api/api-reference.md @@ -237,6 +237,7 @@ See [OPDS Feeds](opds/) See [KOReader Sync](koreader/) and [Sync Protocol](sync/koreader-protocol.md) - POST /api/sync/koreader/progress - Sync reading progress +- GET /api/sync/koreader/resolve?sha256={hash} - Resolve a book UUID by file SHA-256 - GET /api/sync/koreader/metadata/:uuid - Get book metadata - GET /api/sync/koreader/library - Get device library - POST /api/sync/koreader/bookmarks - Sync bookmarks diff --git a/docs/developer/api/koreader/resolve_book.md b/docs/developer/api/koreader/resolve_book.md new file mode 100644 index 0000000..c22c29d --- /dev/null +++ b/docs/developer/api/koreader/resolve_book.md @@ -0,0 +1,50 @@ +# Resolve Book + +Map a book's file SHA-256 to its Bookhoard UUID without touching progress +state. Used by devices to link a freshly downloaded book before their first +pull, so the device's first-page position is never pushed (which would +conflict with server-side progress for books already mid-read). + +**Endpoint**: `GET /api/sync/koreader/resolve` +**Auth**: Required (Device authentication) + +## Query Parameters + +| Parameter | Type | Required | Description | +| --------- | ------ | -------- | ------------------------------------ | +| sha256 | string | Yes | File content hash (64 hex characters) | + +Resolution is format-aware: the hash is checked against both +`media_items.file_sha256` and `media_item_formats.file_sha256`, so a +converted file (KEPUB/PDF) matches its media item too. + +## Device Authentication + +This endpoint requires device authentication (not user JWT). Devices +authenticate using their device credentials. + +### Example Request + +```http +GET /api/sync/koreader/resolve?sha256=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 +Authorization: Bearer {device_token} +``` + +## Response (200 OK) + +```json +{ + "book_uuid": "550e8400-e29b-41d4-a716-446655440000", + "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "title": "Book Title", + "author": "Author Name" +} +``` + +## Error Responses + +| Code | Description | +| ---- | -------------------------------------------- | +| 400 | Missing or malformed `sha256` parameter | +| 401 | Device authentication failed | +| 404 | No book in the library matches the given hash | diff --git a/docs/developer/api/sync/koreader-protocol.md b/docs/developer/api/sync/koreader-protocol.md index ee1d620..aad91ab 100644 --- a/docs/developer/api/sync/koreader-protocol.md +++ b/docs/developer/api/sync/koreader-protocol.md @@ -94,6 +94,41 @@ hash differs from the primary format's hash. } ``` +## Book Resolution (UUID lookup) + +**Endpoint**: `GET /api/sync/koreader/resolve?sha256={hash}` +**Auth**: Device token required + +Read-only lookup mapping a file SHA-256 to the book's UUID (format-aware, +same `BookResolver` path as the progress push). Devices call this on the +first open of a newly downloaded book to learn the UUID **before** their +first pull. Full details: [Resolve Book](../koreader/resolve_book.md). + +This matters for conflict avoidance: a device that pushes to bootstrap its +identity transmits its current (first-page) position, which the server +treats as a real progress update — overwriting/conflicting with genuine +mid-read progress from other sources. Resolve, then pull, then push. + +### Example Request + +```http +GET /api/sync/koreader/resolve?sha256=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 +Authorization: Bearer device-token +``` + +### Response (200 OK) + +```json +{ + "book_uuid": "book-uuid", + "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "title": "Book Title", + "author": "Author Name" +} +``` + +404 when no book in the library matches the hash. + ## KOReader Metadata Fetch **Endpoint**: `GET /api/sync/koreader/metadata/{book_uuid}`