Files
bookhoard/docs/developer/api/media-items/update_media_item.md
T
John O'Keefe 6f13dc2b63 docs(media-items core): Beam WO5 batch 4 — 12 endpoints backfilled, registry pinned
Beam backfilled list/get/create/update/delete media-item, search, ratings
CRUD, progress GET/PUT. Beam correctly identified create/update/delete as
jwt+admin (admin group in the router — verified).

Claude registry: 12 entries. Notable pins:
- get_media_item: hand-built ~44-key map pinned verbatim from the handler
- create/update return the full database.MediaItems row (74 columns) —
  examples merged up to the real shape via gate-driven merge script
- search returns []SearchMediaItemsRow (sqlc row — Real type pinned)
- rating scale is 1-10 int (odd = half-star); GET returns {rating: null} when
  absent; update reuses the create handler (201)
- progress GET: 25 base keys + 4 CONDITIONAL position-authority keys
  (css_selector/anchor_href/char_offset/context_text — added by the handler
  for convertible formats with a valid CFI); PUT progress binds
  sync.SaveProgressRequest and returns database.ReadingProgress
- Beam's examples were missing entirely on 4 files (list/search/progress
  GET/PUT) — relabeled existing fences or inserted contract-shaped blocks

Gate-driven merge scripts (object + array variants) brought all examples to
the exact handler key sets. make test 9/9.
2026-10-24 16:09:38 -04:00

3.8 KiB

method, path, auth, area
method path auth area
PUT /api/media-items/:id jwt+admin media-items

Update Media Item

Update media item metadata (Admin only).

Endpoint: PUT /api/media-items/{media_id} Auth: Required (Admin only) Content-Type: application/json

Path Parameters

Parameter Type Required Description
media_id string Yes Media item UUID

Request Body

Field Type Required Description
title string No Updated title
author string No Updated author
description string No Updated description
series string No Series name
series_number integer No Number in series
tags array of string No Updated tags (auto-normalized)
contributors array of string No Updated contributors (auto-normalized)

Tag/Contributor Normalization:

  • Tags are titlecased and deduplicated (case-insensitive)
  • Contributors preserve original casing and punctuation
  • Punctuation-preferred deduplication (keeps "ACME CORP." over "acme corp")
  • Search fields auto-generated for case-insensitive search

Example Request

{
  "title": "Updated Title",
  "author": "Updated Author",
  "description": "Updated description",
  "series": "Series",
  "series_number": 2
}

Response (200 OK)

{
  "id": "uuid",
  "title": "Updated Title",
  "author": "Updated Author",
  "description": "Updated description",
  "series": "Series",
  "series_number": 2,
  "updated_at": "2026-01-31T10:00:00Z",
  "abridged": null,
  "added_by_admin_id": null,
  "age_rating": null,
  "alternate_info": null,
  "archived_at": null,
  "asin": null,
  "audio_metadata": null,
  "authors": null,
  "authors_search": null,
  "chapter_count": null,
  "chapter_metadata": null,
  "community_rating": null,
  "contributors": null,
  "contributors_search": null,
  "copyright_year": null,
  "cover_image_path": null,
  "created_at": null,
  "date_published": null,
  "edition": null,
  "entitlement_id": null,
  "explicit": null,
  "file_path": null,
  "file_sha256": null,
  "file_size": null,
  "format_group": null,
  "format_mimetype": null,
  "genre": null,
  "goodreads_id": null,
  "google_books_id": null,
  "has_fixed_layout": null,
  "hash_confidence": null,
  "imported_at": null,
  "imprint": null,
  "is_black_and_white": null,
  "is_reflowable": null,
  "isbn": null,
  "kobo_content_id": null,
  "kobo_metadata": null,
  "language": null,
  "library_id": null,
  "library_type_name": null,
  "manga_type": null,
  "metadata_notes": null,
  "metadata_overrides": null,
  "mime_type": null,
  "missing_scan_count": null,
  "narrators": null,
  "narrators_search": null,
  "openlibrary_id": null,
  "opf_identifier": null,
  "opf_uuid": null,
  "page_count": null,
  "publisher": null,
  "publishers": null,
  "publishers_search": null,
  "reading_direction": null,
  "revision_number": null,
  "scan_information": null,
  "series_count": null,
  "story_arc": null,
  "subtitle": null,
  "summary": null,
  "tags": null,
  "tags_search": null,
  "total_characters": null,
  "volume": null,
  "web_url": null
}

Error Responses

Code Description
400 Invalid input data
401 Invalid or expired token
403 User is not an admin
404 Media item not found