meta { name: Filter Media Items type: http seq: 1 } get { url: {{base_url}}/api/media-items/filtered?library_id={{library_id}}&genre_filter=Fiction&language_filter=en&year_min=2000&year_max=2024&limit=10&offset=0 auth: inherit } headers { Content-Type: application/json } tests { test_filter_media_items(status, headers, body) { if (status !== 200) { throw new Error("Expected status 200, got " + status); } const contentType = headers["content-type"]; if (!contentType || !contentType.includes("application/json")) { throw new Error("Expected content-type to contain application/json, got " + contentType); } let data; try { const parsed = JSON.parse(body); data = parsed.data; } catch (e) { throw new Error("Response body is not valid JSON: " + e.message); } if (!Array.isArray(data)) { throw new Error("Expected response data to be an array"); } // Verify filters are applied data.forEach((item, index) => { if (!item || typeof item !== "object") { throw new Error("Media item at index " + index + " is not an object"); } if (!item.id) { throw new Error("Media item at index " + index + " missing required field: id"); } if (!item.title) { throw new Error("Media item at index " + index + " missing required field: title"); } if (!item.library_id) { throw new Error("Media item at index " + index + " missing required field: library_id"); } // Check genre filter if genre is specified if (item.genre && item.genre !== 'Fiction') { throw new Error("Item at index " + index + " has incorrect genre: " + item.genre); } // Check language filter if language is specified if (item.language && item.language !== 'en') { throw new Error("Item at index " + index + " has incorrect language: " + item.language); } // Check year range if specified if (item.copyright_year) { if (item.copyright_year < 2000 || item.copyright_year > 2024) { throw new Error("Item at index " + index + " has copyright_year outside range: " + item.copyright_year); } } }); return true; } } vars:pre-request { genre: "Fiction" language: "en" yearMin: 2000 yearMax: 2024 } settings { encodeUrl: true timeout: 0 } docs { ## Filter Media Items **Method:** GET **Endpoint:** /api/media-items/filtered **Authentication:** Required (Bearer token) **Query Parameters:** - `library_id` (string, required): UUID of the library - `author_filter` (string, optional): Filter by author (partial match) - `series_filter` (string, optional): Filter by series (partial match) - `genre_filter` (string, optional): Filter by genre (exact match) - `language_filter` (string, optional): Filter by language (exact match, e.g., 'en', 'es', 'fr') - `year_min` (integer, optional): Minimum copyright year - `year_max` (integer, optional): Maximum copyright year - `has_cover` (boolean, optional): Filter for items with cover images only - `sort` (string, optional): Sort field and direction (same options as ListMediaItems) - `limit` (integer, optional): Number of items to return (default: 50, max: 1000) - `offset` (integer, optional): Number of items to skip (default: 0) **Response:** Object containing array of filtered media items **Status Codes:** - 200: Success - 400: Bad request (invalid parameters) - 401: Unauthorized - 500: Internal server error **Examples:** - Filter by genre: `/api/media-items/filtered?library_id=xxx&genre_filter=Fiction` - Filter by language: `/api/media-items/filtered?library_id=xxx&language_filter=es` - Filter by year range: `/api/media-items/filtered?library_id=xxx&year_min=2000&year_max=2024` - Filter by cover: `/api/media-items/filtered?library_id=xxx&has_cover=true` - Combine filters: `/api/media-items/filtered?library_id=xxx&genre_filter=Sci-Fi&year_min=2010&language_filter=en` **Filter Behavior:** - Multiple filters can be combined (AND logic) - Author and series filters use partial matching (ILIKE) - Genre and language filters use exact matching - Year range filters are inclusive - Filters are applied before sorting and pagination - User library visibility is respected }