- Add Kobo bookmark/markup sync tests - Add Koreader progress/bookmark sync tests - Add OPDS feed tests - Add collection tests - Add sync tests for book linking
KOReader Integration
Overview
Bookmann provides full Calibre-compatible wireless sync for KOReader devices, enabling seamless reading progress, highlights, and notes synchronization.
Setup
1. Register Your Device
First, register your KOReader device with Bookmann:
POST /api/devices/register
{
"device_name": "My Kindle Paperwhite",
"device_type": "koreader",
"device_identifier": "unique-hardware-id"
}
You'll receive:
- A registration URL to approve the device
- A QR code for easy setup
- Setup instructions for your device type
2. Approve Device
Visit the approval URL in your web browser (or scan the QR code) to authenticate the device.
3. Configure KOReader
In KOReader settings, set:
- Calibre wireless URL:
https://your-bookmann-domain.com/api/sync/koreader - Enable wireless sync: ON
- Sync frequency: Every page turn (recommended)
4. Enter Device Token
After approval, you'll receive a device token. Add this to KOReader:
- Settings → Wireless sync → Password
- Paste the token:
dev_xxxxx...
API Endpoints
Sync Progress
Updates reading progress for one or more books.
POST /api/sync/koreader/progress
Authorization: Bearer {device_token}
Content-Type: application/json
{
"books": [
{
"uuid": "book-uuid",
"title": "Book Title",
"authors": ["Author Name"],
"percentage": 0.45,
"progress": 0.45,
"chapter": 5,
"character": 15432,
"epubcfi": "epubcfi(/6/4/2:15)",
"page": 89,
"total_pages": 200,
"last_read": "2026-01-30T20:00:00Z"
}
],
"sync_mode": "immediate"
}
Response (202 Accepted):
{
"sync_status": "accepted",
"books_synced": 1,
"conflicts": [],
"timestamp": "2026-01-30T20:00:00Z",
"device_updated": true
}
Get Book Metadata
Fetches progress and annotations for a specific book.
GET /api/sync/koreader/metadata/{book_uuid}
Authorization: Bearer {device_token}
Response (200 OK):
{
"uuid": "book-uuid",
"title": "Book Title",
"authors": ["Author Name"],
"progress": {
"percentage": 0.45,
"chapter": 5,
"epubcfi": "epubcfi(/6/4/2:15)",
"character": 15432,
"page": 89,
"total_pages": 200
},
"annotations": {
"highlights": [
{
"text": "highlighted text",
"pos0": "epubcfi(/6/4/2:15)",
"pos1": "epubcfi(/6/4/2:20)",
"color": "#ffff00",
"datetime": "2026-01-30T19:55:00Z"
}
],
"notes": [
{
"text": "My note",
"pos0": "epubcfi(/6/4/2:15)",
"datetime": "2026-01-30T19:55:00Z"
}
]
},
"last_sync": "2026-01-30T20:00:00Z"
}
Get Library
Fetches all books available for sync.
GET /api/sync/koreader/library
Authorization: Bearer {device_token}
Response (200 OK):
{
"library_sync": [
{
"uuid": "book-uuid",
"title": "Book Title",
"author": "Author Name",
"content_type": "6",
"percent_read": 45.0,
"pages_remaining": 115,
"bookmark_count": 3,
"last_modified": "2026-01-30T20:00:00Z"
}
],
"total_books": 10,
"last_sync": "2026-01-30T20:00:00Z"
}
Sync Bookmarks/Notes/Highlights
Syncs annotations for a specific book.
POST /api/sync/koreader/bookmarks
Authorization: Bearer {device_token}
Content-Type: application/json
{
"book_uuid": "book-uuid",
"bookmarks": [
{
"chapter": 3,
"datetime": "2026-01-30T19:55:00Z",
"pos0": "epubcfi(/6/4/2:15)",
"page": 45,
"text": "Bookmarked text",
"type": "bookmark"
}
],
"highlights": [
{
"chapter": 3,
"datetime": "2026-01-30T19:55:00Z",
"pos0": "epubcfi(/6/4/2:15)",
"pos1": "epubcfi(/6/4/2:20)",
"page": 45,
"text": "highlighted text",
"color": "#ffff00"
}
],
"notes": [
{
"chapter": 3,
"datetime": "2026-01-30T19:55:00Z",
"pos0": "epubcfi(/6/4/2:15)",
"notes": "My note content",
"page": 45
}
]
}
Response (200 OK):
{
"sync_status": "completed",
"bookmarks_synced": 1,
"notes_synced": 1,
"highlights_synced": 1,
"total_synced": 3,
"timestamp": "2026-01-30T20:00:00Z"
}
Sync Modes
Immediate Mode (Recommended)
Syncs on every page turn for real-time updates across all devices.
{ "sync_mode": "immediate" }
Checkpoint Mode
Syncs periodically to save bandwidth.
{
"sync_mode": "checkpoint",
"checkpoint_id": "checkpoint-uuid",
"since_timestamp": "2026-01-30T19:00:00Z"
}
Rate Limits
- Sync requests: 60/minute
- Progress updates: 120/minute
- Metadata requests: 30/minute
Device Matching
Bookmann tries multiple strategies to match books:
- By UUID: Most reliable if your book files have unique IDs (confidence: 1.0)
- By SHA-256: Hash-based matching for reliable identification (confidence: 0.9)
- By file path: Matches exact file path and creates device alias (confidence: 0.7)
- By title + author: Fallback for unmatched books (confidence: 0.5)
- By title only: Last resort match (confidence: 0.4)
SHA-256 Matching (Phase 7 Enhancement)
Bookmann now supports SHA-256 hash matching for reliable book identification:
{
"books": [
{
"sha256": "a1b2c3d4e5f6...",
"file_path": "/mnt/onboard/Book.epub",
"percentage": 0.65,
"page": 142,
"total_pages": 310
}
]
}
Benefits:
- Works even if file path changes
- Reliable across device re-formats
- Automatic device file alias creation
- Per-annotation SHA-256 support for mixed-book syncs
Device File Alias System
When a book is matched with a file path, Bookmann automatically creates a device file alias:
- UUID + FilePath: Creates alias with confidence 1.0
- SHA-256 + FilePath: Creates alias with confidence 0.9
- FilePath only: Creates alias with confidence 0.7
- Title match + FilePath: Creates alias with confidence 0.5-0.7
Once created, aliases enable future syncs without UUID or SHA-256:
{
"books": [
{
"file_path": "/mnt/onboard/Book.epub",
"percentage": 0.70
}
]
}
Per-Annotation SHA-256
Sync bookmarks/notes/highlights for multiple books in one request:
{
"highlights": [
{
"text": "Quote from book 1",
"pos0": "/6/4[chap1]!/4/2/1:0",
"pos1": "/6/4[chap1]!/4/2/1:50",
"color": "#ffff00",
"book_sha256": "abc123..."
},
{
"text": "Quote from book 2",
"pos0": "/6/4[chap1]!/4/2/1:0",
"pos1": "/6/4[chap1]!/4/2/1:50",
"color": "#00ff00",
"book_sha256": "def456..."
}
]
}
Conflict Resolution
When the same book is read on multiple devices within 5 minutes:
- Auto-resolution uses "most recent progress wins"
- Conflicts are logged for review
- Users can manually resolve conflicts via the web UI
Troubleshooting
Sync Not Working
- Check device token: Ensure token is valid and not revoked
- Verify sync enabled: Device must have
sync_enabled: true - Check rate limits: Device may be rate-limited
- Book matching: Ensure books can be matched by UUID, path, or title
Progress Not Updating
- Verify percentage value: Must be between 0.0 and 1.0
- Check book ownership: User must have access to the book
- Review sync logs: Check for error messages
Authentication Errors
- Token expired: Re-register device
- Device revoked: Check device status in web UI
- Invalid token format: Ensure
Bearer dev_xxxxx...format
Testing
Use the Bruno API collection in /bruno/koreader/ to test endpoints:
Sync Progress.bru- Test progress syncGet Book Metadata.bru- Test metadata retrievalGet Library.bru- Test library syncSync Bookmarks.bru- Test annotation sync
Required variables:
baseUrl- Your Bookmann server URLdevice_token- Device authentication tokenbook_uuid- UUID of a test book
Implementation Notes
- Compatible with Calibre wireless protocol
- Supports EPUB CFI for precise locations
- Handles reflowable and fixed-layout formats
- Bidirectional sync (KOReader ↔ Bookmann)
- Real-time updates via WebSocket (coming in Phase 3b)
Next Steps
See Phase 3 implementation guide for:
- WebSocket real-time sync
- Advanced conflict resolution
- Offline sync queue management
- Performance optimization