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

77 lines
2.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
method: POST
path: /api/media-items/:id/bookmarks
auth: jwt
area: media-items
---
<!-- source: internal/handlers/media.go:2206 MediaHandler.CreateMediaBookmark -->
# 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
```json 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
```json 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 |