Files
bookhoard/docs/developer/api/koreader/sync_progress.md
T
John O'Keefe 25ef0d12ba docs(kobo,koreader,collections): Beam WO5 batch 6 — 12 endpoints
Kobo emulation + KOReader calibre-compatible surface backfilled with
device-token auth; collections reorder + update_rule created.

Claude registry: 12 entries. kobo/koreader emulation endpoints all bind
arbitrary protocol POST bodies (markup/bookmark/gettests/sync-from-server,
koreader progress/bookmarks) — registered as AnyJSONObject, not bodyless as
first drafted. Initialization returns the library sync payload, not the init
response.

Contract correction in update_rule.md: the route is SetRuleEnabled ({enabled}
required -> {collection_id, is_smart}); Beam's draft invented rule-field
updates. Reordered response/status: {item_ids} -> {status: reordered}.

make test 9/9.
2026-10-24 16:25:00 -04:00

3.3 KiB

method, path, auth, area
method path auth area
POST /api/sync/koreader/progress device-token koreader

Sync Progress

Push reading progress from a KOReader device.

Endpoint: POST /api/sync/koreader/progress Auth: Required (Device authentication — Authorization: Bearer {device_token})

This is the device-native tier of the Position Contract: the KOReader payload carries a CRE xpointer and the server converts it to the canonical standard CFI, verifies it against the submitted context_text, and heals it on mismatch — exactly like every other client.

Request Body

Field Type Required Description
books array Yes One book object (the reference client sends a single-element array).
sync_mode string No immediate (default) or manual.

Book Object

Field Type Required Description
uuid string (UUID) No Bookhoard UUID, once the device has linked the book via Resolve Book.
sha256 string Yes File content hash (64 hex chars) — the primary book identity.
title string No Document title.
authors array No Author names.
percentage float Yes Position as a fraction of the book (0..1).
context_text string No Up to 100 whitespace-normalized chars from the current position — enables the server's verification/healing. Strongly recommended.
page int No Current page (fixed-layout books).
total_pages int No Page count (fixed-layout books).
epubcfi string Reflowable only A CRE xpointer (/body/DocFragment[N]/body/...), not a CFI — the field name is historical. Fixed-layout books must omit it and carry their position in page/total_pages.
file_path string No Device-local file path (informational).
device_info object No { koreader_version, device_model }.

Example Request

POST /api/sync/koreader/progress
Authorization: Bearer {device_token}
Content-Type: application/json
{
  "books": [
    {
      "uuid": "774641f9-317b-4087-8e04-53bb4392ae56",
      "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
      "title": "1984",
      "authors": ["George Orwell"],
      "percentage": 0.045,
      "context_text": "from day to day, but there was none in which Goldstein was not the principal figure. He was the prim",
      "page": 14,
      "total_pages": 311,
      "epubcfi": "/body/DocFragment[1]/body/p[29]/text().598",
      "device_info": {
        "koreader_version": "v2026.07.1",
        "device_model": "emulator"
      }
    }
  ],
  "sync_mode": "immediate"
}

Response (202 Accepted)

{
  "sync_status": "ok",
  "books_synced": 1,
  "timestamp": "2026-09-26T21:25:09Z",
  "device_updated": null
}

Per-book results and any detected sync conflicts are carried in book_results and conflicts when present.

Error Responses

Code Description
400 Invalid request format
401 Device authentication failed
500 Database error