Files
bookhoard/docs/developer/api/media-items/create_media_bookmark.md
T
John O'Keefe ed0ce5d077 docs(media-items): Work Order 3 batch 3a — reader-adjacent CRUD (11 endpoints)
New frontmatter'd docs with real shapes (sqlc models pinned directly):
- bookmarks: get/create/update/delete (sync-aware rows: dedup_key,
  last_modified_*, tombstones; delete is 204)
- review: upsert (empty string DELETES the review) / get (200 with
  {review:null} when absent) / delete
- get single note + highlight (full sqlc row shapes)
- annotation history: restore (POST, kind via query or body) and purge
  (DELETE, kind via required query; permanent)

Gate hardening forced by this batch:
- required-field walk now guards non-struct Request types (RawMessage pins)
- update_media_bookmark needed a full example block (no cross-reference
  shortcuts — the gate checks every doc standalone)
2026-10-24 15:03:36 -04:00

2.0 KiB
Raw Blame History

method, path, auth, area
method path auth area
POST /api/media-items/:id/bookmarks jwt media-items

Create Media Bookmark

Creates a bookmark through the sync-aware path (dedup + last-write-wins + tombstones). Returns 201 with the stored bookmark row.

Example request

{
  "title": "Chapter 3",
  "position": "kindle:pos:1:2",
  "notes": "revisit this",
  "cfi_position": "epubcfi(/6/4)",
  "page_number": 42,
  "chapter_number": 3,
  "percentage": 35.5,
  "chapter_reference": 3,
  "origin": "android"
}

Example response

{
  "id": "110e8400-e29b-41d4-a716-446655440000",
  "media_item_id": "550e8400-e29b-41d4-a716-446655440000",
  "user_id": "92413c3a-e1b8-4fff-b3f9-95c74478d19a",
  "page_number": 42,
  "chapter_number": 3,
  "cfi_position": "epubcfi(/6/4)",
  "title": "Chapter 3",
  "position": "kindle:pos:1:2",
  "notes": "revisit this",
  "created_at": "2026-10-24T13:57:01Z",
  "dedup_key": "kindle:pos:1:2",
  "last_modified_at": "2026-10-24T13:57:01Z",
  "last_modified_source": "android",
  "device_sync_data": null,
  "percentage_location": 35.5,
  "epubcfi_location": "epubcfi(/6/4)",
  "chapter_reference": 3,
  "deleted": false,
  "deleted_at": null,
  "origin_source": "android"
}

Request fields

Field Type Required Notes
title string yes 1–255 chars
position string no ≤100 chars
notes string no ≤100000 chars
cfi_position string no ≤255 chars
page_number number no
chapter_number number no
percentage number no
chapter_reference number no
origin string no client label ("android", "web"); defaults to "web"

Errors

Status Body When
400 {"error": "invalid request"} / validation error malformed body
500 {"error": "..."} annotation service failure