diff --git a/docs/api/sync/kobo_protocol.md b/docs/api/sync/kobo_protocol.md new file mode 100644 index 0000000..e7d5e50 --- /dev/null +++ b/docs/api/sync/kobo_protocol.md @@ -0,0 +1,103 @@ +# Kobo Sync Protocol + +Kobo uses a proprietary sync protocol with JSON payloads. + +## Kobo Markup Sync + +**Endpoint**: `POST /api/sync/kobo/markup` +**Auth**: Device token required +**Content-Type**: `application/json` + +### Request Headers + +| Header | Type | Required | Description | +|--------|------|-----------|-------------| +| Authorization | string | Yes | Bearer device token | +| x-kobo-device | string | Yes | JSON device info | +| Content-Type | string | Yes | application/json | + +### Request Body + +| Field | Type | Required | Description | +|--------|------|-----------|-------------| +| ReadingSync | array | No | Array of reading progress data | +| ReadingSync[].ContentId | string | Yes | Book UUID | +| ReadingSync[].PercentRead | float | Yes | Progress percentage (0-100) | +| ReadingSync[].EntitlementId | string | Yes | Kobo entitlement ID | +| ReadingSync[].RemainingTimeMinutes | integer | No | Estimated remaining time | +| ReadingSync[].LastModified | string | Yes | ISO 8601 timestamp | +| BookmarkSync | array | No | Array of bookmarks/highlights | + +### Example Request + +```http +POST /api/sync/kobo/markup +Authorization: Bearer device-token +x-kobo-device: {"DeviceId":"device-id","Model":"Kobo Clara"} +Content-Type: application/json + +{ + "ReadingSync": [ + { + "ContentId": "book-uuid", + "PercentRead": 45.6, + "EntitlementId": "entitlement-id", + "RemainingTimeMinutes": 120, + "LastModified": "2026-01-30T20:00:00Z" + } + ], + "BookmarkSync": [ + { + "ContentId": "book-uuid", + "BookmarkText": "highlighted text", + "BookmarkType": "annotation", + "BookmarkTitle": "Chapter 3" + } + ] +} +``` + +### Response (200 OK) + +```json +{ + "Status": "Success", + "MarkupsSynced": 5, + "BookmarksSynced": 3 +} +``` + +## Kobo Library Fetch + +**Endpoint**: `GET /api/sync/kobo/library` +**Auth**: Device token required + +### Example Request + +```http +GET /api/sync/kobo/library +Authorization: Bearer device-token +``` + +### Response (200 OK) + +```json +{ + "library_sync": [ + { + "ContentId": "book-uuid", + "ContentType": "6", + "Title": "Book Title", + "Author": "Author Name", + "PercentRead": 42.3, + "PagesRemaining": 115, + "BookmarkCount": 3, + "LastModified": "2026-01-30T20:00:00Z" + } + ] +} +``` + +## Try It Out + + diff --git a/docs/api/sync/koreader_protocol.md b/docs/api/sync/koreader_protocol.md new file mode 100644 index 0000000..5c714bf --- /dev/null +++ b/docs/api/sync/koreader_protocol.md @@ -0,0 +1,125 @@ +# KOReader Sync Protocol + +KOReader uses a custom JSON-based sync protocol. + +## KOReader Progress Sync + +**Endpoint**: `POST /api/sync/koreader/progress` +**Auth**: Device token required +**Content-Type**: `application/json` + +### Request Headers + +| Header | Type | Required | Description | +|--------|------|-----------|-------------| +| Authorization | string | Yes | Bearer device token | +| Content-Type | string | Yes | application/json | + +### Request Body + +| Field | Type | Required | Description | +|--------|------|-----------|-------------| +| library_id | string | No | Library UUID | +| books | array | Yes | Array of book sync data | +| books[].uuid | string | Yes | Book UUID | +| books[].title | string | Yes | Book title | +| books[].authors | array | Yes | Array of author names | +| books[].progress | float | Yes | Progress percentage (0-1) | +| books[].percentage | float | Yes | Progress percentage (0-1) | +| books[].last_read | string | Yes | ISO 8601 timestamp | +| books[].chapter | integer | No | Current chapter | +| books[].epubcfi | string | No | EPUB CFI location | +| books[].character | integer | No | Character offset | +| books[].bookmarks | array | No | Array of bookmarks/highlights | + +### Example Request + +```json +{ + "library_id": "optional-uuid", + "books": [ + { + "uuid": "book-uuid", + "title": "Book Title", + "authors": ["Author Name"], + "progress": 0.45, + "percentage": 0.45, + "last_read": "2026-01-30T20:00:00Z", + "chapter": 3, + "epubcfi": "epubcfi(/6/4/2:15)", + "character": 15432, + "bookmarks": [ + { + "chapter": 3, + "datetime": "2026-01-30T19:55:00Z", + "notes": "highlighted text", + "pos0": "epubcfi(/6/4/2:15)", + "pos1": "epubcfi(/6/4/2:20)", + "page": 45, + "text": "highlighted text excerpt", + "type": "highlight" + } + ], + "highlights": [], + "notes": [] + } + ] +} +``` + +### Response (202 Accepted) + +```json +{ + "sync_status": "accepted", + "books_synced": 1, + "conflicts": [ + { + "book_uuid": "book-uuid", + "conflict_type": "progress_mismatch", + "device_progress": 0.45, + "server_progress": 0.42, + "resolution": "device_wins" + } + ] +} +``` + +## KOReader Metadata Fetch + +**Endpoint**: `GET /api/sync/koreader/metadata/{book_uuid}` +**Auth**: Device token required + +### Example Request + +```http +GET /api/sync/koreader/metadata/book-uuid +Authorization: Bearer device-token +``` + +### Response (200 OK) + +```json +{ + "uuid": "book-uuid", + "title": "Book Title", + "authors": ["Author Name"], + "progress": { + "percentage": 0.42, + "character": 15432, + "epubcfi": "epubcfi(/6/4/2:15)", + "chapter": 3, + "chapter_progress": 0.234 + }, + "annotations": { + "highlights": [...], + "notes": [...], + "bookmarks": [...] + }, + "last_sync": "2026-01-30T20:00:00Z" +} +``` + +## Try It Out + + diff --git a/docs/api/websocket/protocol.md b/docs/api/websocket/protocol.md new file mode 100644 index 0000000..f10e000 --- /dev/null +++ b/docs/api/websocket/protocol.md @@ -0,0 +1,109 @@ +# WebSocket Protocol + +Real-time sync events broadcast to connected clients. + +## Connect to WebSocket + +**Endpoint**: `WS /ws/sync?token=` + +### Connection Parameters + +| Parameter | Type | Required | Description | +|-----------|------|-----------|-------------| +| token | string | Yes | JWT authentication token | + +### Example Connection + +```javascript +const ws = new WebSocket('wss://bookhoard.com/ws/sync?token=eyJhbG...'); +``` + +## Message Format + +All messages are JSON objects with a `type` field. + +### Client → Server Messages + +#### Ping (Heartbeat) + +```json +{ + "type": "ping" +} +``` + +Keep connection alive. Server responds with `pong`. + +### Server → Client Messages + +#### Progress Update + +```json +{ + "type": "progress_update", + "timestamp": "2026-01-31T10:00:00Z", + "data": { + "book_id": "uuid", + "progress": { + "percentage": 0.45678, + "epubcfi": "epubcfi(/6/4/2:15)", + "chapter": 3 + }, + "annotations": {} + }, + "source_device": { + "id": "device-uuid", + "name": "My Kobo", + "type": "kobo" + } +} +``` + +Broadcast when any device updates reading progress. + +#### Conflict Detected + +```json +{ + "type": "conflict", + "timestamp": "2026-01-31T10:00:00Z", + "data": { + "book_id": "uuid", + "conflict_id": "uuid", + "conflict_type": "progress" + } +} +``` + +Broadcast when a sync conflict is detected. + +#### Pong + +```json +{ + "type": "pong" +} +``` + +Server response to client `ping`. + +## Connection Management + +- **Heartbeat**: Send `ping` every 30 seconds +- **Reconnect**: Use exponential backoff if connection drops +- **Authentication**: Token must be valid for connection +- **Rate Limits**: 60 messages/minute per connection + +## Error Handling + +```json +{ + "type": "error", + "message": "Invalid token", + "code": "AUTH_FAILED" +} +``` + +## Try It Out + +