Follow-up to the sweep route audit, correcting its diagnosis: the CLI
DOES read .yml bodies — via OpenCollection's `body.data` string form
(the NewDevDBSetup script always worked because it used it). The
failing scenario POSTs used `body.json` (structured) / `body.jsonBody`
(string) — keys the CLI silently ignores, sending Content-Length: 0
with form-urlencoded content-type, so every server bind failed.
- 81 bodies converted to data-form (json maps serialized; jsonBody
strings kept verbatim, {{vars}} intact).
- 6 pre-existing TRUNCATED payloads repaired: the original generator
cut bodies at the first {{var}} (every SHA-256-identified scenario
plus Sync Progress/Sync Bookmarks shipped mid-JSON and 400'd from
day one). Rewritten whole, faithful to each file's documented
purpose; book_sha256/book_uuid added to the environment.
- environments: opds_base_url correction from the sweep retained.
Verified live against the rebuilt dev container: the full koreader
scenario tree runs green through `bru run` — 14/14 (202s across
immediate/checkpoint/SHA-256 progress, 200s bookmarks, highlights,
notes; SHA-256 book identification exercised against a real
file_sha256).
20 lines
2.8 KiB
YAML
20 lines
2.8 KiB
YAML
info:
|
|
name: Sync Reading Progress
|
|
type: http
|
|
seq: 1
|
|
http:
|
|
method: POST
|
|
url: '{{base_url}}/api/sync/kobo/{{kobo_device_token}}/markup'
|
|
auth: inherit
|
|
headers:
|
|
- key: Content-Type
|
|
value: application/json
|
|
- key: x-kobo-device
|
|
value: '{"DeviceId":"{{kobo_device_id}}","Model":"Kobo Clara"}'
|
|
body:
|
|
type: json
|
|
data: "{\n \"ReadingSync\": [\n {\n \"ContentId\": \"book-uuid-here\",\n \"PercentRead\": 45.6,\n \"EntitlementId\": \"entitlement-id-here\",\n \"RemainingTimeMinutes\": 120,\n \"FirstReadTime\": \"2026-01-25T10:00:00Z\",\n \"LastModified\": \"2026-01-30T20:00:00Z\"\n }\n ],\n \"BookmarkSync\": []\n}"
|
|
docs: "## Sync Kobo Reading Progress\n\nSynchronizes reading progress from a Kobo device to the server using Bearer token authentication.\n\n**Method:** POST\n\n**Endpoint:** /api/sync/kobo/markup\n\n**Authentication:** Bearer token (in Authorization header)\n\n**Headers:**\n- `Authorization`: Bearer {{kobo_device_token}}\n- `x-kobo-device`: JSON-encoded device info\n - `DeviceId`: Kobo device identifier\n - `Model`: Device model (e.g., \"Kobo Clara\", \"Kobo Libra\", \"Kobo Aura\")\n\n**Request Body:**\n- `ReadingSync` (array): Reading progress items\n - `ContentId` (string): Book/Content UUID\n - `PercentRead` (number): Reading progress 0-100\n - `EntitlementId` (string): Kobo entitlement ID\n - `RemainingTimeMinutes` (integer): Estimated reading time remaining\n - `FirstReadTime` (string): ISO 8601 timestamp when first opened\n - `LastModified` (string): ISO 8601 timestamp of last progress update\n- `BookmarkSync` (array): Empty array for progress-only sync\n\n**Response:**\n\
|
|
- `synced` (integer): Number of items synced\n- `failed` (integer): Number of items that failed to sync\n- `timestamp` (string): Server timestamp of sync\n- `books` (array): Synced book data\n - `ContentId` (string): Book UUID\n - `status` (string): `synced`, `failed`, `skipped`\n - `server_percent` (number): Server-side progress (for conflict detection)\n\n**Status Codes:**\n- 200: Sync successful\n- 401: Invalid device token\n- 403: Device not approved\n- 400: Invalid request format\n\n**Authentication Methods:**\nThis endpoint uses **Bearer token authentication** (token in Authorization header).\nAlternative: Use `/sync/kobo/{token}/markup` with token in URL path.\n\n**Kobo Sync Features:**\n- Native Kobo sync protocol\n- Supports Kobo Clara, Libra, Aura, Forma, Sage, Elipsa\n- Progress percentage tracking\n- Reading time estimation\n- Cross-device synchronization\n- Automatic conflict resolution (most recent wins)\n\n**Sync Frequency:**\n- Kobo devices auto-sync every 15-30 minutes\
|
|
\ when connected to WiFi\n- Manual sync available from device settings\n- Sync triggers on: device wake, book close, WiFi connection"
|