The progress documentation described GET/POST /api/progress/:id — endpoints that do not exist in the router — while the endpoint every client actually uses (GET/PUT/DELETE /api/media-items/:id/progress) had no field-level docs at all. New: - progress/position-contract.md: the canonical position model — server as position authority, the three-tier submission (percentage / context_text / epubcfi), ingest verification and healing, the restore handles, the OPF spine numbering hazard (canonical CFI spine steps include linear="no" items; clients resolve documents by anchor_href and land by css_selector + char_offset, never by spine step), the offset currencies (UTF-16 at the wire, runes internal), and context_text rules. - progress/get_media_progress.md and update_media_progress.md: the real endpoints with full field tables, conditionality of the restore handles, the first-page anti-clobber guard, and healed-response semantics. - progress/delete_media_progress.md: the real DELETE route. - koreader/sync_progress.md and koreader/get_metadata.md rewritten to the actual payloads: the plugin sends a single-book array whose "epubcfi" field is a CRE xpointer; the metadata response navigates via koreader_xpointer (canonical CFI converted back to CRE), with page as the canonical locator for fixed-layout books. Removed: the five files documenting the nonexistent /api/progress/:id GET/POST/DELETE endpoints. Kept get_progress_history.md (that route exists). The legacy developer/api-reference.md and the indexed api/api-reference.md progress sections now match the wire and link the new docs; the duplicate "Universal Progress" section points at Reading Progress.
3.5 KiB
3.5 KiB
Update Media Item Progress
Submit reading progress for a media item. This is the position-authority ingest point: the server independently verifies the submission against the book and heals it when the client's projection is wrong.
Endpoint: PUT /api/media-items/:id/progress
Auth: Required (Bearer token)
Content-Type: application/json
See the Position Contract for the three-tier submission model, the verification/healing semantics, and the offset currencies.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | string (UUID) | Yes | Media item UUID |
Request Body
All fields are optional; submit what your renderer can observe.
| Field | Type | Description |
|---|---|---|
percentage |
float | Position as a fraction of the whole book (0..1). Tier 1 — the universal field. |
context_text |
string | Up to 100 whitespace-normalized chars starting at the anchor. Tier 2 — enables verification and healing. |
epubcfi |
string | Standard wrapped CFI (UTF-16 terminals). Tier 3 — the structural anchor. Note: the server re-derives the stored canonical CFI; a client's own spine numbering is healed if it disagrees with the OPF spine. |
character_offset |
int | Book-wide rune offset. Accepted but recomputed server-side from the verified anchor on every verified save. |
current_page, total_pages |
int | Fixed-layout position. For fixed-layout formats the page index is the canonical locator. |
chapter, chapter_progress |
int, float | Chapter index and within-chapter fraction. |
reading_mode |
string | paged or scrolled (fixed-layout reader state). |
zoom_level, scroll_position_x, scroll_position_y |
float | Fixed-layout viewport state. |
Example Request (reflowable, all three tiers)
PUT /api/media-items/774641f9-317b-4087-8e04-53bb4392ae56/progress
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Content-Type: application/json
{
"percentage": 0.0415,
"context_text": "was at war with one of these Powers it was generally at peace with the other. But what was strange w",
"epubcfi": "epubcfi(/6/4!/4/8[_idContainer003]/62/1:456)"
}
Example Request (fixed-layout)
{
"percentage": 0.15,
"current_page": 30,
"total_pages": 194,
"reading_mode": "paged"
}
Behavior
- The submission is verified against the book's XHTML when
context_textis present and the book is convertible reflowable: the CFI is resolved, the text at the anchor is compared withcontext_text, and mismatches heal by text search (percentage disambiguates repeats). See Position Contract. - Anti-clobber guard: a submission with
percentage < 0.005is ignored with{"status": "ignored"}when the stored row already holds a percentage above0.01— re-opening a book at its first page does not wipe real progress. - The response is the stored row after verification, including the
healed
epubcfiand the refreshedcharacter_offsetwhen verification ran.
Response (200 OK)
The saved progress row (same shape as
GET, minus the GET-time handles). The
epubcfi and percentage in the response are the server-verified
values, which may differ from the submitted ones when healing occurred.
Error Responses
| Code | Description |
|---|---|
| 400 | Invalid request data |
| 401 | Invalid or expired token |
| 500 | Database error |