Files
bookhoard/docs/developer/api/koreader/sync_bookmarks.md
T
john-okeefe c49a9605ff docs(api): rewrite KOReader bookmark sync for current protocol
sync_bookmarks.md documented a request shape the handler never accepted.

- Document the real body: book_uuid/book_sha256 (either required,
  SHA-256 is format-aware), plus separate bookmarks/notes/highlights
  arrays using the shared KOReader annotation shape (pos0/pos1, page,
  text, type, per-annotation book_sha256, dedup_key, percentage)
- Document color semantics from 178fb2e/dafcadd: KOReader palette
  names map to web hex swatches at the boundary, echoes carry no color
  so stored web colors survive round-trips, explicit colors are device
  edits
- koreader-protocol.md: cross-link the bookmark shape/color/dedup
  rules from the progress-sync field table
2026-08-20 14:40:59 -04:00

4.4 KiB

Sync Bookmarks

Sync bookmarks, notes, and highlights from a KOReader device (bidirectional — the response also returns the server's current state for the book so the device can reconcile).

Endpoint: POST /api/sync/koreader/bookmarks Auth: Device token (Bearer)

Request Body

Field Type Required Description
book_uuid string one of uuid/sha Book UUID (highest-confidence match)
book_sha256 string one of uuid/sha Full-file SHA-256 (64 hex chars); format-aware (also matches media_item_formats, so a KEPUB/PDF download matches)
bookmarks array No Bookmark objects
notes array No Note objects
highlights array No Highlight objects

At least one of book_uuid or book_sha256 is required; book_sha256 resolves through the shared BookResolver.

Bookmark / Note / Highlight Object

All three types share the same KOReader annotation shape:

Field Type Required Description
chapter int No Chapter index
datetime string No ISO 8601 creation/edit timestamp
pos0 / pos1 string No Start/end xpointer (or page:N / bare page)
page int No Page number (fallback location when pos0 is empty)
text string No Highlighted text
notes string No Note text attached to the annotation
type string No Annotation type (highlight, note, bookmark)
color string No Highlight color (highlights only) — KOReader palette name, see below
percentage float No Position within the book (0-1)
book_sha256 string No Per-annotation SHA-256; overrides the request-level book match
dedup_key string No Stable echo key; an entry whose content is unchanged from what the server previously served is recognized as an echo rather than a new edit

Color Semantics

KOReader paints highlights from a fixed palette of color names; the web reader uses hex swatches. Colors are mapped at the boundary (unmappable values fall back to yellow on both sides):

KOReader name Web hex
yellow, orange #ffd54f
green, olive #a5d6a7
cyan, blue #90caf9
purple #ce93d8
red #f48fb1
  • An echo (device re-reporting an annotation it received from the server) carries no color, so the stored web color is never clobbered.
  • A non-empty color means the user edited the highlight on the device; it is mapped to the nearest web swatch.

Example Request

{
  "book_sha256": "64-hex-char-sha256",
  "bookmarks": [
    {
      "chapter": 3,
      "datetime": "2026-08-20T10:00:00Z",
      "pos0": "/body/Doc[4]/Sec[2]",
      "page": 25,
      "text": "",
      "type": "bookmark",
      "percentage": 0.125
    }
  ],
  "highlights": [
    {
      "datetime": "2026-08-20T10:05:00Z",
      "pos0": "/body/Doc[4]/Sec[2]/text()[3]:0",
      "pos1": "/body/Doc[4]/Sec[2]/text()[3]:42",
      "text": "Text to remember",
      "notes": "Why this matters",
      "type": "highlight",
      "color": "blue",
      "dedup_key": "echo-key-from-server"
    }
  ]
}

Response (200 OK)

{
  "sync_status": "ok",
  "bookmarks_synced": 1,
  "notes_synced": 0,
  "highlights_synced": 1
}

Error Responses

Code Description
400 Invalid request, or neither uuid nor SHA provided
401 Missing/invalid device token
404 Book not found by SHA-256