meta { name: Create Media Item type: http seq: 1 } post { url: {{base_url}}/api/media-items body: json auth: inherit } headers { Content-Type: application/json } body:json { "library_id": "{{library_id}}", "title": "New Media Item", "author": "Author Name", "isbn": "978-0123456789", "description": "Description of the media item", "cover_image_path": "/path/to/cover.jpg", "series": "Series Name", "series_number": 1, "tags": ["science fiction", "ACME CORP.", "non-fiction"], "asin": "B08XYZ123", "date_published": "2023-01-15", "publisher": "Publisher Name", "contributors": ["O'Reilly Media", "acme corp"], "language": "en", "edition": "First Edition", "page_count": 350, "genre": "Science Fiction", "copyright_year": 2023, "goodreads_id": "123456", "openlibrary_id": "OL123456M", "google_books_id": "GB123456" } tests { test_create_media_item_success(status, headers, body) { if (status !== 201) { throw new Error("Expected status 201, got " + status); } let data; try { data = JSON.parse(body); } catch (e) { throw new Error("Response body is not valid JSON"); } if (!data || typeof data !== "object") { throw new Error("Expected media item object in response"); } // Verify required fields if (!data.id || !data.title || !data.library_id) { throw new Error("Media item missing required fields: id, title, library_id"); } return true; } test_create_media_item_no_folders(status, headers, body) { if (status !== 400) { throw new Error("Expected status 400 for library with no folders, got " + status); } let data; try { data = JSON.parse(body); } catch (e) { throw new Error("Response body is not valid JSON"); } if (!data || typeof data !== 'object') { throw new Error("Expected error object in response"); } if (!data.error || typeof data.error !== 'string') { throw new Error("Expected error message in response"); } if (!data.error.includes("folder")) { throw new Error("Error message should mention folders requirement"); } return true; } } vars:pre-request { libraryId: "cc23c3a7-f8fb-451a-a78d-2a16df1b725a" } settings { encodeUrl: true timeout: 0 } docs { ## Create Media Item Creates a new media item in a library with full metadata. **Method:** POST **Endpoint:** /api/media-items **Authentication:** Required (Bearer token, admin only) **Prerequisites** - Library must have at least one folder configured before media items can be added - Use `POST /api/libraries/{library_id}/folders` to add folders first - See: [Add Library Folder](../../library/Add%20Library%20Folder.bru) **Request Body:** - `library_id` (string, required): Library UUID - `title` (string, required): Media item title - `author` (string, optional): Author name - `isbn` (string, optional): ISBN number - `description` (string, optional): Description - `cover_image_path` (string, optional): Path to cover image - `series` (string, optional): Series name - `series_number` (integer, optional): Number in series - `tags` (array of string, optional): Tags or categories (auto-normalized) (automatically normalized) - `asin` (string, optional): Amazon ASIN - `date_published` (string, optional): Publication date - `publisher` (string, optional): Publisher name - `contributors` (array of string, optional): List of contributors (auto-normalized) (automatically normalized) - `language` (string, optional): Language code (ISO 639-1) - `edition` (string, optional): Edition information - `page_count` (integer, optional): Total page count - `genre` (string, optional): Genre classification - `copyright_year` (integer, optional): Copyright year - `goodreads_id` (string, optional): Goodreads identifier - `openlibrary_id` (string, optional): Open Library identifier - `google_books_id` (string, optional): Google Books identifier **Response:** Created media item object - All fields above plus: - `tags_search` (array): Normalized for search (lowercase, no punctuation) - `contributors_search` (array): Normalized for search (lowercase, no punctuation) **Normalization Behavior:** Tags are automatically normalized: - Trim whitespace - Titlecased (preserves hyphenation: "non-fiction" → "Non-Fiction") - Case-insensitive deduplication (keeps version with punctuation if exists) - Example: `["science fiction", "SCIENCE-FICTION"]` → `["Science-Fiction"]` Contributors are automatically normalized: - Trim whitespace - Preserve original casing (CAPSLOCK companies, Title Case, etc.) - Preserve punctuation for display - Case-insensitive deduplication (keeps version with punctuation if exists) - Example: `["acme corp", "ACME CORP.", "acme corp"]` → `["ACME CORP."]` **Validation Error Response** - **400 Bad Request** - Library has no folders: ```json { "error": "Cannot add media items to a library with no folders. Please add at least one folder to the library first." } ``` **Status Codes:** - 201: Media item created successfully - 400: Invalid request data OR library has no folders - 401: Unauthorized - 403: Forbidden (admin access required) - 404: Library not found - 500: Internal server error **Setup Workflow Example:** ```bash # 1. Create library POST /api/libraries { "name": "My Books", "type": "ebooks" } # 2. Add folder to library (REQUIRED before adding media items) POST /api/libraries/{library_id}/folders { "folder_path": "/mnt/books/my-library" } # 3. Create media items (now that library has folders) POST /api/media-items { "library_id": "...", "title": "Book Title", ... } ``` **Examples:** - Create media item: `POST /api/media-items` **Note:** Admin access required - only users with admin role can create media items. }