Files
bookhoard/docs/developer/api/media-items/bulk_update_media_items.md
T
John O'Keefe e21e1facde docs(media-items,collections,koreader,admin): Beam batch 11 — final backfill
All remaining endpoint docs frontmatter'd: media-item bulk ops + audio
surface, collections book-listing/preview, koreader rating/review/stats
plugin protocol, hash-conflicts JSON list.

Scope call (Claude): resolve_hash_conflict.md DELETED — the resolve POST
renders an htmx fragment (renderResolved), a web-admin flow under rule 3;
only the GET list is a JSON API. update_media_review skipped by Beam
(correct): ratings/upsert_media_review.md already covers the PUT.

Registry: 16 entries. koreader rating/review/stats all bind
koreaderBookRef (query or body) — odd=half-star rating scale; audio track
endpoint serves raw bytes (ServeContent, Range) — response nil. Fixed
drift: deleted_annotations doc's secondary restore/purge fences
unlabeled (gate validates labeled blocks against the ONE frontmatter
route); chapters example labeled. UNVERIFIED: 1 (koreader book-ref
fields, push_stats). make test 9/9.
2026-10-24 18:21:17 -04:00

4.0 KiB

method, path, auth, area
method path auth area
POST /api/media-items/bulk-update jwt media-items

Bulk Update Media Items

Update multiple media items at once (supports ebooks, comics, manga).

Endpoint: POST /api/media-items/bulk-update Auth: Required Content-Type: application/json

Request Body

Field Type Required Description
media_item_updates array of objects Yes Array of update operations
media_item_updates[].media_item_id string (UUID) Yes Media item UUID to update
media_item_updates[].updates object Yes Fields to update

Update Fields

Field Type Required Description
title string No Updated title
author string No Updated author
genre string No Updated genre
language string No Updated language (ISO 639-1 code)
tags array of strings No Updated tags (auto-normalized)

Example Request

{
  "media_item_updates": [
    {
      "media_item_id": "550e8400-e29b-41d4-a716-446655440001",
      "updates": {
        "title": "Updated Title",
        "genre": "Science Fiction",
        "tags": ["science fiction", "space opera", "ACME CORP."]
      }
    },
    {
      "media_item_id": "660e8400-e29b-41d4-a716-446655440002",
      "updates": {
        "author": "Updated Author Name",
        "language": "en"
      }
    }
  ]
}

Response (200 OK)

{
  "results": [
    {
      "media_item_id": "550e8400-e29b-41d4-a716-446655440001",
      "status": "success"
    },
    {
      "media_item_id": "660e8400-e29b-41d4-a716-446655440002",
      "status": "error",
      "error": "Media item not found"
    }
  ],
  "total": 2,
  "updated": 1,
  "failed": 1
}

Response Fields

Field Type Description
results array Individual result for each media item
results[].media_item_id string UUID of the media item
results[].status string "success" or "error"
results[].error string Error message (only present if status is "error")
total number Total number of media items processed
updated number Number of media items successfully updated
failed number Number of media items that failed to update

Tag and Contributor Normalization

The backend automatically normalizes tags:

  • Tags: Titlecased, punctuation preserved, deduplicated
  • Search fields: Lowercase, no punctuation, stored in tags_search

Error Responses

Code Description
400 Invalid request data or empty media_item_updates array
401 Invalid or expired token
403 User does not have permission
404 One or more media items not found
500 Server error during update

Notes

  • Partial success: The operation continues even if some updates fail
  • Invalid UUIDs: Invalid UUID formats are counted as failures
  • Non-existent items: Media items that don't exist are counted as failures
  • No changes: If updates object is empty, the item still counts as success