mirror of
https://github.com/agregarr/agregarr.git
synced 2026-01-09 07:45:17 +08:00
14660 lines
469 KiB
YAML
14660 lines
469 KiB
YAML
openapi: '3.0.2'
|
|
info:
|
|
title: 'Agregarr API'
|
|
version: '1.0.0'
|
|
description: |
|
|
This is the documentation for the Agregarr API backend.
|
|
|
|
Two primary authentication methods are supported:
|
|
|
|
- **Cookie Authentication**: A valid sign-in to the `/auth/plex` or `/auth/local` will generate a valid authentication cookie.
|
|
- **API Key Authentication**: Sign-in is also possible by passing an `X-Api-Key` header along with a valid API Key generated by Agregarr.
|
|
contact:
|
|
name: Agregarr Team
|
|
url: https://github.com/agregarr/agregarr
|
|
license:
|
|
name: MIT
|
|
url: https://github.com/agregarr/agregarr/blob/main/LICENSE
|
|
tags:
|
|
- name: public
|
|
description: Public API endpoints requiring no authentication.
|
|
- name: auth
|
|
description: Endpoints related to logging in or out, and the currently authenticated user.
|
|
- name: users
|
|
description: Endpoints related to user management.
|
|
- name: settings-general
|
|
description: General application settings, initialization, and public configuration.
|
|
- name: settings-plex
|
|
description: Plex media server configuration and library management.
|
|
- name: settings-services
|
|
description: Download service configurations (Radarr & Sonarr).
|
|
- name: settings-integrations
|
|
description: External service integrations for collection sources (Tautulli, Trakt, MDBList, MyAnimeList, Overseerr).
|
|
- name: settings-system
|
|
description: System management including jobs, cache, and logs.
|
|
- name: search
|
|
description: Endpoints related to search and discovery.
|
|
- name: movies
|
|
description: Endpoints related to retrieving movies and their details.
|
|
- name: tv
|
|
description: Endpoints related to retrieving TV series and their details.
|
|
- name: other
|
|
description: Endpoints related to other TMDB data.
|
|
- name: tmdb
|
|
description: Endpoints related to retrieving TMDB assets, media, genres, and countries.
|
|
- name: media
|
|
description: Endpoints related to media management.
|
|
- name: collections
|
|
description: User-created collection management including CRUD operations, syncing, and reordering.
|
|
- name: collections-utility
|
|
description: Collection utility operations including preview, template validation, and source data fetching.
|
|
- name: collections-posters
|
|
description: Collection poster operations including upload, generation, and download.
|
|
- name: default-hubs
|
|
description: Default Plex algorithmic hub configuration (Recently Added, Continue Watching, etc.) including visibility and reordering.
|
|
- name: pre-existing-collections
|
|
description: Pre-existing Plex collection management including discovery, visibility configuration, and custom posters.
|
|
- name: hubs
|
|
description: Plex hub management and configuration operations.
|
|
- name: service
|
|
description: Endpoints related to getting service (Radarr/Sonarr) details.
|
|
- name: missing-items
|
|
description: Endpoints related to missing item request tracking and management.
|
|
- name: dashboard
|
|
description: Endpoints related to dashboard statistics and analytics.
|
|
- name: poster-templates
|
|
description: Poster template management including CRUD operations, validation, preview, and import/export.
|
|
- name: poster-assets
|
|
description: Poster icon and asset management including upload, download, and file serving.
|
|
- name: poster-saved
|
|
description: Saved poster instance management.
|
|
- name: source-colors
|
|
description: Managing global source color schemes for poster generation.
|
|
- name: exclusions
|
|
description: Managing global item exclusions for collections.
|
|
- name: overlays
|
|
description: Unified overlay template system for applying customizable badges, banners, and metadata to library posters. Create reusable templates with ratings, directors, resolution info, and more.
|
|
servers:
|
|
- url: '{server}/api/v1'
|
|
variables:
|
|
server:
|
|
default: http://localhost:7171
|
|
|
|
components:
|
|
schemas:
|
|
User:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
example: 1
|
|
readOnly: true
|
|
email:
|
|
type: string
|
|
example: 'hey@itsme.com'
|
|
readOnly: true
|
|
username:
|
|
type: string
|
|
plexToken:
|
|
type: string
|
|
readOnly: true
|
|
plexUsername:
|
|
type: string
|
|
readOnly: true
|
|
userType:
|
|
type: integer
|
|
example: 1
|
|
readOnly: true
|
|
permissions:
|
|
type: number
|
|
example: 0
|
|
avatar:
|
|
type: string
|
|
readOnly: true
|
|
createdAt:
|
|
type: string
|
|
example: '2020-09-02T05:02:23.000Z'
|
|
readOnly: true
|
|
updatedAt:
|
|
type: string
|
|
example: '2020-09-02T05:02:23.000Z'
|
|
readOnly: true
|
|
requestCount:
|
|
type: number
|
|
example: 5
|
|
readOnly: true
|
|
required:
|
|
- id
|
|
- email
|
|
- createdAt
|
|
- updatedAt
|
|
UserSettings:
|
|
type: object
|
|
properties:
|
|
locale:
|
|
type: string
|
|
region:
|
|
type: string
|
|
originalLanguage:
|
|
type: string
|
|
MainSettings:
|
|
type: object
|
|
properties:
|
|
apiKey:
|
|
type: string
|
|
readOnly: true
|
|
appLanguage:
|
|
type: string
|
|
example: en
|
|
applicationTitle:
|
|
type: string
|
|
example: Agregarr
|
|
applicationUrl:
|
|
type: string
|
|
example: https://os.example.com
|
|
trustProxy:
|
|
type: boolean
|
|
example: true
|
|
csrfProtection:
|
|
type: boolean
|
|
example: false
|
|
hideAvailable:
|
|
type: boolean
|
|
example: false
|
|
partialRequestsEnabled:
|
|
type: boolean
|
|
example: false
|
|
localLogin:
|
|
type: boolean
|
|
example: true
|
|
newPlexLogin:
|
|
type: boolean
|
|
example: true
|
|
placeholderMovieRootFolders:
|
|
type: object
|
|
additionalProperties:
|
|
type: string
|
|
description: Per-library movie placeholder root folders (libraryKey -> path)
|
|
example:
|
|
'1': /data/media/movies
|
|
'3': /data/media/movies-4k
|
|
placeholderTVRootFolders:
|
|
type: object
|
|
additionalProperties:
|
|
type: string
|
|
description: Per-library TV placeholder root folders (libraryKey -> path)
|
|
example:
|
|
'2': /data/media/tv
|
|
'4': /data/media/anime
|
|
PlexLibrary:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
name:
|
|
type: string
|
|
example: Movies
|
|
enabled:
|
|
type: boolean
|
|
example: false
|
|
required:
|
|
- id
|
|
- name
|
|
- enabled
|
|
PlexSettings:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
example: 'Main Server'
|
|
readOnly: true
|
|
machineId:
|
|
type: string
|
|
example: '1234123412341234'
|
|
readOnly: true
|
|
ip:
|
|
type: string
|
|
example: '127.0.0.1'
|
|
port:
|
|
type: number
|
|
example: 32400
|
|
useSsl:
|
|
type: boolean
|
|
nullable: true
|
|
libraries:
|
|
type: array
|
|
readOnly: true
|
|
items:
|
|
$ref: '#/components/schemas/PlexLibrary'
|
|
webAppUrl:
|
|
type: string
|
|
nullable: true
|
|
example: 'https://app.plex.tv/desktop'
|
|
required:
|
|
- name
|
|
- machineId
|
|
- ip
|
|
- port
|
|
CollectionConfig:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
description: 'Unique collection identifier (sequential number starting from 10000)'
|
|
example: '10000'
|
|
name:
|
|
type: string
|
|
example: 'User Requests'
|
|
type:
|
|
type: string
|
|
enum:
|
|
[
|
|
'overseerr',
|
|
'tautulli',
|
|
'trakt',
|
|
'tmdb',
|
|
'imdb',
|
|
'mdblist',
|
|
'letterboxd',
|
|
'networks',
|
|
'originals',
|
|
'plex',
|
|
'multi-source',
|
|
'anilist',
|
|
'myanimelist',
|
|
'radarrtag',
|
|
'sonarrtag',
|
|
'comingsoon',
|
|
'filtered_hub',
|
|
]
|
|
example: 'overseerr'
|
|
subtype:
|
|
type: string
|
|
example: 'users'
|
|
template:
|
|
type: string
|
|
example: "{nickname}'s Requests"
|
|
customMovieTemplate:
|
|
type: string
|
|
description: "Custom template for movie collections when mediaType is 'both'"
|
|
example: "{nickname}'s Movie Requests"
|
|
nullable: true
|
|
customTVTemplate:
|
|
type: string
|
|
description: "Custom template for TV collections when mediaType is 'both'"
|
|
example: "{nickname}'s TV Requests"
|
|
nullable: true
|
|
customPoster:
|
|
oneOf:
|
|
- type: string
|
|
description: 'Filename of custom poster image (legacy format)'
|
|
example: 'f47ac10b-58cc-4372-a567-0e02b2c3d479.jpg'
|
|
- type: object
|
|
description: 'Per-library poster mapping (libraryId -> filename)'
|
|
additionalProperties:
|
|
type: string
|
|
example:
|
|
lib1: 'f47ac10b-58cc-4372-a567-0e02b2c3d479.jpg'
|
|
lib2: 'a12bc34d-58cc-4372-a567-0e02b2c3d480.jpg'
|
|
nullable: true
|
|
autoPoster:
|
|
type: boolean
|
|
description: 'Auto-generate poster during sync'
|
|
example: true
|
|
nullable: true
|
|
autoPosterTemplate:
|
|
type: integer
|
|
description: 'Template ID for auto-generated posters (null for default template)'
|
|
example: 1
|
|
nullable: true
|
|
useTmdbFranchisePoster:
|
|
type: boolean
|
|
description: 'Use TMDB franchise poster instead of auto-generated poster (only for TMDB auto_franchise collections)'
|
|
example: false
|
|
nullable: true
|
|
hideIndividualItems:
|
|
type: boolean
|
|
description: 'Hide individual items, show collection (collectionMode = 1, only for TMDB auto_franchise collections)'
|
|
example: false
|
|
nullable: true
|
|
applyOverlaysDuringSync:
|
|
type: boolean
|
|
description: 'Apply item overlays during sync (for Coming Soon collections)'
|
|
example: true
|
|
nullable: true
|
|
customWallpaper:
|
|
oneOf:
|
|
- type: string
|
|
description: 'Filename of custom wallpaper image (art)'
|
|
example: 'wallpaper-12345.jpg'
|
|
- type: object
|
|
description: 'Per-library wallpaper mapping (libraryId -> filename)'
|
|
additionalProperties:
|
|
type: string
|
|
example:
|
|
lib1: 'wallpaper-12345.jpg'
|
|
lib2: 'wallpaper-67890.jpg'
|
|
nullable: true
|
|
customSummary:
|
|
type: string
|
|
description: 'Custom summary/description text for the collection'
|
|
example: 'A curated collection of the best movies'
|
|
nullable: true
|
|
customTheme:
|
|
oneOf:
|
|
- type: string
|
|
description: 'Filename of custom theme music file'
|
|
example: 'theme-12345.mp3'
|
|
- type: object
|
|
description: 'Per-library theme mapping (libraryId -> filename)'
|
|
additionalProperties:
|
|
type: string
|
|
example:
|
|
lib1: 'theme-12345.mp3'
|
|
lib2: 'theme-67890.mp3'
|
|
nullable: true
|
|
enableCustomWallpaper:
|
|
type: boolean
|
|
description: 'Enable custom wallpaper sync to Plex'
|
|
example: false
|
|
nullable: true
|
|
enableCustomSummary:
|
|
type: boolean
|
|
description: 'Enable custom summary sync to Plex'
|
|
example: false
|
|
nullable: true
|
|
enableCustomTheme:
|
|
type: boolean
|
|
description: 'Enable custom theme sync to Plex'
|
|
example: false
|
|
nullable: true
|
|
visibilityConfig:
|
|
type: object
|
|
properties:
|
|
usersHome:
|
|
type: boolean
|
|
description: "Show on shared users' home screens"
|
|
example: true
|
|
serverOwnerHome:
|
|
type: boolean
|
|
description: "Show on server owner's home screen"
|
|
example: false
|
|
libraryRecommended:
|
|
type: boolean
|
|
description: 'Show in library recommended section'
|
|
example: false
|
|
required:
|
|
- usersHome
|
|
- serverOwnerHome
|
|
- libraryRecommended
|
|
maxItems:
|
|
type: integer
|
|
example: 20
|
|
mediaType:
|
|
type: string
|
|
enum: ['movie', 'tv', 'both']
|
|
example: 'both'
|
|
libraryIds:
|
|
type: array
|
|
items:
|
|
type: string
|
|
description: "Array of selected library IDs (['all'] for all libraries)"
|
|
example: ['1', '2']
|
|
nullable: true
|
|
libraryName:
|
|
type: string
|
|
description: 'Selected library name for display'
|
|
example: 'Movies'
|
|
nullable: true
|
|
sortOrderHome:
|
|
type: integer
|
|
description: 'Order for Plex home screen (creation time based)'
|
|
example: 0
|
|
nullable: true
|
|
sortOrderLibrary:
|
|
type: integer
|
|
description: 'Position in library (0 for A-Z section, 1+ for promoted section)'
|
|
example: 0
|
|
nullable: true
|
|
isLibraryPromoted:
|
|
type: boolean
|
|
description: 'true = promoted section (uses exclamation marks), false = A-Z section'
|
|
example: true
|
|
randomizeHomeOrder:
|
|
type: boolean
|
|
description: 'If true, randomize position amongst other randomized items on home screen'
|
|
example: false
|
|
nullable: true
|
|
parentConfigId:
|
|
type: integer
|
|
description: "Reference to original config when expanded from 'all' libraries"
|
|
example: 1
|
|
nullable: true
|
|
isExpandedConfig:
|
|
type: boolean
|
|
description: "True if this config was auto-generated from a parent 'all' config"
|
|
example: false
|
|
nullable: true
|
|
customDays:
|
|
type: integer
|
|
description: 'Number of days for Tautulli collections (required for Tautulli type)'
|
|
example: 30
|
|
nullable: true
|
|
createPlaceholdersForMissing:
|
|
type: boolean
|
|
description: 'Create placeholder files for missing items (enabled by default for Coming Soon collections)'
|
|
example: false
|
|
nullable: true
|
|
placeholderDaysAhead:
|
|
type: integer
|
|
description: 'Days to look ahead for release dates when creating placeholders (default: 360)'
|
|
example: 360
|
|
nullable: true
|
|
placeholderReleasedDays:
|
|
type: integer
|
|
description: 'Days to keep released items with overlay before cleanup (default: 7)'
|
|
example: 7
|
|
nullable: true
|
|
comingSoonDays:
|
|
type: integer
|
|
description: 'DEPRECATED: Use placeholderDaysAhead instead'
|
|
deprecated: true
|
|
example: 360
|
|
nullable: true
|
|
comingSoonReleasedDays:
|
|
type: integer
|
|
description: 'DEPRECATED: Use placeholderReleasedDays instead'
|
|
deprecated: true
|
|
example: 7
|
|
nullable: true
|
|
minimumPlays:
|
|
type: integer
|
|
description: 'Minimum play count for Tautulli collections (defaults to 3 if not set, 1-100)'
|
|
example: 3
|
|
nullable: true
|
|
tautulliStatType:
|
|
type: string
|
|
enum: ['plays', 'duration']
|
|
description: 'Tautulli statistic type: plays (play count) or duration (watch time)'
|
|
example: 'plays'
|
|
nullable: true
|
|
searchMissingMovies:
|
|
type: boolean
|
|
description: 'Auto-request missing movies'
|
|
example: false
|
|
nullable: true
|
|
searchMissingTV:
|
|
type: boolean
|
|
description: 'Auto-request missing TV shows'
|
|
example: false
|
|
nullable: true
|
|
autoApproveMovies:
|
|
type: boolean
|
|
description: 'Auto-approve movie requests'
|
|
example: false
|
|
nullable: true
|
|
autoApproveTV:
|
|
type: boolean
|
|
description: 'Auto-approve TV show requests'
|
|
example: false
|
|
nullable: true
|
|
maxSeasonsToRequest:
|
|
type: integer
|
|
description: 'Max seasons for auto-approval (TV shows with more seasons require manual approval)'
|
|
example: 5
|
|
nullable: true
|
|
seasonsPerShowLimit:
|
|
type: integer
|
|
description: 'Limit each TV show to only the first X seasons (0 = all seasons)'
|
|
example: 2
|
|
nullable: true
|
|
seasonGrabOrder:
|
|
type: string
|
|
enum:
|
|
- first
|
|
- latest
|
|
- airing
|
|
description: 'Order to grab seasons: first N seasons (default), N latest seasons (including unreleased), or N most recently aired seasons'
|
|
example: 'first'
|
|
nullable: true
|
|
minimumYear:
|
|
type: integer
|
|
description: 'Only process movies/TV shows released on or after this year (0 = no limit)'
|
|
example: 2010
|
|
nullable: true
|
|
minimumImdbRating:
|
|
type: number
|
|
format: float
|
|
description: 'Only process movies/TV shows with IMDb rating >= this value (0 = no limit)'
|
|
example: 6.8
|
|
minimum: 0
|
|
maximum: 10
|
|
nullable: true
|
|
minimumRottenTomatoesRating:
|
|
type: number
|
|
format: float
|
|
description: 'Only process movies/TV shows with Rotten Tomatoes critics score >= this value (0 = no limit)'
|
|
example: 70
|
|
minimum: 0
|
|
maximum: 100
|
|
nullable: true
|
|
minimumRottenTomatoesAudienceRating:
|
|
type: number
|
|
format: float
|
|
description: 'Only process movies/TV shows with Rotten Tomatoes audience score >= this value (0 = no limit)'
|
|
example: 75
|
|
minimum: 0
|
|
maximum: 100
|
|
nullable: true
|
|
filterSettings:
|
|
type: object
|
|
description: 'Unified filter settings with include/exclude modes'
|
|
properties:
|
|
genres:
|
|
type: object
|
|
properties:
|
|
mode:
|
|
type: string
|
|
enum: ['exclude', 'include']
|
|
description: 'Filter mode: exclude items with these genres, or include only items with these genres'
|
|
example: 'exclude'
|
|
values:
|
|
type: array
|
|
items:
|
|
type: integer
|
|
description: 'TMDB genre IDs'
|
|
example: [28, 53]
|
|
countries:
|
|
type: object
|
|
properties:
|
|
mode:
|
|
type: string
|
|
enum: ['exclude', 'include']
|
|
description: 'Filter mode: exclude items from these countries, or include only items from these countries'
|
|
example: 'exclude'
|
|
values:
|
|
type: array
|
|
items:
|
|
type: string
|
|
description: 'ISO 3166-1 country codes'
|
|
example: ['JP', 'KR']
|
|
languages:
|
|
type: object
|
|
properties:
|
|
mode:
|
|
type: string
|
|
enum: ['exclude', 'include']
|
|
description: 'Filter mode: exclude items with these languages, or include only items with these languages'
|
|
example: 'exclude'
|
|
values:
|
|
type: array
|
|
items:
|
|
type: string
|
|
description: 'ISO 639-1 language codes'
|
|
example: ['ja', 'ko']
|
|
nullable: true
|
|
traktCustomListUrl:
|
|
type: string
|
|
description: 'Custom Trakt list URL (e.g., https://trakt.tv/users/username/lists/list-name or https://trakt.tv/lists/official/collection-name)'
|
|
example: 'https://trakt.tv/users/username/lists/my-list'
|
|
nullable: true
|
|
tmdbCustomCollectionUrl:
|
|
type: string
|
|
description: 'Custom TMDB collection or list URL (e.g., https://www.themoviedb.org/collection/123456 or https://www.themoviedb.org/list/310)'
|
|
example: 'https://www.themoviedb.org/list/310-my-movie-list'
|
|
nullable: true
|
|
imdbCustomListUrl:
|
|
type: string
|
|
description: 'Custom IMDb list URL (e.g., https://www.imdb.com/list/ls123456789/)'
|
|
example: 'https://www.imdb.com/list/ls123456789/'
|
|
nullable: true
|
|
mdblistCustomListUrl:
|
|
type: string
|
|
description: 'Custom MDBList list URL (e.g., https://mdblist.com/lists/username/listname)'
|
|
example: 'https://mdblist.com/lists/garycrawfordgc/netflix-shows'
|
|
nullable: true
|
|
sortOrder:
|
|
type: string
|
|
enum:
|
|
- default
|
|
- reverse
|
|
- random
|
|
- imdb_rating_desc
|
|
- imdb_rating_asc
|
|
description: 'Sort order for collection items'
|
|
example: 'default'
|
|
default: 'default'
|
|
nullable: true
|
|
personMinimumItems:
|
|
type: number
|
|
description: 'Unified minimum items required to create actor/director collections'
|
|
example: 3
|
|
nullable: true
|
|
useSeparator:
|
|
type: boolean
|
|
description: 'Create a separator collection for auto actor/director collections'
|
|
example: false
|
|
nullable: true
|
|
separatorTitle:
|
|
type: string
|
|
description: 'Title for the separator collection'
|
|
example: 'Actors Collections'
|
|
nullable: true
|
|
excludeFromCollections:
|
|
type: array
|
|
items:
|
|
type: string
|
|
description: 'Array of collection IDs to exclude items from (mutual exclusion)'
|
|
example: ['10001', '10002']
|
|
nullable: true
|
|
timeRestriction:
|
|
type: object
|
|
description: 'Time restriction settings for the collection'
|
|
properties:
|
|
alwaysActive:
|
|
type: boolean
|
|
description: 'If true, collection is always active (default)'
|
|
example: true
|
|
removeFromPlexWhenInactive:
|
|
type: boolean
|
|
description: 'If true, completely remove from Plex when inactive (old behavior)'
|
|
example: false
|
|
nullable: true
|
|
inactiveVisibilityConfig:
|
|
type: object
|
|
description: 'Visibility settings to use when collection is inactive (only used if removeFromPlexWhenInactive is false)'
|
|
properties:
|
|
usersHome:
|
|
type: boolean
|
|
description: "Show on shared users' home screens when inactive"
|
|
example: false
|
|
serverOwnerHome:
|
|
type: boolean
|
|
description: "Show on server owner's home screen when inactive"
|
|
example: false
|
|
libraryRecommended:
|
|
type: boolean
|
|
description: 'Show in library recommended section when inactive'
|
|
example: true
|
|
required:
|
|
- usersHome
|
|
- serverOwnerHome
|
|
- libraryRecommended
|
|
nullable: true
|
|
dateRanges:
|
|
type: array
|
|
description: 'Date ranges when collection should be active (repeated annually)'
|
|
items:
|
|
type: object
|
|
properties:
|
|
startDate:
|
|
type: string
|
|
description: "DD-MM format (e.g., '05-12' for 5th December)"
|
|
example: '05-12'
|
|
endDate:
|
|
type: string
|
|
description: "DD-MM format (e.g., '26-12' for 26th December)"
|
|
example: '26-12'
|
|
required:
|
|
- startDate
|
|
- endDate
|
|
nullable: true
|
|
weeklySchedule:
|
|
type: object
|
|
description: 'Days of the week when collection should be active'
|
|
properties:
|
|
monday:
|
|
type: boolean
|
|
example: true
|
|
tuesday:
|
|
type: boolean
|
|
example: true
|
|
wednesday:
|
|
type: boolean
|
|
example: true
|
|
thursday:
|
|
type: boolean
|
|
example: true
|
|
friday:
|
|
type: boolean
|
|
example: true
|
|
saturday:
|
|
type: boolean
|
|
example: false
|
|
sunday:
|
|
type: boolean
|
|
example: false
|
|
nullable: true
|
|
nullable: true
|
|
isActive:
|
|
type: boolean
|
|
description: 'Whether collection is currently active (time restrictions met)'
|
|
example: true
|
|
readOnly: true
|
|
collectionType:
|
|
type: string
|
|
enum: ['default_plex_hub', 'agregarr_created', 'pre_existing']
|
|
description: 'Backend categorization system for different collection types'
|
|
example: 'agregarr_created'
|
|
nullable: true
|
|
isLinked:
|
|
type: boolean
|
|
description: 'Whether collection is actively linked to other collections'
|
|
example: true
|
|
nullable: true
|
|
isUnlinked:
|
|
type: boolean
|
|
description: 'True if this collection was deliberately unlinked and should not be grouped with siblings'
|
|
example: false
|
|
nullable: true
|
|
missing:
|
|
type: boolean
|
|
description: 'True if collection no longer exists in Plex'
|
|
example: false
|
|
lastSyncedAt:
|
|
type: string
|
|
format: date-time
|
|
description: 'ISO timestamp of last successful sync to Plex'
|
|
example: '2024-01-15T10:30:00.000Z'
|
|
nullable: true
|
|
lastModifiedAt:
|
|
type: string
|
|
format: date-time
|
|
description: 'ISO timestamp when config was last modified'
|
|
example: '2024-01-15T09:15:00.000Z'
|
|
nullable: true
|
|
needsSync:
|
|
type: boolean
|
|
description: 'True if collection has been modified and needs to be synced to Plex'
|
|
example: false
|
|
nullable: true
|
|
showUnwatchedOnly:
|
|
type: boolean
|
|
description: 'Create a smart collection that shows only unwatched items from this collection'
|
|
example: false
|
|
nullable: true
|
|
smartCollectionSort:
|
|
type: object
|
|
description: 'Sort option for smart collections'
|
|
properties:
|
|
value:
|
|
type: string
|
|
description: "The sort parameter value (e.g., 'year:desc', 'titleSort', 'rating:desc')"
|
|
example: 'year:desc'
|
|
label:
|
|
type: string
|
|
description: 'Human-readable label for the dropdown'
|
|
example: 'Year (Newest First)'
|
|
nullable: true
|
|
required:
|
|
- id
|
|
- name
|
|
- type
|
|
- subtype
|
|
- template
|
|
- visibilityConfig
|
|
- maxItems
|
|
CollectionConfigCreate:
|
|
type: object
|
|
description: 'Schema for creating a new collection configuration'
|
|
properties:
|
|
id:
|
|
type: string
|
|
description: 'Empty string for new collections (will be assigned sequential number by backend)'
|
|
example: ''
|
|
name:
|
|
type: string
|
|
example: 'User Requests'
|
|
type:
|
|
type: string
|
|
enum:
|
|
[
|
|
'overseerr',
|
|
'tautulli',
|
|
'trakt',
|
|
'tmdb',
|
|
'imdb',
|
|
'mdblist',
|
|
'letterboxd',
|
|
'networks',
|
|
'originals',
|
|
'plex',
|
|
'multi-source',
|
|
'anilist',
|
|
'myanimelist',
|
|
'radarrtag',
|
|
'sonarrtag',
|
|
'comingsoon',
|
|
'filtered_hub',
|
|
]
|
|
example: 'overseerr'
|
|
subtype:
|
|
type: string
|
|
example: 'users'
|
|
template:
|
|
type: string
|
|
example: "{nickname}'s Requests"
|
|
customMovieTemplate:
|
|
type: string
|
|
description: "Custom template for movie collections when mediaType is 'both'"
|
|
example: "{nickname}'s Movie Requests"
|
|
nullable: true
|
|
customTVTemplate:
|
|
type: string
|
|
description: "Custom template for TV collections when mediaType is 'both'"
|
|
example: "{nickname}'s TV Requests"
|
|
nullable: true
|
|
customPoster:
|
|
oneOf:
|
|
- type: string
|
|
description: 'Filename of custom poster image (legacy format)'
|
|
example: 'f47ac10b-58cc-4372-a567-0e02b2c3d479.jpg'
|
|
- type: object
|
|
description: 'Per-library poster mapping (libraryId -> filename)'
|
|
additionalProperties:
|
|
type: string
|
|
example:
|
|
lib1: 'f47ac10b-58cc-4372-a567-0e02b2c3d479.jpg'
|
|
lib2: 'a12bc34d-58cc-4372-a567-0e02b2c3d480.jpg'
|
|
nullable: true
|
|
autoPoster:
|
|
type: boolean
|
|
description: 'Auto-generate poster during sync'
|
|
example: true
|
|
nullable: true
|
|
autoPosterTemplate:
|
|
type: integer
|
|
description: 'Template ID for auto-generated posters (null for default template)'
|
|
example: 1
|
|
nullable: true
|
|
useTmdbFranchisePoster:
|
|
type: boolean
|
|
description: 'Use TMDB franchise poster instead of auto-generated poster (only for TMDB auto_franchise collections)'
|
|
example: false
|
|
nullable: true
|
|
hideIndividualItems:
|
|
type: boolean
|
|
description: 'Hide individual items, show collection (collectionMode = 1, only for TMDB auto_franchise collections)'
|
|
example: false
|
|
nullable: true
|
|
applyOverlaysDuringSync:
|
|
type: boolean
|
|
description: 'Apply item overlays during sync (for Coming Soon collections)'
|
|
example: true
|
|
nullable: true
|
|
customWallpaper:
|
|
oneOf:
|
|
- type: string
|
|
description: 'Filename of custom wallpaper image (art)'
|
|
example: 'wallpaper-12345.jpg'
|
|
- type: object
|
|
description: 'Per-library wallpaper mapping (libraryId -> filename)'
|
|
additionalProperties:
|
|
type: string
|
|
example:
|
|
lib1: 'wallpaper-12345.jpg'
|
|
lib2: 'wallpaper-67890.jpg'
|
|
nullable: true
|
|
customSummary:
|
|
type: string
|
|
description: 'Custom summary/description text for the collection'
|
|
example: 'A curated collection of the best movies'
|
|
nullable: true
|
|
customTheme:
|
|
oneOf:
|
|
- type: string
|
|
description: 'Filename of custom theme music file'
|
|
example: 'theme-12345.mp3'
|
|
- type: object
|
|
description: 'Per-library theme mapping (libraryId -> filename)'
|
|
additionalProperties:
|
|
type: string
|
|
example:
|
|
lib1: 'theme-12345.mp3'
|
|
lib2: 'theme-67890.mp3'
|
|
nullable: true
|
|
enableCustomWallpaper:
|
|
type: boolean
|
|
description: 'Enable custom wallpaper sync to Plex'
|
|
example: false
|
|
nullable: true
|
|
enableCustomSummary:
|
|
type: boolean
|
|
description: 'Enable custom summary sync to Plex'
|
|
example: false
|
|
nullable: true
|
|
enableCustomTheme:
|
|
type: boolean
|
|
description: 'Enable custom theme sync to Plex'
|
|
example: false
|
|
nullable: true
|
|
visibilityConfig:
|
|
type: object
|
|
properties:
|
|
usersHome:
|
|
type: boolean
|
|
description: "Show on shared users' home screens"
|
|
example: true
|
|
serverOwnerHome:
|
|
type: boolean
|
|
description: "Show on server owner's home screen"
|
|
example: false
|
|
libraryRecommended:
|
|
type: boolean
|
|
description: 'Show in library recommended section'
|
|
example: false
|
|
required:
|
|
- usersHome
|
|
- serverOwnerHome
|
|
- libraryRecommended
|
|
maxItems:
|
|
type: integer
|
|
example: 20
|
|
mediaType:
|
|
type: string
|
|
enum: ['movie', 'tv', 'both']
|
|
example: 'both'
|
|
libraryId:
|
|
type: string
|
|
description: "Selected library ID - each config is for exactly one library (optional when mediaType is 'both')"
|
|
example: '1'
|
|
libraryName:
|
|
type: string
|
|
description: "Selected library name for display (optional when mediaType is 'both')"
|
|
example: 'Movies'
|
|
libraryIds:
|
|
type: array
|
|
items:
|
|
type: string
|
|
description: "Array of library IDs when mediaType is 'both' (backend expands into individual configs)"
|
|
example: ['1', '2']
|
|
libraryNames:
|
|
type: array
|
|
items:
|
|
type: string
|
|
description: "Array of library names when mediaType is 'both' (backend expands into individual configs)"
|
|
example: ['Movies', 'TV Shows']
|
|
sortOrderHome:
|
|
type: integer
|
|
description: 'Order for Plex home screen (creation time based)'
|
|
example: 0
|
|
nullable: true
|
|
sortOrderLibrary:
|
|
type: integer
|
|
description: 'Order for Plex library tab (sortTitle based)'
|
|
example: 0
|
|
nullable: true
|
|
randomizeHomeOrder:
|
|
type: boolean
|
|
description: 'If true, randomize position amongst other randomized items on home screen'
|
|
example: false
|
|
nullable: true
|
|
customDays:
|
|
type: integer
|
|
description: 'Number of days for Tautulli collections (required for Tautulli type)'
|
|
example: 30
|
|
nullable: true
|
|
createPlaceholdersForMissing:
|
|
type: boolean
|
|
description: 'Create placeholder files for missing items (enabled by default for Coming Soon collections)'
|
|
example: false
|
|
nullable: true
|
|
placeholderDaysAhead:
|
|
type: integer
|
|
description: 'Days to look ahead for release dates when creating placeholders (default: 360)'
|
|
example: 360
|
|
nullable: true
|
|
placeholderReleasedDays:
|
|
type: integer
|
|
description: 'Days to keep released items with overlay before cleanup (default: 7)'
|
|
example: 7
|
|
nullable: true
|
|
minimumPlays:
|
|
type: integer
|
|
description: 'Minimum play count for Tautulli collections (defaults to 3 if not set, 1-100)'
|
|
example: 3
|
|
nullable: true
|
|
tautulliStatType:
|
|
type: string
|
|
enum: ['plays', 'duration']
|
|
description: 'Tautulli statistic type: plays (play count) or duration (watch time)'
|
|
example: 'plays'
|
|
nullable: true
|
|
searchMissingMovies:
|
|
type: boolean
|
|
description: 'Auto-request missing movies'
|
|
example: false
|
|
nullable: true
|
|
searchMissingTV:
|
|
type: boolean
|
|
description: 'Auto-request missing TV shows'
|
|
example: false
|
|
nullable: true
|
|
autoApproveMovies:
|
|
type: boolean
|
|
description: 'Auto-approve movie requests'
|
|
example: false
|
|
nullable: true
|
|
autoApproveTV:
|
|
type: boolean
|
|
description: 'Auto-approve TV show requests'
|
|
example: false
|
|
nullable: true
|
|
maxSeasonsToRequest:
|
|
type: integer
|
|
description: 'Max seasons for auto-approval (TV shows with more seasons require manual approval)'
|
|
example: 5
|
|
nullable: true
|
|
seasonsPerShowLimit:
|
|
type: integer
|
|
description: 'Limit each TV show to only the first X seasons (0 = all seasons)'
|
|
example: 2
|
|
nullable: true
|
|
seasonGrabOrder:
|
|
type: string
|
|
enum:
|
|
- first
|
|
- latest
|
|
- airing
|
|
description: 'Order to grab seasons: first N seasons (default), N latest seasons (including unreleased), or N most recently aired seasons'
|
|
example: 'first'
|
|
nullable: true
|
|
minimumYear:
|
|
type: integer
|
|
description: 'Only process movies/TV shows released on or after this year (0 = no limit)'
|
|
example: 2010
|
|
nullable: true
|
|
minimumImdbRating:
|
|
type: number
|
|
format: float
|
|
description: 'Only process movies/TV shows with IMDb rating >= this value (0 = no limit)'
|
|
example: 6.8
|
|
minimum: 0
|
|
maximum: 10
|
|
nullable: true
|
|
minimumRottenTomatoesRating:
|
|
type: number
|
|
format: float
|
|
description: 'Only process movies/TV shows with Rotten Tomatoes critics score >= this value (0 = no limit)'
|
|
example: 70
|
|
minimum: 0
|
|
maximum: 100
|
|
nullable: true
|
|
minimumRottenTomatoesAudienceRating:
|
|
type: number
|
|
format: float
|
|
description: 'Only process movies/TV shows with Rotten Tomatoes audience score >= this value (0 = no limit)'
|
|
example: 75
|
|
minimum: 0
|
|
maximum: 100
|
|
nullable: true
|
|
filterSettings:
|
|
type: object
|
|
description: 'Unified filter settings with include/exclude modes'
|
|
properties:
|
|
genres:
|
|
type: object
|
|
properties:
|
|
mode:
|
|
type: string
|
|
enum: ['exclude', 'include']
|
|
description: 'Filter mode: exclude items with these genres, or include only items with these genres'
|
|
example: 'exclude'
|
|
values:
|
|
type: array
|
|
items:
|
|
type: integer
|
|
description: 'TMDB genre IDs'
|
|
example: [28, 53]
|
|
countries:
|
|
type: object
|
|
properties:
|
|
mode:
|
|
type: string
|
|
enum: ['exclude', 'include']
|
|
description: 'Filter mode: exclude items from these countries, or include only items from these countries'
|
|
example: 'exclude'
|
|
values:
|
|
type: array
|
|
items:
|
|
type: string
|
|
description: 'ISO 3166-1 country codes'
|
|
example: ['JP', 'KR']
|
|
languages:
|
|
type: object
|
|
properties:
|
|
mode:
|
|
type: string
|
|
enum: ['exclude', 'include']
|
|
description: 'Filter mode: exclude items with these languages, or include only items with these languages'
|
|
example: 'exclude'
|
|
values:
|
|
type: array
|
|
items:
|
|
type: string
|
|
description: 'ISO 639-1 language codes'
|
|
example: ['ja', 'ko']
|
|
nullable: true
|
|
traktCustomListUrl:
|
|
type: string
|
|
description: 'Custom Trakt list URL (e.g., https://trakt.tv/users/username/lists/list-name or https://trakt.tv/lists/official/collection-name)'
|
|
example: 'https://trakt.tv/users/username/lists/my-list'
|
|
nullable: true
|
|
tmdbCustomCollectionUrl:
|
|
type: string
|
|
description: 'Custom TMDB collection or list URL (e.g., https://www.themoviedb.org/collection/123456 or https://www.themoviedb.org/list/310)'
|
|
example: 'https://www.themoviedb.org/list/310-my-movie-list'
|
|
nullable: true
|
|
imdbCustomListUrl:
|
|
type: string
|
|
description: 'Custom IMDb list URL (e.g., https://www.imdb.com/list/ls123456789/)'
|
|
example: 'https://www.imdb.com/list/ls123456789/'
|
|
nullable: true
|
|
mdblistCustomListUrl:
|
|
type: string
|
|
description: 'Custom MDBList list URL (e.g., https://mdblist.com/lists/username/listname)'
|
|
example: 'https://mdblist.com/lists/garycrawfordgc/netflix-shows'
|
|
nullable: true
|
|
sortOrder:
|
|
type: string
|
|
enum:
|
|
- default
|
|
- reverse
|
|
- random
|
|
- imdb_rating_desc
|
|
- imdb_rating_asc
|
|
description: 'Sort order for collection items'
|
|
example: 'default'
|
|
default: 'default'
|
|
nullable: true
|
|
personMinimumItems:
|
|
type: number
|
|
description: 'Unified minimum items required to create actor/director collections'
|
|
example: 3
|
|
nullable: true
|
|
useSeparator:
|
|
type: boolean
|
|
description: 'Create a separator collection for auto actor/director collections'
|
|
example: false
|
|
nullable: true
|
|
separatorTitle:
|
|
type: string
|
|
description: 'Title for the separator collection'
|
|
example: 'Actors Collections'
|
|
nullable: true
|
|
excludeFromCollections:
|
|
type: array
|
|
items:
|
|
type: string
|
|
description: 'Array of collection IDs to exclude items from (mutual exclusion)'
|
|
example: ['10001', '10002']
|
|
nullable: true
|
|
timeRestriction:
|
|
type: object
|
|
description: 'Time restriction settings for the collection'
|
|
properties:
|
|
alwaysActive:
|
|
type: boolean
|
|
description: 'If true, collection is always active (default)'
|
|
example: true
|
|
removeFromPlexWhenInactive:
|
|
type: boolean
|
|
description: 'If true, completely remove from Plex when inactive (old behavior)'
|
|
example: false
|
|
nullable: true
|
|
inactiveVisibilityConfig:
|
|
type: object
|
|
description: 'Visibility settings to use when collection is inactive (only used if removeFromPlexWhenInactive is false)'
|
|
properties:
|
|
usersHome:
|
|
type: boolean
|
|
description: "Show on shared users' home screens when inactive"
|
|
example: false
|
|
serverOwnerHome:
|
|
type: boolean
|
|
description: "Show on server owner's home screen when inactive"
|
|
example: false
|
|
libraryRecommended:
|
|
type: boolean
|
|
description: 'Show in library recommended section when inactive'
|
|
example: true
|
|
required:
|
|
- usersHome
|
|
- serverOwnerHome
|
|
- libraryRecommended
|
|
nullable: true
|
|
dateRanges:
|
|
type: array
|
|
description: 'Date ranges when collection should be active (repeated annually)'
|
|
items:
|
|
type: object
|
|
properties:
|
|
startDate:
|
|
type: string
|
|
description: "DD-MM format (e.g., '05-12' for 5th December)"
|
|
example: '05-12'
|
|
endDate:
|
|
type: string
|
|
description: "DD-MM format (e.g., '26-12' for 26th December)"
|
|
example: '26-12'
|
|
required:
|
|
- startDate
|
|
- endDate
|
|
nullable: true
|
|
weeklySchedule:
|
|
type: object
|
|
description: 'Days of the week when collection should be active'
|
|
properties:
|
|
monday:
|
|
type: boolean
|
|
example: true
|
|
tuesday:
|
|
type: boolean
|
|
example: true
|
|
wednesday:
|
|
type: boolean
|
|
example: true
|
|
thursday:
|
|
type: boolean
|
|
example: true
|
|
friday:
|
|
type: boolean
|
|
example: true
|
|
saturday:
|
|
type: boolean
|
|
example: false
|
|
sunday:
|
|
type: boolean
|
|
example: false
|
|
nullable: true
|
|
nullable: true
|
|
# Multi-source collection properties
|
|
isMultiSource:
|
|
type: boolean
|
|
description: 'Enable multi-source mode for combining multiple collection sources'
|
|
example: false
|
|
nullable: true
|
|
sources:
|
|
type: array
|
|
description: 'Array of source configurations for multi-source collections'
|
|
items:
|
|
$ref: '#/components/schemas/CollectionSourceConfig'
|
|
nullable: true
|
|
combineMode:
|
|
type: string
|
|
enum: ['interleaved', 'list_order', 'randomised', 'cycle_lists']
|
|
description: 'How to combine multiple sources: interleaved (alternate items), list_order (all from first, then second), randomised (shuffle all), cycle_lists (rotate active source)'
|
|
example: 'list_order'
|
|
nullable: true
|
|
customSyncSchedule:
|
|
type: object
|
|
description: 'Custom sync schedule configuration'
|
|
properties:
|
|
enabled:
|
|
type: boolean
|
|
description: 'Enable custom sync schedule'
|
|
example: false
|
|
scheduleType:
|
|
type: string
|
|
enum: ['preset', 'custom']
|
|
description: 'Type of schedule: preset dropdown or custom cron'
|
|
example: 'preset'
|
|
intervalHours:
|
|
type: number
|
|
description: "Legacy field for backward compatibility (when scheduleType === 'preset')"
|
|
example: 24.0
|
|
minimum: 0.1
|
|
maximum: 8760
|
|
nullable: true
|
|
preset:
|
|
type: string
|
|
description: "Preset option key (e.g., '10m', '30m', '1h', '6h', '1d', '1w')"
|
|
example: '1d'
|
|
nullable: true
|
|
customCron:
|
|
type: string
|
|
description: "Custom cron expression (when scheduleType === 'custom')"
|
|
example: '0 9 * * MON'
|
|
nullable: true
|
|
startNow:
|
|
type: boolean
|
|
description: 'If true, start immediately; if false, use startDate/startTime'
|
|
example: true
|
|
startDate:
|
|
type: string
|
|
description: "Start date in DD-MM format (e.g., '01-01' for January 1st)"
|
|
example: '01-01'
|
|
pattern: '^(0[1-9]|[12][0-9]|3[01])-(0[1-9]|1[0-2])$'
|
|
nullable: true
|
|
startTime:
|
|
type: string
|
|
description: "Start time in HH:MM format (e.g., '09:00')"
|
|
example: '09:00'
|
|
pattern: '^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$'
|
|
nullable: true
|
|
firstSyncAt:
|
|
type: string
|
|
format: date-time
|
|
description: 'ISO timestamp of when this schedule was first created (for persistence across restarts)'
|
|
example: '2024-01-01T09:00:00.000Z'
|
|
nullable: true
|
|
nullable: true
|
|
downloadMode:
|
|
type: string
|
|
enum: ['overseerr', 'direct']
|
|
description: 'Download method: overseerr (requests) or direct (*arr)'
|
|
example: 'overseerr'
|
|
nullable: true
|
|
directDownloadRadarrServerId:
|
|
type: integer
|
|
description: "Selected Radarr server ID for movies (when downloadMode is 'direct')"
|
|
example: 1
|
|
nullable: true
|
|
directDownloadRadarrProfileId:
|
|
type: integer
|
|
description: "Selected Radarr profile ID for movies (when downloadMode is 'direct')"
|
|
example: 3
|
|
nullable: true
|
|
directDownloadRadarrRootFolder:
|
|
type: string
|
|
description: "Selected Radarr root folder path for movies (when downloadMode is 'direct')"
|
|
example: '/movies'
|
|
nullable: true
|
|
directDownloadRadarrTags:
|
|
type: array
|
|
items:
|
|
type: integer
|
|
description: "Selected Radarr tags for movies (when downloadMode is 'direct')"
|
|
example: [1, 2]
|
|
nullable: true
|
|
directDownloadRadarrMonitor:
|
|
type: boolean
|
|
description: "Override Radarr monitor setting for movies (when downloadMode is 'direct')"
|
|
example: true
|
|
nullable: true
|
|
directDownloadRadarrSearchOnAdd:
|
|
type: boolean
|
|
description: "Override Radarr search on add setting for movies (when downloadMode is 'direct')"
|
|
example: true
|
|
nullable: true
|
|
directDownloadSonarrServerId:
|
|
type: integer
|
|
description: "Selected Sonarr server ID for TV shows (when downloadMode is 'direct')"
|
|
example: 1
|
|
nullable: true
|
|
directDownloadSonarrProfileId:
|
|
type: integer
|
|
description: "Selected Sonarr profile ID for TV shows (when downloadMode is 'direct')"
|
|
example: 2
|
|
nullable: true
|
|
directDownloadSonarrRootFolder:
|
|
type: string
|
|
description: "Selected Sonarr root folder path for TV shows (when downloadMode is 'direct')"
|
|
example: '/tv'
|
|
nullable: true
|
|
directDownloadSonarrTags:
|
|
type: array
|
|
items:
|
|
type: integer
|
|
description: "Selected Sonarr tags for TV shows (when downloadMode is 'direct')"
|
|
example: [1, 2]
|
|
nullable: true
|
|
directDownloadSonarrMonitor:
|
|
type: boolean
|
|
description: "Override Sonarr monitor setting for TV shows (when downloadMode is 'direct')"
|
|
example: true
|
|
nullable: true
|
|
directDownloadSonarrSearchOnAdd:
|
|
type: boolean
|
|
description: "Override Sonarr search on add setting for TV shows (when downloadMode is 'direct')"
|
|
example: true
|
|
nullable: true
|
|
overseerrRadarrServerId:
|
|
type: integer
|
|
description: "Override Radarr server ID for Overseerr movie requests (when downloadMode is 'overseerr')"
|
|
example: 1
|
|
nullable: true
|
|
overseerrRadarrProfileId:
|
|
type: integer
|
|
description: "Override Radarr profile ID for Overseerr movie requests (when downloadMode is 'overseerr')"
|
|
example: 3
|
|
nullable: true
|
|
overseerrRadarrRootFolder:
|
|
type: string
|
|
description: "Override Radarr root folder path for Overseerr movie requests (when downloadMode is 'overseerr')"
|
|
example: '/movies'
|
|
nullable: true
|
|
overseerrRadarrTags:
|
|
type: array
|
|
items:
|
|
type: integer
|
|
description: "Override Radarr tags for Overseerr movie requests (when downloadMode is 'overseerr')"
|
|
example: [1, 2]
|
|
nullable: true
|
|
overseerrSonarrServerId:
|
|
type: integer
|
|
description: "Override Sonarr server ID for Overseerr TV requests (when downloadMode is 'overseerr')"
|
|
example: 1
|
|
nullable: true
|
|
overseerrSonarrProfileId:
|
|
type: integer
|
|
description: "Override Sonarr profile ID for Overseerr TV requests (when downloadMode is 'overseerr')"
|
|
example: 2
|
|
nullable: true
|
|
overseerrSonarrRootFolder:
|
|
type: string
|
|
description: "Override Sonarr root folder path for Overseerr TV requests (when downloadMode is 'overseerr')"
|
|
example: '/tv'
|
|
nullable: true
|
|
overseerrSonarrTags:
|
|
type: array
|
|
items:
|
|
type: integer
|
|
description: "Override Sonarr tags for Overseerr TV requests (when downloadMode is 'overseerr')"
|
|
example: [1, 2]
|
|
nullable: true
|
|
showUnwatchedOnly:
|
|
type: boolean
|
|
description: 'Create a smart collection that shows only unwatched items from this collection'
|
|
example: false
|
|
nullable: true
|
|
smartCollectionSort:
|
|
type: object
|
|
description: 'Sort option for smart collections'
|
|
properties:
|
|
value:
|
|
type: string
|
|
description: "The sort parameter value (e.g., 'year:desc', 'titleSort', 'rating:desc')"
|
|
example: 'year:desc'
|
|
label:
|
|
type: string
|
|
description: 'Human-readable label for the dropdown'
|
|
example: 'Year (Newest First)'
|
|
nullable: true
|
|
required:
|
|
- id
|
|
- name
|
|
- visibilityConfig
|
|
- maxItems
|
|
|
|
CollectionConfigUpdate:
|
|
type: object
|
|
description: 'Schema for updating collection configuration settings (excludes computed fields)'
|
|
properties:
|
|
id:
|
|
type: string
|
|
description: 'Unique collection identifier (sequential number starting from 10000)'
|
|
example: '10000'
|
|
name:
|
|
type: string
|
|
example: 'User Requests'
|
|
type:
|
|
type: string
|
|
enum:
|
|
[
|
|
'overseerr',
|
|
'tautulli',
|
|
'trakt',
|
|
'tmdb',
|
|
'imdb',
|
|
'mdblist',
|
|
'letterboxd',
|
|
'networks',
|
|
'originals',
|
|
'plex',
|
|
'multi-source',
|
|
'anilist',
|
|
'myanimelist',
|
|
'radarrtag',
|
|
'sonarrtag',
|
|
'comingsoon',
|
|
'filtered_hub',
|
|
]
|
|
example: 'overseerr'
|
|
subtype:
|
|
type: string
|
|
example: 'users'
|
|
template:
|
|
type: string
|
|
example: "{nickname}'s Requests"
|
|
customMovieTemplate:
|
|
type: string
|
|
description: "Custom template for movie collections when mediaType is 'both'"
|
|
example: "{nickname}'s Movie Requests"
|
|
nullable: true
|
|
customTVTemplate:
|
|
type: string
|
|
description: "Custom template for TV collections when mediaType is 'both'"
|
|
example: "{nickname}'s TV Requests"
|
|
nullable: true
|
|
customPoster:
|
|
oneOf:
|
|
- type: string
|
|
description: 'Filename of custom poster image (legacy format)'
|
|
example: 'f47ac10b-58cc-4372-a567-0e02b2c3d479.jpg'
|
|
- type: object
|
|
description: 'Per-library poster mapping (libraryId -> filename)'
|
|
additionalProperties:
|
|
type: string
|
|
example:
|
|
lib1: 'f47ac10b-58cc-4372-a567-0e02b2c3d479.jpg'
|
|
lib2: 'a12bc34d-58cc-4372-a567-0e02b2c3d480.jpg'
|
|
nullable: true
|
|
autoPoster:
|
|
type: boolean
|
|
description: 'Auto-generate poster during sync'
|
|
example: true
|
|
nullable: true
|
|
autoPosterTemplate:
|
|
type: integer
|
|
description: 'Template ID for auto-generated posters (null for default template)'
|
|
example: 1
|
|
nullable: true
|
|
useTmdbFranchisePoster:
|
|
type: boolean
|
|
description: 'Use TMDB franchise poster instead of auto-generated poster (only for TMDB auto_franchise collections)'
|
|
example: false
|
|
nullable: true
|
|
hideIndividualItems:
|
|
type: boolean
|
|
description: 'Hide individual items, show collection (collectionMode = 1, only for TMDB auto_franchise collections)'
|
|
example: false
|
|
nullable: true
|
|
applyOverlaysDuringSync:
|
|
type: boolean
|
|
description: 'Apply item overlays during sync (for Coming Soon collections)'
|
|
example: true
|
|
nullable: true
|
|
customWallpaper:
|
|
oneOf:
|
|
- type: string
|
|
description: 'Filename of custom wallpaper image (art)'
|
|
example: 'wallpaper-12345.jpg'
|
|
- type: object
|
|
description: 'Per-library wallpaper mapping (libraryId -> filename)'
|
|
additionalProperties:
|
|
type: string
|
|
example:
|
|
lib1: 'wallpaper-12345.jpg'
|
|
lib2: 'wallpaper-67890.jpg'
|
|
nullable: true
|
|
customSummary:
|
|
type: string
|
|
description: 'Custom summary/description text for the collection'
|
|
example: 'A curated collection of the best movies'
|
|
nullable: true
|
|
customTheme:
|
|
oneOf:
|
|
- type: string
|
|
description: 'Filename of custom theme music file'
|
|
example: 'theme-12345.mp3'
|
|
- type: object
|
|
description: 'Per-library theme mapping (libraryId -> filename)'
|
|
additionalProperties:
|
|
type: string
|
|
example:
|
|
lib1: 'theme-12345.mp3'
|
|
lib2: 'theme-67890.mp3'
|
|
nullable: true
|
|
enableCustomWallpaper:
|
|
type: boolean
|
|
description: 'Enable custom wallpaper sync to Plex'
|
|
example: false
|
|
nullable: true
|
|
enableCustomSummary:
|
|
type: boolean
|
|
description: 'Enable custom summary sync to Plex'
|
|
example: false
|
|
nullable: true
|
|
enableCustomTheme:
|
|
type: boolean
|
|
description: 'Enable custom theme sync to Plex'
|
|
example: false
|
|
nullable: true
|
|
visibilityConfig:
|
|
type: object
|
|
properties:
|
|
usersHome:
|
|
type: boolean
|
|
description: "Show on shared users' home screens"
|
|
example: true
|
|
serverOwnerHome:
|
|
type: boolean
|
|
description: "Show on server owner's home screen"
|
|
example: false
|
|
libraryRecommended:
|
|
type: boolean
|
|
description: 'Show in library recommended section'
|
|
example: false
|
|
required:
|
|
- usersHome
|
|
- serverOwnerHome
|
|
- libraryRecommended
|
|
maxItems:
|
|
type: integer
|
|
example: 20
|
|
mediaType:
|
|
type: string
|
|
enum: ['movie', 'tv', 'both']
|
|
example: 'both'
|
|
libraryIds:
|
|
type: array
|
|
items:
|
|
type: string
|
|
description: "Array of selected library IDs (['all'] for all libraries)"
|
|
example: ['1', '2']
|
|
nullable: true
|
|
libraryName:
|
|
type: string
|
|
description: 'Selected library name for display'
|
|
example: 'Movies'
|
|
nullable: true
|
|
sortOrderHome:
|
|
type: integer
|
|
description: 'Order for Plex home screen (creation time based)'
|
|
example: 0
|
|
nullable: true
|
|
sortOrderLibrary:
|
|
type: integer
|
|
description: 'Position in library (0 for A-Z section, 1+ for promoted section)'
|
|
example: 0
|
|
nullable: true
|
|
isLibraryPromoted:
|
|
type: boolean
|
|
description: 'true = promoted section (uses exclamation marks), false = A-Z section'
|
|
example: true
|
|
randomizeHomeOrder:
|
|
type: boolean
|
|
description: 'If true, randomize position amongst other randomized items on home screen'
|
|
example: false
|
|
nullable: true
|
|
parentConfigId:
|
|
type: integer
|
|
description: "Reference to original config when expanded from 'all' libraries"
|
|
example: 1
|
|
nullable: true
|
|
isExpandedConfig:
|
|
type: boolean
|
|
description: "True if this config was auto-generated from a parent 'all' config"
|
|
example: false
|
|
nullable: true
|
|
customDays:
|
|
type: integer
|
|
description: 'Number of days for Tautulli collections (required for Tautulli type)'
|
|
example: 30
|
|
nullable: true
|
|
createPlaceholdersForMissing:
|
|
type: boolean
|
|
description: 'Create placeholder files for missing items (enabled by default for Coming Soon collections)'
|
|
example: false
|
|
nullable: true
|
|
placeholderDaysAhead:
|
|
type: integer
|
|
description: 'Days to look ahead for release dates when creating placeholders (default: 360)'
|
|
example: 360
|
|
nullable: true
|
|
placeholderReleasedDays:
|
|
type: integer
|
|
description: 'Days to keep released items with overlay before cleanup (default: 7)'
|
|
example: 7
|
|
nullable: true
|
|
minimumPlays:
|
|
type: integer
|
|
description: 'Minimum play count for Tautulli collections (defaults to 3 if not set, 1-100)'
|
|
example: 3
|
|
nullable: true
|
|
tautulliStatType:
|
|
type: string
|
|
enum: ['plays', 'duration']
|
|
example: 'plays'
|
|
nullable: true
|
|
libraryNames:
|
|
type: array
|
|
items:
|
|
type: string
|
|
description: 'Array of selected library names for display'
|
|
example: ['Movies', 'TV Shows']
|
|
nullable: true
|
|
searchMissingMovies:
|
|
type: boolean
|
|
description: 'Automatically search for missing movies'
|
|
example: false
|
|
nullable: true
|
|
searchMissingTV:
|
|
type: boolean
|
|
description: 'Automatically search for missing TV shows'
|
|
example: false
|
|
nullable: true
|
|
autoApproveMovies:
|
|
type: boolean
|
|
description: 'Auto-approve movie requests'
|
|
example: false
|
|
nullable: true
|
|
autoApproveTV:
|
|
type: boolean
|
|
description: 'Auto-approve TV show requests'
|
|
example: false
|
|
nullable: true
|
|
maxSeasonsToRequest:
|
|
type: integer
|
|
description: 'Max seasons for auto-approval (TV shows with more seasons require manual approval)'
|
|
example: 5
|
|
nullable: true
|
|
seasonsPerShowLimit:
|
|
type: integer
|
|
description: 'Limit each TV show to only the first X seasons (0 = all seasons)'
|
|
example: 2
|
|
nullable: true
|
|
seasonGrabOrder:
|
|
type: string
|
|
enum:
|
|
- first
|
|
- latest
|
|
- airing
|
|
description: 'Order to grab seasons: first N seasons (default), N latest seasons (including unreleased), or N most recently aired seasons'
|
|
example: 'first'
|
|
nullable: true
|
|
minimumYear:
|
|
type: integer
|
|
description: 'Only process movies/TV shows released on or after this year (0 = no limit)'
|
|
example: 2010
|
|
nullable: true
|
|
minimumImdbRating:
|
|
type: number
|
|
format: float
|
|
description: 'Only process movies/TV shows with IMDb rating >= this value (0 = no limit)'
|
|
example: 6.8
|
|
minimum: 0
|
|
maximum: 10
|
|
nullable: true
|
|
minimumRottenTomatoesRating:
|
|
type: number
|
|
format: float
|
|
description: 'Only process movies/TV shows with Rotten Tomatoes critics score >= this value (0 = no limit)'
|
|
example: 70
|
|
minimum: 0
|
|
maximum: 100
|
|
nullable: true
|
|
minimumRottenTomatoesAudienceRating:
|
|
type: number
|
|
format: float
|
|
description: 'Only process movies/TV shows with Rotten Tomatoes audience score >= this value (0 = no limit)'
|
|
example: 75
|
|
minimum: 0
|
|
maximum: 100
|
|
nullable: true
|
|
filterSettings:
|
|
type: object
|
|
description: 'Unified filter settings with include/exclude modes'
|
|
properties:
|
|
genres:
|
|
type: object
|
|
properties:
|
|
mode:
|
|
type: string
|
|
enum: ['exclude', 'include']
|
|
description: 'Filter mode: exclude items with these genres, or include only items with these genres'
|
|
example: 'exclude'
|
|
values:
|
|
type: array
|
|
items:
|
|
type: integer
|
|
description: 'TMDB genre IDs'
|
|
example: [28, 53]
|
|
countries:
|
|
type: object
|
|
properties:
|
|
mode:
|
|
type: string
|
|
enum: ['exclude', 'include']
|
|
description: 'Filter mode: exclude items from these countries, or include only items from these countries'
|
|
example: 'exclude'
|
|
values:
|
|
type: array
|
|
items:
|
|
type: string
|
|
description: 'ISO 3166-1 country codes'
|
|
example: ['JP', 'KR']
|
|
languages:
|
|
type: object
|
|
properties:
|
|
mode:
|
|
type: string
|
|
enum: ['exclude', 'include']
|
|
description: 'Filter mode: exclude items with these languages, or include only items with these languages'
|
|
example: 'exclude'
|
|
values:
|
|
type: array
|
|
items:
|
|
type: string
|
|
description: 'ISO 639-1 language codes'
|
|
example: ['ja', 'ko']
|
|
nullable: true
|
|
traktCustomListUrl:
|
|
type: string
|
|
description: 'Custom Trakt list URL (e.g., https://trakt.tv/users/username/lists/list-name or https://trakt.tv/lists/official/collection-name)'
|
|
example: 'https://trakt.tv/users/username/lists/my-list'
|
|
nullable: true
|
|
tmdbCustomCollectionUrl:
|
|
type: string
|
|
description: 'Custom TMDB collection or list URL (e.g., https://www.themoviedb.org/collection/123456 or https://www.themoviedb.org/list/310)'
|
|
example: 'https://www.themoviedb.org/list/310-my-movie-list'
|
|
nullable: true
|
|
imdbCustomListUrl:
|
|
type: string
|
|
description: 'Custom IMDb list URL (e.g., https://www.imdb.com/list/ls123456789/)'
|
|
example: 'https://www.imdb.com/list/ls123456789/'
|
|
nullable: true
|
|
mdblistCustomListUrl:
|
|
type: string
|
|
description: 'Custom MDBList list URL (e.g., https://mdblist.com/lists/username/listname)'
|
|
example: 'https://mdblist.com/lists/garycrawfordgc/netflix-shows'
|
|
nullable: true
|
|
letterboxdCustomListUrl:
|
|
type: string
|
|
description: 'Custom Letterboxd list URL (e.g., https://letterboxd.com/user/list/list-name/)'
|
|
example: 'https://letterboxd.com/user/list/my-list/'
|
|
nullable: true
|
|
networksCountry:
|
|
type: string
|
|
description: "Selected country for Networks collections (e.g., 'united-states', 'world')"
|
|
example: 'united-states'
|
|
nullable: true
|
|
sortOrder:
|
|
type: string
|
|
enum:
|
|
- default
|
|
- reverse
|
|
- random
|
|
- imdb_rating_desc
|
|
- imdb_rating_asc
|
|
description: 'Sort order for collection items'
|
|
example: 'default'
|
|
default: 'default'
|
|
nullable: true
|
|
personMinimumItems:
|
|
type: number
|
|
description: 'Unified minimum items required to create actor/director collections'
|
|
example: 3
|
|
nullable: true
|
|
useSeparator:
|
|
type: boolean
|
|
description: 'Create a separator collection for auto actor/director collections'
|
|
example: false
|
|
nullable: true
|
|
separatorTitle:
|
|
type: string
|
|
description: 'Title for the separator collection'
|
|
example: 'Actors Collections'
|
|
nullable: true
|
|
excludeFromCollections:
|
|
type: array
|
|
items:
|
|
type: string
|
|
description: 'Array of collection IDs to exclude items from (mutual exclusion)'
|
|
example: ['10001', '10002']
|
|
nullable: true
|
|
timeRestriction:
|
|
type: object
|
|
description: 'Time restriction settings for the collection'
|
|
properties:
|
|
alwaysActive:
|
|
type: boolean
|
|
description: 'If true, collection is always active (default)'
|
|
example: true
|
|
removeFromPlexWhenInactive:
|
|
type: boolean
|
|
description: 'If true, remove collection from Plex when inactive'
|
|
example: false
|
|
timeSlots:
|
|
type: array
|
|
description: 'Array of time slot objects'
|
|
items:
|
|
type: object
|
|
properties:
|
|
startTime:
|
|
type: string
|
|
description: 'HH:MM format'
|
|
example: '09:00'
|
|
endTime:
|
|
type: string
|
|
description: 'HH:MM format'
|
|
example: '17:00'
|
|
nullable: true
|
|
dateRanges:
|
|
type: array
|
|
description: 'Array of date range objects'
|
|
items:
|
|
type: object
|
|
properties:
|
|
startDate:
|
|
type: string
|
|
description: 'DD-MM format'
|
|
example: '05-12'
|
|
endDate:
|
|
type: string
|
|
description: 'DD-MM format'
|
|
example: '26-12'
|
|
nullable: true
|
|
weeklySchedule:
|
|
type: object
|
|
description: 'Days of the week when collection should be active'
|
|
properties:
|
|
monday:
|
|
type: boolean
|
|
example: true
|
|
tuesday:
|
|
type: boolean
|
|
example: true
|
|
wednesday:
|
|
type: boolean
|
|
example: true
|
|
thursday:
|
|
type: boolean
|
|
example: true
|
|
friday:
|
|
type: boolean
|
|
example: true
|
|
saturday:
|
|
type: boolean
|
|
example: false
|
|
sunday:
|
|
type: boolean
|
|
example: false
|
|
nullable: true
|
|
nullable: true
|
|
collectionType:
|
|
type: string
|
|
enum: ['default_plex_hub', 'agregarr_created', 'pre_existing']
|
|
description: 'Backend categorization system for different collection types'
|
|
example: 'agregarr_created'
|
|
nullable: true
|
|
isLinked:
|
|
type: boolean
|
|
description: 'Whether collection is actively linked to other collections'
|
|
example: true
|
|
nullable: true
|
|
isUnlinked:
|
|
type: boolean
|
|
description: 'True if this collection was deliberately unlinked and should not be grouped with siblings'
|
|
example: false
|
|
nullable: true
|
|
missing:
|
|
type: boolean
|
|
description: 'True if collection no longer exists in Plex'
|
|
example: false
|
|
# Multi-source collection properties
|
|
isMultiSource:
|
|
type: boolean
|
|
description: 'Enable multi-source mode for combining multiple collection sources'
|
|
example: false
|
|
nullable: true
|
|
sources:
|
|
type: array
|
|
description: 'Array of source configurations for multi-source collections'
|
|
items:
|
|
$ref: '#/components/schemas/CollectionSourceConfig'
|
|
nullable: true
|
|
combineMode:
|
|
type: string
|
|
enum: ['interleaved', 'list_order', 'randomised', 'cycle_lists']
|
|
description: 'How to combine multiple sources: interleaved (alternate items), list_order (all from first, then second), randomised (shuffle all), cycle_lists (rotate active source)'
|
|
example: 'list_order'
|
|
nullable: true
|
|
customSyncSchedule:
|
|
type: object
|
|
description: 'Custom sync schedule configuration'
|
|
properties:
|
|
enabled:
|
|
type: boolean
|
|
description: 'Enable custom sync schedule'
|
|
example: false
|
|
scheduleType:
|
|
type: string
|
|
enum: ['preset', 'custom']
|
|
description: 'Type of schedule: preset dropdown or custom cron'
|
|
example: 'preset'
|
|
intervalHours:
|
|
type: number
|
|
description: "Legacy field for backward compatibility (when scheduleType === 'preset')"
|
|
example: 24.0
|
|
minimum: 0.1
|
|
maximum: 8760
|
|
nullable: true
|
|
preset:
|
|
type: string
|
|
description: "Preset option key (e.g., '10m', '30m', '1h', '6h', '1d', '1w')"
|
|
example: '1d'
|
|
nullable: true
|
|
customCron:
|
|
type: string
|
|
description: "Custom cron expression (when scheduleType === 'custom')"
|
|
example: '0 9 * * MON'
|
|
nullable: true
|
|
startNow:
|
|
type: boolean
|
|
description: 'If true, start immediately; if false, use startDate/startTime'
|
|
example: true
|
|
startDate:
|
|
type: string
|
|
description: "Start date in DD-MM format (e.g., '01-01' for January 1st)"
|
|
example: '01-01'
|
|
pattern: '^(0[1-9]|[12][0-9]|3[01])-(0[1-9]|1[0-2])$'
|
|
nullable: true
|
|
startTime:
|
|
type: string
|
|
description: "Start time in HH:MM format (e.g., '09:00')"
|
|
example: '09:00'
|
|
pattern: '^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$'
|
|
nullable: true
|
|
firstSyncAt:
|
|
type: string
|
|
format: date-time
|
|
description: 'ISO timestamp of when this schedule was first created (for persistence across restarts)'
|
|
example: '2024-01-01T09:00:00.000Z'
|
|
nullable: true
|
|
nullable: true
|
|
downloadMode:
|
|
type: string
|
|
enum: ['overseerr', 'direct']
|
|
description: 'Download method: overseerr (requests) or direct (*arr)'
|
|
example: 'overseerr'
|
|
nullable: true
|
|
directDownloadRadarrServerId:
|
|
type: integer
|
|
description: "Selected Radarr server ID for movies (when downloadMode is 'direct')"
|
|
example: 1
|
|
nullable: true
|
|
directDownloadRadarrProfileId:
|
|
type: integer
|
|
description: "Selected Radarr profile ID for movies (when downloadMode is 'direct')"
|
|
example: 3
|
|
nullable: true
|
|
directDownloadRadarrRootFolder:
|
|
type: string
|
|
description: "Selected Radarr root folder path for movies (when downloadMode is 'direct')"
|
|
example: '/movies'
|
|
nullable: true
|
|
directDownloadRadarrTags:
|
|
type: array
|
|
items:
|
|
type: integer
|
|
description: "Selected Radarr tags for movies (when downloadMode is 'direct')"
|
|
example: [1, 2]
|
|
nullable: true
|
|
directDownloadRadarrMonitor:
|
|
type: boolean
|
|
description: "Override Radarr monitor setting for movies (when downloadMode is 'direct')"
|
|
example: true
|
|
nullable: true
|
|
directDownloadRadarrSearchOnAdd:
|
|
type: boolean
|
|
description: "Override Radarr search on add setting for movies (when downloadMode is 'direct')"
|
|
example: true
|
|
nullable: true
|
|
directDownloadSonarrServerId:
|
|
type: integer
|
|
description: "Selected Sonarr server ID for TV shows (when downloadMode is 'direct')"
|
|
example: 1
|
|
nullable: true
|
|
directDownloadSonarrProfileId:
|
|
type: integer
|
|
description: "Selected Sonarr profile ID for TV shows (when downloadMode is 'direct')"
|
|
example: 2
|
|
nullable: true
|
|
directDownloadSonarrRootFolder:
|
|
type: string
|
|
description: "Selected Sonarr root folder path for TV shows (when downloadMode is 'direct')"
|
|
example: '/tv'
|
|
nullable: true
|
|
directDownloadSonarrTags:
|
|
type: array
|
|
items:
|
|
type: integer
|
|
description: "Selected Sonarr tags for TV shows (when downloadMode is 'direct')"
|
|
example: [1, 2]
|
|
nullable: true
|
|
directDownloadSonarrMonitor:
|
|
type: boolean
|
|
description: "Override Sonarr monitor setting for TV shows (when downloadMode is 'direct')"
|
|
example: true
|
|
nullable: true
|
|
directDownloadSonarrSearchOnAdd:
|
|
type: boolean
|
|
description: "Override Sonarr search on add setting for TV shows (when downloadMode is 'direct')"
|
|
example: true
|
|
nullable: true
|
|
overseerrRadarrServerId:
|
|
type: integer
|
|
description: "Override Radarr server ID for Overseerr movie requests (when downloadMode is 'overseerr')"
|
|
example: 1
|
|
nullable: true
|
|
overseerrRadarrProfileId:
|
|
type: integer
|
|
description: "Override Radarr profile ID for Overseerr movie requests (when downloadMode is 'overseerr')"
|
|
example: 3
|
|
nullable: true
|
|
overseerrRadarrRootFolder:
|
|
type: string
|
|
description: "Override Radarr root folder path for Overseerr movie requests (when downloadMode is 'overseerr')"
|
|
example: '/movies'
|
|
nullable: true
|
|
overseerrRadarrTags:
|
|
type: array
|
|
items:
|
|
type: integer
|
|
description: "Override Radarr tags for Overseerr movie requests (when downloadMode is 'overseerr')"
|
|
example: [1, 2]
|
|
nullable: true
|
|
overseerrSonarrServerId:
|
|
type: integer
|
|
description: "Override Sonarr server ID for Overseerr TV requests (when downloadMode is 'overseerr')"
|
|
example: 1
|
|
nullable: true
|
|
overseerrSonarrProfileId:
|
|
type: integer
|
|
description: "Override Sonarr profile ID for Overseerr TV requests (when downloadMode is 'overseerr')"
|
|
example: 2
|
|
nullable: true
|
|
overseerrSonarrRootFolder:
|
|
type: string
|
|
description: "Override Sonarr root folder path for Overseerr TV requests (when downloadMode is 'overseerr')"
|
|
example: '/tv'
|
|
nullable: true
|
|
overseerrSonarrTags:
|
|
type: array
|
|
items:
|
|
type: integer
|
|
description: "Override Sonarr tags for Overseerr TV requests (when downloadMode is 'overseerr')"
|
|
example: [1, 2]
|
|
nullable: true
|
|
showUnwatchedOnly:
|
|
type: boolean
|
|
description: 'Create a smart collection that shows only unwatched items from this collection'
|
|
example: false
|
|
nullable: true
|
|
smartCollectionSort:
|
|
type: object
|
|
description: 'Sort option for smart collections'
|
|
properties:
|
|
value:
|
|
type: string
|
|
description: "The sort parameter value (e.g., 'year:desc', 'titleSort', 'rating:desc')"
|
|
example: 'year:desc'
|
|
label:
|
|
type: string
|
|
description: 'Human-readable label for the dropdown'
|
|
example: 'Year (Newest First)'
|
|
nullable: true
|
|
required:
|
|
- id
|
|
- name
|
|
- type
|
|
- subtype
|
|
- template
|
|
- visibilityConfig
|
|
- maxItems
|
|
|
|
CollectionSourceConfig:
|
|
type: object
|
|
description: 'Individual source configuration for multi-source collections'
|
|
properties:
|
|
id:
|
|
type: string
|
|
description: 'Unique identifier for this source within the collection'
|
|
example: 'source-1234567890'
|
|
type:
|
|
type: string
|
|
enum:
|
|
[
|
|
'trakt',
|
|
'tmdb',
|
|
'imdb',
|
|
'mdblist',
|
|
'letterboxd',
|
|
'tautulli',
|
|
'overseerr',
|
|
'networks',
|
|
'originals',
|
|
'plex',
|
|
'anilist',
|
|
'myanimelist',
|
|
'radarrtag',
|
|
'sonarrtag',
|
|
'comingsoon',
|
|
'filtered_hub',
|
|
]
|
|
description: 'Type of collection source'
|
|
example: 'trakt'
|
|
subtype:
|
|
type: string
|
|
description: 'Sub-type of the collection source'
|
|
example: 'trending'
|
|
nullable: true
|
|
customUrl:
|
|
type: string
|
|
description: 'Custom URL for list-based sources (Trakt, TMDB, IMDb, Letterboxd)'
|
|
example: 'https://trakt.tv/users/username/lists/my-list'
|
|
nullable: true
|
|
timePeriod:
|
|
type: string
|
|
enum: ['daily', 'weekly', 'monthly', 'all']
|
|
description: 'Time period for time-based sources'
|
|
example: 'weekly'
|
|
nullable: true
|
|
priority:
|
|
type: integer
|
|
description: 'Order priority when combining (0 = highest priority)'
|
|
example: 0
|
|
minimum: 0
|
|
isExpanded:
|
|
type: boolean
|
|
description: 'UI state for expandable sections'
|
|
example: true
|
|
nullable: true
|
|
customDays:
|
|
type: integer
|
|
description: 'Number of days to look back for Tautulli statistics'
|
|
example: 30
|
|
minimum: 1
|
|
maximum: 365
|
|
nullable: true
|
|
minimumPlays:
|
|
type: integer
|
|
description: 'Minimum play count required for Tautulli sources'
|
|
example: 3
|
|
minimum: 1
|
|
maximum: 100
|
|
nullable: true
|
|
networksCountry:
|
|
type: string
|
|
description: 'Selected country for Networks collections'
|
|
example: 'united-states'
|
|
nullable: true
|
|
required:
|
|
- id
|
|
- type
|
|
- priority
|
|
|
|
PlexHubConfig:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
description: 'Unique hub identifier (libraryId-hubIdentifier)'
|
|
example: '1-movie.recentlyadded'
|
|
hubIdentifier:
|
|
type: string
|
|
description: 'Plex built-in hub identifier'
|
|
example: 'movie.recentlyadded'
|
|
name:
|
|
type: string
|
|
description: 'Display name for the hub'
|
|
example: 'Recently Added Movies'
|
|
libraryId:
|
|
type: string
|
|
description: 'Plex library ID'
|
|
example: '1'
|
|
libraryName:
|
|
type: string
|
|
description: 'Plex library display name'
|
|
example: 'Films'
|
|
mediaType:
|
|
type: string
|
|
enum: ['movie', 'tv', 'both']
|
|
description: 'Media type of the hub'
|
|
example: 'movie'
|
|
sortOrderLibrary:
|
|
type: integer
|
|
description: 'Position/order within the library'
|
|
example: 0
|
|
visibilityConfig:
|
|
type: object
|
|
properties:
|
|
usersHome:
|
|
type: boolean
|
|
description: "Show on shared users' home screens"
|
|
example: true
|
|
serverOwnerHome:
|
|
type: boolean
|
|
description: "Show on server owner's home screen"
|
|
example: false
|
|
libraryRecommended:
|
|
type: boolean
|
|
description: 'Show in library recommended section'
|
|
example: false
|
|
required:
|
|
- usersHome
|
|
- serverOwnerHome
|
|
- libraryRecommended
|
|
isActive:
|
|
type: boolean
|
|
description: 'Whether hub is currently active (always true for built-in hubs, time restrictions for collections)'
|
|
example: true
|
|
readOnly: true
|
|
isLinked:
|
|
type: boolean
|
|
description: 'True if hub is actively linked to other hubs'
|
|
example: false
|
|
linkId:
|
|
type: integer
|
|
description: 'Group ID for linked hubs (preserved even when isLinked=false)'
|
|
example: 1
|
|
isUnlinked:
|
|
type: boolean
|
|
description: 'True if this hub was deliberately unlinked and should not be grouped with siblings'
|
|
example: false
|
|
sortOrderHome:
|
|
type: integer
|
|
description: 'Position on Plex home screen'
|
|
example: 0
|
|
isLibraryPromoted:
|
|
type: boolean
|
|
description: 'true = promoted section (uses exclamation marks), false = A-Z section'
|
|
example: false
|
|
randomizeHomeOrder:
|
|
type: boolean
|
|
description: 'If true, randomize position amongst other randomized items on home screen'
|
|
example: false
|
|
nullable: true
|
|
everLibraryPromoted:
|
|
type: boolean
|
|
description: 'True if this hub has ever been promoted to the promoted section (once true, stays true until sortTitle reset)'
|
|
example: false
|
|
nullable: true
|
|
isPromotedToHub:
|
|
type: boolean
|
|
description: 'True if hub exists as a promotable item in Plex (appears in hub management list)'
|
|
example: false
|
|
nullable: true
|
|
timeRestriction:
|
|
type: object
|
|
description: 'Time restriction settings for the hub'
|
|
properties:
|
|
alwaysActive:
|
|
type: boolean
|
|
description: 'If true, hub is always active (default)'
|
|
example: true
|
|
removeFromPlexWhenInactive:
|
|
type: boolean
|
|
description: 'If true, remove hub from Plex when inactive'
|
|
example: false
|
|
inactiveVisibilityConfig:
|
|
type: object
|
|
properties:
|
|
usersHome:
|
|
type: boolean
|
|
serverOwnerHome:
|
|
type: boolean
|
|
libraryRecommended:
|
|
type: boolean
|
|
nullable: true
|
|
dateRanges:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
startDate:
|
|
type: string
|
|
description: "DD-MM format (e.g., '05-12' for 5th December)"
|
|
example: '05-12'
|
|
endDate:
|
|
type: string
|
|
description: "DD-MM format (e.g., '26-12' for 26th December)"
|
|
example: '26-12'
|
|
required:
|
|
- startDate
|
|
- endDate
|
|
nullable: true
|
|
weeklySchedule:
|
|
type: object
|
|
properties:
|
|
monday:
|
|
type: boolean
|
|
tuesday:
|
|
type: boolean
|
|
wednesday:
|
|
type: boolean
|
|
thursday:
|
|
type: boolean
|
|
friday:
|
|
type: boolean
|
|
saturday:
|
|
type: boolean
|
|
sunday:
|
|
type: boolean
|
|
nullable: true
|
|
required:
|
|
- alwaysActive
|
|
nullable: true
|
|
missing:
|
|
type: boolean
|
|
description: 'True if hub no longer exists in Plex'
|
|
example: false
|
|
lastSyncedAt:
|
|
type: string
|
|
format: date-time
|
|
description: 'ISO timestamp of last successful sync to Plex'
|
|
example: '2024-01-15T10:30:00.000Z'
|
|
nullable: true
|
|
lastModifiedAt:
|
|
type: string
|
|
format: date-time
|
|
description: 'ISO timestamp when config was last modified'
|
|
example: '2024-01-15T09:15:00.000Z'
|
|
nullable: true
|
|
needsSync:
|
|
type: boolean
|
|
description: 'True if hub has been modified and needs to be synced to Plex'
|
|
example: false
|
|
nullable: true
|
|
required:
|
|
- id
|
|
- hubIdentifier
|
|
- name
|
|
- libraryId
|
|
- libraryName
|
|
- mediaType
|
|
- sortOrderLibrary
|
|
- visibilityConfig
|
|
- isActive
|
|
|
|
PlexHubConfigUpdate:
|
|
type: object
|
|
description: 'Schema for updating PlexHubConfig settings (excludes computed fields)'
|
|
properties:
|
|
id:
|
|
type: string
|
|
description: 'Unique hub identifier (libraryId-hubIdentifier)'
|
|
example: '1-movie.recentlyadded'
|
|
hubIdentifier:
|
|
type: string
|
|
description: 'Plex built-in hub identifier'
|
|
example: 'movie.recentlyadded'
|
|
name:
|
|
type: string
|
|
description: 'Display name for the hub'
|
|
example: 'Recently Added Movies'
|
|
libraryId:
|
|
type: string
|
|
description: 'Plex library ID'
|
|
example: '1'
|
|
libraryName:
|
|
type: string
|
|
description: 'Plex library display name'
|
|
example: 'Films'
|
|
mediaType:
|
|
type: string
|
|
enum: ['movie', 'tv', 'both']
|
|
description: 'Media type of the hub'
|
|
example: 'movie'
|
|
sortOrderHome:
|
|
type: integer
|
|
description: 'Position/order on Plex home screen'
|
|
example: 0
|
|
sortOrderLibrary:
|
|
type: integer
|
|
description: 'Position/order within the library'
|
|
example: 0
|
|
isLibraryPromoted:
|
|
type: boolean
|
|
description: 'true = promoted section (uses exclamation marks), false = A-Z section'
|
|
example: false
|
|
visibilityConfig:
|
|
type: object
|
|
properties:
|
|
usersHome:
|
|
type: boolean
|
|
description: "Show on shared users' home screens"
|
|
example: true
|
|
serverOwnerHome:
|
|
type: boolean
|
|
description: "Show on server owner's home screen"
|
|
example: false
|
|
libraryRecommended:
|
|
type: boolean
|
|
description: 'Show in library recommended section'
|
|
example: false
|
|
required:
|
|
- usersHome
|
|
- serverOwnerHome
|
|
- libraryRecommended
|
|
isLinked:
|
|
type: boolean
|
|
description: 'True if hub is actively linked to other hubs'
|
|
example: false
|
|
linkId:
|
|
type: integer
|
|
description: 'Group ID for linked hubs (preserved even when isLinked=false)'
|
|
example: 1
|
|
isUnlinked:
|
|
type: boolean
|
|
description: 'True if this hub was deliberately unlinked and should not be grouped with siblings'
|
|
example: false
|
|
randomizeHomeOrder:
|
|
type: boolean
|
|
description: 'If true, randomize position amongst other randomized items on home screen'
|
|
example: false
|
|
nullable: true
|
|
everLibraryPromoted:
|
|
type: boolean
|
|
description: 'True if this hub has ever been promoted to the promoted section (once true, stays true until sortTitle reset)'
|
|
example: false
|
|
nullable: true
|
|
isPromotedToHub:
|
|
type: boolean
|
|
description: 'True if hub exists as a promotable item in Plex (appears in hub management list)'
|
|
example: false
|
|
nullable: true
|
|
missing:
|
|
type: boolean
|
|
description: 'True if hub no longer exists in Plex'
|
|
example: false
|
|
timeRestriction:
|
|
type: object
|
|
description: 'Time restriction settings for the hub'
|
|
properties:
|
|
alwaysActive:
|
|
type: boolean
|
|
description: 'If true, hub is always active (default)'
|
|
example: true
|
|
removeFromPlexWhenInactive:
|
|
type: boolean
|
|
description: 'If true, remove hub from Plex when inactive'
|
|
example: false
|
|
timeSlots:
|
|
type: array
|
|
description: 'Array of time slot objects'
|
|
items:
|
|
type: object
|
|
properties:
|
|
startTime:
|
|
type: string
|
|
description: 'HH:MM format'
|
|
example: '09:00'
|
|
endTime:
|
|
type: string
|
|
description: 'HH:MM format'
|
|
example: '17:00'
|
|
nullable: true
|
|
dateRanges:
|
|
type: array
|
|
description: 'Array of date range objects'
|
|
items:
|
|
type: object
|
|
properties:
|
|
startDate:
|
|
type: string
|
|
description: 'DD-MM format'
|
|
example: '05-12'
|
|
endDate:
|
|
type: string
|
|
description: 'DD-MM format'
|
|
example: '26-12'
|
|
nullable: true
|
|
weeklySchedule:
|
|
type: object
|
|
properties:
|
|
monday:
|
|
type: boolean
|
|
tuesday:
|
|
type: boolean
|
|
wednesday:
|
|
type: boolean
|
|
thursday:
|
|
type: boolean
|
|
friday:
|
|
type: boolean
|
|
saturday:
|
|
type: boolean
|
|
sunday:
|
|
type: boolean
|
|
nullable: true
|
|
nullable: true
|
|
required:
|
|
- id
|
|
- hubIdentifier
|
|
- name
|
|
- libraryId
|
|
- libraryName
|
|
- mediaType
|
|
- sortOrderLibrary
|
|
- visibilityConfig
|
|
|
|
PreExistingCollectionConfig:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
description: 'Unique collection identifier (libraryId-collectionRatingKey)'
|
|
example: '1-35954'
|
|
collectionRatingKey:
|
|
type: string
|
|
description: 'Plex collection rating key'
|
|
example: '35954'
|
|
name:
|
|
type: string
|
|
description: 'Display name from Plex'
|
|
example: 'Action Movies'
|
|
libraryId:
|
|
type: string
|
|
description: 'Plex library ID'
|
|
example: '1'
|
|
libraryName:
|
|
type: string
|
|
description: 'Plex library display name'
|
|
example: 'Films'
|
|
mediaType:
|
|
type: string
|
|
enum: ['movie', 'tv', 'both']
|
|
description: 'Media type based on collection contents'
|
|
example: 'movie'
|
|
sortOrderHome:
|
|
type: integer
|
|
description: 'Position on Plex home screen'
|
|
example: 0
|
|
sortOrderLibrary:
|
|
type: integer
|
|
description: 'Position in library (0 for A-Z section, 1+ for promoted section)'
|
|
example: 0
|
|
isLibraryPromoted:
|
|
type: boolean
|
|
description: 'true = promoted section (uses exclamation marks), false = A-Z section'
|
|
example: false
|
|
visibilityConfig:
|
|
type: object
|
|
properties:
|
|
usersHome:
|
|
type: boolean
|
|
description: "Show on shared users' home screens"
|
|
example: true
|
|
serverOwnerHome:
|
|
type: boolean
|
|
description: "Show on server owner's home screen"
|
|
example: false
|
|
libraryRecommended:
|
|
type: boolean
|
|
description: 'Show in library recommended section'
|
|
example: false
|
|
required:
|
|
- usersHome
|
|
- serverOwnerHome
|
|
- libraryRecommended
|
|
isActive:
|
|
type: boolean
|
|
description: 'Whether collection is currently active (computed from time restrictions)'
|
|
example: true
|
|
readOnly: true
|
|
collectionType:
|
|
type: string
|
|
enum: ['default_plex_hub', 'agregarr_created', 'pre_existing']
|
|
description: 'Type of collection (determined during discovery)'
|
|
example: 'pre_existing'
|
|
readOnly: true
|
|
isLinked:
|
|
type: boolean
|
|
description: 'True if collection is actively linked to other collections'
|
|
example: false
|
|
linkId:
|
|
type: integer
|
|
description: 'Group ID for linked collections (preserved even when isLinked=false)'
|
|
example: 1
|
|
isUnlinked:
|
|
type: boolean
|
|
description: 'True if this collection was deliberately unlinked and should not be grouped with siblings'
|
|
example: false
|
|
nullable: true
|
|
timeRestriction:
|
|
type: object
|
|
properties:
|
|
alwaysActive:
|
|
type: boolean
|
|
description: 'If true, collection is always active (default)'
|
|
example: true
|
|
removeFromPlexWhenInactive:
|
|
type: boolean
|
|
description: 'If true, completely remove from Plex when inactive'
|
|
example: false
|
|
nullable: true
|
|
inactiveVisibilityConfig:
|
|
type: object
|
|
properties:
|
|
usersHome:
|
|
type: boolean
|
|
serverOwnerHome:
|
|
type: boolean
|
|
libraryRecommended:
|
|
type: boolean
|
|
nullable: true
|
|
dateRanges:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
startDate:
|
|
type: string
|
|
description: "DD-MM format (e.g., '05-12' for 5th December)"
|
|
example: '05-12'
|
|
endDate:
|
|
type: string
|
|
description: "DD-MM format (e.g., '26-12' for 26th December)"
|
|
example: '26-12'
|
|
required:
|
|
- startDate
|
|
- endDate
|
|
nullable: true
|
|
weeklySchedule:
|
|
type: object
|
|
properties:
|
|
monday:
|
|
type: boolean
|
|
tuesday:
|
|
type: boolean
|
|
wednesday:
|
|
type: boolean
|
|
thursday:
|
|
type: boolean
|
|
friday:
|
|
type: boolean
|
|
saturday:
|
|
type: boolean
|
|
sunday:
|
|
type: boolean
|
|
nullable: true
|
|
required:
|
|
- alwaysActive
|
|
nullable: true
|
|
customPoster:
|
|
type: string
|
|
description: 'Path to custom poster image file'
|
|
example: '/app/config/poster-123.jpg'
|
|
nullable: true
|
|
autoPoster:
|
|
type: boolean
|
|
description: 'Auto-generate poster during sync'
|
|
example: true
|
|
nullable: true
|
|
autoPosterTemplate:
|
|
type: integer
|
|
description: 'Template ID for auto-generated posters (null for default template)'
|
|
example: 1
|
|
nullable: true
|
|
titleSort:
|
|
type: string
|
|
description: 'Plex sortTitle field for alphabetical ordering'
|
|
example: 'Action Movies'
|
|
nullable: true
|
|
randomizeHomeOrder:
|
|
type: boolean
|
|
description: 'If true, randomize position amongst other randomized items on home screen'
|
|
example: false
|
|
nullable: true
|
|
everLibraryPromoted:
|
|
type: boolean
|
|
description: 'True if this collection has ever been promoted to the promoted section (once true, stays true until sortTitle reset)'
|
|
example: false
|
|
nullable: true
|
|
isPromotedToHub:
|
|
type: boolean
|
|
description: 'True if collection exists as a promotable hub in Plex (appears in hub management list)'
|
|
example: false
|
|
nullable: true
|
|
customWallpaper:
|
|
oneOf:
|
|
- type: string
|
|
description: 'Filename of custom wallpaper image (art)'
|
|
example: 'wallpaper-12345.jpg'
|
|
- type: object
|
|
description: 'Per-library wallpaper mapping (libraryId -> filename)'
|
|
additionalProperties:
|
|
type: string
|
|
example:
|
|
lib1: 'wallpaper-12345.jpg'
|
|
lib2: 'wallpaper-67890.jpg'
|
|
nullable: true
|
|
customSummary:
|
|
type: string
|
|
description: 'Custom summary/description text for the collection'
|
|
example: 'A curated collection of the best movies'
|
|
nullable: true
|
|
customTheme:
|
|
oneOf:
|
|
- type: string
|
|
description: 'Filename of custom theme music file'
|
|
example: 'theme-12345.mp3'
|
|
- type: object
|
|
description: 'Per-library theme mapping (libraryId -> filename)'
|
|
additionalProperties:
|
|
type: string
|
|
example:
|
|
lib1: 'theme-12345.mp3'
|
|
lib2: 'theme-67890.mp3'
|
|
nullable: true
|
|
enableCustomWallpaper:
|
|
type: boolean
|
|
description: 'Enable custom wallpaper sync to Plex'
|
|
example: false
|
|
nullable: true
|
|
enableCustomSummary:
|
|
type: boolean
|
|
description: 'Enable custom summary sync to Plex'
|
|
example: false
|
|
nullable: true
|
|
enableCustomTheme:
|
|
type: boolean
|
|
description: 'Enable custom theme sync to Plex'
|
|
example: false
|
|
nullable: true
|
|
missing:
|
|
type: boolean
|
|
description: 'True if collection no longer exists in Plex'
|
|
example: false
|
|
lastSyncedAt:
|
|
type: string
|
|
format: date-time
|
|
description: 'ISO timestamp of last successful sync to Plex'
|
|
example: '2024-01-15T10:30:00.000Z'
|
|
nullable: true
|
|
lastModifiedAt:
|
|
type: string
|
|
format: date-time
|
|
description: 'ISO timestamp when config was last modified'
|
|
example: '2024-01-15T09:15:00.000Z'
|
|
nullable: true
|
|
needsSync:
|
|
type: boolean
|
|
description: 'True if collection has been modified and needs to be synced to Plex'
|
|
example: false
|
|
nullable: true
|
|
required:
|
|
- id
|
|
- collectionRatingKey
|
|
- name
|
|
- libraryId
|
|
- libraryName
|
|
- mediaType
|
|
- sortOrderHome
|
|
- sortOrderLibrary
|
|
- visibilityConfig
|
|
- isActive
|
|
|
|
PreExistingCollectionConfigUpdate:
|
|
type: object
|
|
description: 'Schema for updating PreExistingCollectionConfig settings (excludes computed fields)'
|
|
properties:
|
|
id:
|
|
type: string
|
|
description: 'Unique collection identifier (libraryId-collectionRatingKey)'
|
|
example: '1-35954'
|
|
collectionRatingKey:
|
|
type: string
|
|
description: 'Plex collection rating key'
|
|
example: '35954'
|
|
name:
|
|
type: string
|
|
description: 'Display name from Plex'
|
|
example: 'Action Movies'
|
|
libraryId:
|
|
type: string
|
|
description: 'Plex library ID'
|
|
example: '1'
|
|
libraryName:
|
|
type: string
|
|
description: 'Plex library display name'
|
|
example: 'Films'
|
|
mediaType:
|
|
type: string
|
|
enum: ['movie', 'tv', 'both']
|
|
description: 'Media type based on collection contents'
|
|
example: 'movie'
|
|
sortOrderHome:
|
|
type: integer
|
|
description: 'Position on Plex home screen'
|
|
example: 0
|
|
sortOrderLibrary:
|
|
type: integer
|
|
description: 'Position in library (0 for A-Z section, 1+ for promoted section)'
|
|
example: 0
|
|
isLibraryPromoted:
|
|
type: boolean
|
|
description: 'true = promoted section (uses exclamation marks), false = A-Z section'
|
|
example: false
|
|
visibilityConfig:
|
|
type: object
|
|
properties:
|
|
usersHome:
|
|
type: boolean
|
|
description: "Show on shared users' home screens"
|
|
example: true
|
|
serverOwnerHome:
|
|
type: boolean
|
|
description: "Show on server owner's home screen"
|
|
example: false
|
|
libraryRecommended:
|
|
type: boolean
|
|
description: 'Show in library recommended section'
|
|
example: false
|
|
required:
|
|
- usersHome
|
|
- serverOwnerHome
|
|
- libraryRecommended
|
|
isLinked:
|
|
type: boolean
|
|
description: 'True if collection is actively linked to other collections'
|
|
example: false
|
|
linkId:
|
|
type: integer
|
|
description: 'Group ID for linked collections (preserved even when isLinked=false)'
|
|
example: 1
|
|
isUnlinked:
|
|
type: boolean
|
|
description: 'True if this collection was deliberately unlinked and should not be grouped with siblings'
|
|
example: false
|
|
timeRestriction:
|
|
type: object
|
|
description: 'Time restriction settings for the collection'
|
|
properties:
|
|
alwaysActive:
|
|
type: boolean
|
|
description: 'If true, collection is always active (default)'
|
|
example: true
|
|
removeFromPlexWhenInactive:
|
|
type: boolean
|
|
description: 'If true, remove collection from Plex when inactive'
|
|
example: false
|
|
timeSlots:
|
|
type: array
|
|
description: 'Array of time slot objects'
|
|
items:
|
|
type: object
|
|
properties:
|
|
startTime:
|
|
type: string
|
|
description: 'HH:MM format'
|
|
example: '09:00'
|
|
endTime:
|
|
type: string
|
|
description: 'HH:MM format'
|
|
example: '17:00'
|
|
nullable: true
|
|
dateRanges:
|
|
type: array
|
|
description: 'Array of date range objects'
|
|
items:
|
|
type: object
|
|
properties:
|
|
startDate:
|
|
type: string
|
|
description: 'DD-MM format'
|
|
example: '05-12'
|
|
endDate:
|
|
type: string
|
|
description: 'DD-MM format'
|
|
example: '26-12'
|
|
nullable: true
|
|
weeklySchedule:
|
|
type: object
|
|
properties:
|
|
monday:
|
|
type: boolean
|
|
tuesday:
|
|
type: boolean
|
|
wednesday:
|
|
type: boolean
|
|
thursday:
|
|
type: boolean
|
|
friday:
|
|
type: boolean
|
|
saturday:
|
|
type: boolean
|
|
sunday:
|
|
type: boolean
|
|
nullable: true
|
|
required:
|
|
- alwaysActive
|
|
nullable: true
|
|
customPoster:
|
|
oneOf:
|
|
- type: string
|
|
description: 'Filename of custom poster image (legacy format)'
|
|
example: 'f47ac10b-58cc-4372-a567-0e02b2c3d479.jpg'
|
|
- type: object
|
|
description: 'Per-library poster mapping (libraryId -> filename)'
|
|
additionalProperties:
|
|
type: string
|
|
example:
|
|
lib1: 'f47ac10b-58cc-4372-a567-0e02b2c3d479.jpg'
|
|
lib2: 'a12bc34d-58cc-4372-a567-0e02b2c3d480.jpg'
|
|
nullable: true
|
|
autoPoster:
|
|
type: boolean
|
|
description: 'Auto-generate poster during sync'
|
|
example: true
|
|
nullable: true
|
|
autoPosterTemplate:
|
|
type: integer
|
|
description: 'Template ID for auto-generated posters (null for default template)'
|
|
example: 1
|
|
nullable: true
|
|
titleSort:
|
|
type: string
|
|
description: 'Plex sortTitle field for alphabetical ordering'
|
|
example: 'Action Movies'
|
|
nullable: true
|
|
randomizeHomeOrder:
|
|
type: boolean
|
|
description: 'If true, randomize position amongst other randomized items on home screen'
|
|
example: false
|
|
nullable: true
|
|
everLibraryPromoted:
|
|
type: boolean
|
|
description: 'True if this collection has ever been promoted to the promoted section (once true, stays true until sortTitle reset)'
|
|
example: false
|
|
nullable: true
|
|
isPromotedToHub:
|
|
type: boolean
|
|
description: 'True if collection exists as a promotable hub in Plex (appears in hub management list)'
|
|
example: false
|
|
nullable: true
|
|
customWallpaper:
|
|
oneOf:
|
|
- type: string
|
|
description: 'Filename of custom wallpaper image (art)'
|
|
example: 'wallpaper-12345.jpg'
|
|
- type: object
|
|
description: 'Per-library wallpaper mapping (libraryId -> filename)'
|
|
additionalProperties:
|
|
type: string
|
|
example:
|
|
lib1: 'wallpaper-12345.jpg'
|
|
lib2: 'wallpaper-67890.jpg'
|
|
nullable: true
|
|
customSummary:
|
|
type: string
|
|
description: 'Custom summary/description text for the collection'
|
|
example: 'A curated collection of the best movies'
|
|
nullable: true
|
|
customTheme:
|
|
oneOf:
|
|
- type: string
|
|
description: 'Filename of custom theme music file'
|
|
example: 'theme-12345.mp3'
|
|
- type: object
|
|
description: 'Per-library theme mapping (libraryId -> filename)'
|
|
additionalProperties:
|
|
type: string
|
|
example:
|
|
lib1: 'theme-12345.mp3'
|
|
lib2: 'theme-67890.mp3'
|
|
nullable: true
|
|
enableCustomWallpaper:
|
|
type: boolean
|
|
description: 'Enable custom wallpaper sync to Plex'
|
|
example: false
|
|
nullable: true
|
|
enableCustomSummary:
|
|
type: boolean
|
|
description: 'Enable custom summary sync to Plex'
|
|
example: false
|
|
nullable: true
|
|
enableCustomTheme:
|
|
type: boolean
|
|
description: 'Enable custom theme sync to Plex'
|
|
example: false
|
|
nullable: true
|
|
missing:
|
|
type: boolean
|
|
description: 'True if collection no longer exists in Plex'
|
|
example: false
|
|
required:
|
|
- id
|
|
- collectionRatingKey
|
|
- name
|
|
- libraryId
|
|
- libraryName
|
|
- mediaType
|
|
- sortOrderHome
|
|
- sortOrderLibrary
|
|
- visibilityConfig
|
|
|
|
DiscoveredCollectionConfig:
|
|
type: object
|
|
description: 'Pre-existing collection config for discovery (collectionRatingKey is extracted server-side)'
|
|
properties:
|
|
id:
|
|
type: string
|
|
description: 'Unique collection identifier (libraryId-collectionRatingKey)'
|
|
example: '1:36466'
|
|
hubIdentifier:
|
|
type: string
|
|
description: 'Plex hub identifier for the collection'
|
|
example: 'custom.collection.1.36466'
|
|
name:
|
|
type: string
|
|
description: 'Display name from Plex'
|
|
example: 'movies that i like'
|
|
libraryId:
|
|
type: string
|
|
description: 'Plex library ID'
|
|
example: '1'
|
|
libraryName:
|
|
type: string
|
|
description: 'Plex library display name'
|
|
example: 'Films'
|
|
mediaType:
|
|
type: string
|
|
enum: ['movie', 'tv', 'both']
|
|
description: 'Media type based on collection contents'
|
|
example: 'movie'
|
|
sortOrderHome:
|
|
type: integer
|
|
description: 'Position on Plex home screen'
|
|
example: 0
|
|
sortOrderLibrary:
|
|
type: integer
|
|
description: 'Position in library'
|
|
example: 0
|
|
visibilityConfig:
|
|
type: object
|
|
properties:
|
|
usersHome:
|
|
type: boolean
|
|
example: false
|
|
serverOwnerHome:
|
|
type: boolean
|
|
example: true
|
|
libraryRecommended:
|
|
type: boolean
|
|
example: false
|
|
required:
|
|
- usersHome
|
|
- serverOwnerHome
|
|
- libraryRecommended
|
|
collectionType:
|
|
type: string
|
|
description: 'Type of collection for discovery'
|
|
example: 'pre_existing'
|
|
required:
|
|
- id
|
|
- name
|
|
- libraryId
|
|
- libraryName
|
|
- mediaType
|
|
- sortOrderHome
|
|
- sortOrderLibrary
|
|
- visibilityConfig
|
|
|
|
OverlayTemplate:
|
|
type: object
|
|
description: 'Overlay template for applying customizable badges and banners to library posters'
|
|
properties:
|
|
id:
|
|
type: integer
|
|
readOnly: true
|
|
description: 'Unique identifier'
|
|
example: 1
|
|
name:
|
|
type: string
|
|
description: 'Template name'
|
|
example: 'IMDb Rating Badge'
|
|
description:
|
|
type: string
|
|
nullable: true
|
|
description: 'Optional template description'
|
|
example: 'Shows IMDb rating in top-right corner with gold background'
|
|
type:
|
|
type: string
|
|
enum: ['rating', 'metadata', 'technical', 'status', 'generic']
|
|
description: 'Template type for organization'
|
|
example: 'rating'
|
|
templateData:
|
|
type: object
|
|
description: 'Overlay template design data with layered elements'
|
|
properties:
|
|
width:
|
|
type: number
|
|
description: 'Canvas width for editing'
|
|
example: 1000
|
|
height:
|
|
type: number
|
|
description: 'Canvas height for editing'
|
|
example: 1500
|
|
elements:
|
|
type: array
|
|
description: 'Layered overlay elements (text, tile, variable, SVG, raster)'
|
|
items:
|
|
type: object
|
|
applicationCondition:
|
|
type: object
|
|
nullable: true
|
|
description: 'Flat section-based condition structure for when this template should be applied'
|
|
properties:
|
|
sections:
|
|
type: array
|
|
description: 'Array of condition sections (combined with OR by default)'
|
|
items:
|
|
type: object
|
|
properties:
|
|
sectionOperator:
|
|
type: string
|
|
enum: ['and', 'or']
|
|
description: 'How this section combines with the previous section (omitted for first section)'
|
|
example: 'or'
|
|
rules:
|
|
type: array
|
|
description: 'Array of condition rules within this section'
|
|
items:
|
|
type: object
|
|
properties:
|
|
ruleOperator:
|
|
type: string
|
|
enum: ['and', 'or']
|
|
description: 'How this rule combines with the previous rule (omitted for first rule)'
|
|
example: 'and'
|
|
field:
|
|
type: string
|
|
description: 'Context field to evaluate (e.g., imdbRating, resolution, daysUntilRelease, daysUntilAction)'
|
|
example: 'imdbRating'
|
|
operator:
|
|
type: string
|
|
enum:
|
|
[
|
|
'eq',
|
|
'neq',
|
|
'gt',
|
|
'gte',
|
|
'lt',
|
|
'lte',
|
|
'in',
|
|
'contains',
|
|
'regex',
|
|
'begins',
|
|
'ends',
|
|
]
|
|
description: 'Comparison operator'
|
|
example: 'gte'
|
|
value:
|
|
oneOf:
|
|
- type: string
|
|
- type: number
|
|
- type: boolean
|
|
- type: array
|
|
items:
|
|
oneOf:
|
|
- type: string
|
|
- type: number
|
|
description: 'Value to compare against'
|
|
example: 7.5
|
|
required:
|
|
- field
|
|
- operator
|
|
- value
|
|
required:
|
|
- rules
|
|
example:
|
|
sections:
|
|
- rules:
|
|
- field: 'imdbRating'
|
|
operator: 'gte'
|
|
value: 8.0
|
|
- ruleOperator: 'and'
|
|
field: 'isMonitored'
|
|
operator: 'eq'
|
|
value: true
|
|
isDefault:
|
|
type: boolean
|
|
readOnly: true
|
|
description: 'Whether this is a system preset template (cannot be edited/deleted)'
|
|
example: true
|
|
isActive:
|
|
type: boolean
|
|
description: 'Whether template is active'
|
|
example: true
|
|
default: true
|
|
createdAt:
|
|
type: string
|
|
format: date-time
|
|
readOnly: true
|
|
description: 'Creation timestamp'
|
|
updatedAt:
|
|
type: string
|
|
format: date-time
|
|
readOnly: true
|
|
description: 'Last update timestamp'
|
|
required:
|
|
- name
|
|
- type
|
|
- templateData
|
|
|
|
OverlayLibraryConfig:
|
|
type: object
|
|
description: 'Configuration for which overlay templates are applied to a specific library'
|
|
properties:
|
|
id:
|
|
type: integer
|
|
readOnly: true
|
|
description: 'Unique identifier'
|
|
example: 1
|
|
libraryId:
|
|
type: string
|
|
description: 'Plex library ID (unique constraint)'
|
|
example: '1'
|
|
libraryName:
|
|
type: string
|
|
description: 'Library display name'
|
|
example: 'Movies'
|
|
mediaType:
|
|
type: string
|
|
enum: ['movie', 'show']
|
|
description: 'Media type of library'
|
|
example: 'movie'
|
|
enabledOverlays:
|
|
type: array
|
|
description: 'List of enabled overlay templates with layer ordering'
|
|
items:
|
|
type: object
|
|
properties:
|
|
templateId:
|
|
type: integer
|
|
description: 'OverlayTemplate ID'
|
|
example: 1
|
|
enabled:
|
|
type: boolean
|
|
description: 'Whether this overlay is active'
|
|
example: true
|
|
layerOrder:
|
|
type: integer
|
|
description: 'Stacking order (0 = bottom layer, higher = top)'
|
|
example: 0
|
|
config:
|
|
type: object
|
|
description: 'Optional per-overlay configuration'
|
|
properties:
|
|
daysThreshold:
|
|
type: number
|
|
description: 'For Coming Soon overlays - show if days until release is less than this'
|
|
example: 30
|
|
timeWindowDays:
|
|
type: number
|
|
description: 'For New Release badge - show for X days after download'
|
|
example: 7
|
|
minimumRating:
|
|
type: number
|
|
description: 'For rating badges - minimum rating to display'
|
|
example: 7.0
|
|
tmdbLanguage:
|
|
type: string
|
|
nullable: true
|
|
description: 'ISO language code for TMDB poster metadata (e.g., en, fr, pt-BR). If not set, uses global setting.'
|
|
example: 'en'
|
|
createdAt:
|
|
type: string
|
|
format: date-time
|
|
readOnly: true
|
|
description: 'Creation timestamp'
|
|
updatedAt:
|
|
type: string
|
|
format: date-time
|
|
readOnly: true
|
|
description: 'Last update timestamp'
|
|
required:
|
|
- libraryId
|
|
- libraryName
|
|
- mediaType
|
|
- enabledOverlays
|
|
|
|
PlexConnection:
|
|
type: object
|
|
properties:
|
|
protocol:
|
|
type: string
|
|
example: 'https'
|
|
address:
|
|
type: string
|
|
example: '127.0.0.1'
|
|
port:
|
|
type: number
|
|
example: 32400
|
|
uri:
|
|
type: string
|
|
example: 'https://127-0-0-1.2ab6ce1a093d465e910def96cf4e4799.plex.direct:32400'
|
|
local:
|
|
type: boolean
|
|
example: true
|
|
status:
|
|
type: number
|
|
example: 200
|
|
message:
|
|
type: string
|
|
example: 'OK'
|
|
required:
|
|
- protocol
|
|
- address
|
|
- port
|
|
- uri
|
|
- local
|
|
PlexDevice:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
example: 'My Plex Server'
|
|
product:
|
|
type: string
|
|
example: 'Plex Media Server'
|
|
productVersion:
|
|
type: string
|
|
example: '1.21'
|
|
platform:
|
|
type: string
|
|
example: 'Linux'
|
|
platformVersion:
|
|
type: string
|
|
example: 'default/linux/amd64/17.1/systemd'
|
|
device:
|
|
type: string
|
|
example: 'PC'
|
|
clientIdentifier:
|
|
type: string
|
|
example: '85a943ce-a0cc-4d2a-a4ec-f74f06e40feb'
|
|
createdAt:
|
|
type: string
|
|
example: '2021-01-01T00:00:00.000Z'
|
|
lastSeenAt:
|
|
type: string
|
|
example: '2021-01-01T00:00:00.000Z'
|
|
provides:
|
|
type: array
|
|
items:
|
|
type: string
|
|
example: 'server'
|
|
owned:
|
|
type: boolean
|
|
example: true
|
|
ownerID:
|
|
type: string
|
|
example: '12345'
|
|
home:
|
|
type: boolean
|
|
example: true
|
|
sourceTitle:
|
|
type: string
|
|
example: 'xyzabc'
|
|
accessToken:
|
|
type: string
|
|
example: 'supersecretaccesstoken'
|
|
publicAddress:
|
|
type: string
|
|
example: '127.0.0.1'
|
|
httpsRequired:
|
|
type: boolean
|
|
example: true
|
|
synced:
|
|
type: boolean
|
|
example: true
|
|
relay:
|
|
type: boolean
|
|
example: true
|
|
dnsRebindingProtection:
|
|
type: boolean
|
|
example: false
|
|
natLoopbackSupported:
|
|
type: boolean
|
|
example: false
|
|
publicAddressMatches:
|
|
type: boolean
|
|
example: false
|
|
presence:
|
|
type: boolean
|
|
example: true
|
|
connection:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/PlexConnection'
|
|
required:
|
|
- name
|
|
- product
|
|
- productVersion
|
|
- platform
|
|
- device
|
|
- clientIdentifier
|
|
- createdAt
|
|
- lastSeenAt
|
|
- provides
|
|
- owned
|
|
- connection
|
|
TautulliSettings:
|
|
type: object
|
|
properties:
|
|
hostname:
|
|
type: string
|
|
nullable: true
|
|
example: 'tautulli.example.com'
|
|
port:
|
|
type: number
|
|
nullable: true
|
|
example: 8181
|
|
useSsl:
|
|
type: boolean
|
|
nullable: true
|
|
urlBase:
|
|
type: string
|
|
nullable: true
|
|
example: '/tautulli'
|
|
apiKey:
|
|
type: string
|
|
nullable: true
|
|
externalUrl:
|
|
type: string
|
|
nullable: true
|
|
MaintainerrSettings:
|
|
type: object
|
|
properties:
|
|
hostname:
|
|
type: string
|
|
nullable: true
|
|
example: 'maintainerr.example.com'
|
|
port:
|
|
type: number
|
|
nullable: true
|
|
example: 6246
|
|
useSsl:
|
|
type: boolean
|
|
nullable: true
|
|
urlBase:
|
|
type: string
|
|
nullable: true
|
|
example: ''
|
|
apiKey:
|
|
type: string
|
|
nullable: true
|
|
externalUrl:
|
|
type: string
|
|
nullable: true
|
|
TraktSettings:
|
|
type: object
|
|
properties:
|
|
clientId:
|
|
type: string
|
|
nullable: true
|
|
description: 'Trakt client ID'
|
|
example: 'your-trakt-client-id'
|
|
clientSecret:
|
|
type: string
|
|
nullable: true
|
|
description: 'Trakt client secret'
|
|
example: 'your-trakt-client-secret'
|
|
accessToken:
|
|
type: string
|
|
nullable: true
|
|
description: 'Trakt personal access token'
|
|
example: 'your-trakt-access-token'
|
|
refreshToken:
|
|
type: string
|
|
nullable: true
|
|
description: 'Trakt refresh token'
|
|
example: 'your-trakt-refresh-token'
|
|
tokenExpiresAt:
|
|
type: integer
|
|
format: int64
|
|
nullable: true
|
|
description: 'Unix epoch milliseconds when the current access token expires'
|
|
apiKey:
|
|
type: string
|
|
nullable: true
|
|
deprecated: true
|
|
description: 'Legacy Trakt client ID field (deprecated)'
|
|
MDBListSettings:
|
|
type: object
|
|
properties:
|
|
apiKey:
|
|
type: string
|
|
nullable: true
|
|
example: 'your-mdblist-api-key-here'
|
|
MyAnimeListSettings:
|
|
type: object
|
|
properties:
|
|
apiKey:
|
|
type: string
|
|
nullable: true
|
|
example: 'your-myanimelist-api-key-here'
|
|
OverseerrSettings:
|
|
type: object
|
|
properties:
|
|
hostname:
|
|
type: string
|
|
nullable: true
|
|
example: 'overseerr.example.com'
|
|
port:
|
|
type: number
|
|
nullable: true
|
|
example: 5055
|
|
useSsl:
|
|
type: boolean
|
|
nullable: true
|
|
example: false
|
|
urlBase:
|
|
type: string
|
|
nullable: true
|
|
example: '/overseerr'
|
|
apiKey:
|
|
type: string
|
|
nullable: true
|
|
example: 'your-agregarr-api-key-here'
|
|
externalUrl:
|
|
type: string
|
|
nullable: true
|
|
example: 'https://overseerr.example.com:5055'
|
|
radarrServerId:
|
|
type: number
|
|
nullable: true
|
|
example: 1
|
|
description: 'Default Radarr server ID for movie requests'
|
|
radarrProfileId:
|
|
type: number
|
|
nullable: true
|
|
example: 1
|
|
description: 'Default Radarr quality profile ID for movie requests'
|
|
radarrRootFolder:
|
|
type: string
|
|
nullable: true
|
|
example: '/data/media/movies'
|
|
description: 'Default Radarr root folder path for movie requests'
|
|
radarrTags:
|
|
type: array
|
|
items:
|
|
type: integer
|
|
nullable: true
|
|
example: [1, 2]
|
|
description: 'Default Radarr tags for movie requests'
|
|
sonarrServerId:
|
|
type: number
|
|
nullable: true
|
|
example: 2
|
|
description: 'Default Sonarr server ID for TV requests'
|
|
sonarrProfileId:
|
|
type: number
|
|
nullable: true
|
|
example: 1
|
|
description: 'Default Sonarr quality profile ID for TV requests'
|
|
sonarrRootFolder:
|
|
type: string
|
|
nullable: true
|
|
example: '/data/media/tv'
|
|
description: 'Default Sonarr root folder path for TV requests'
|
|
sonarrTags:
|
|
type: array
|
|
items:
|
|
type: integer
|
|
nullable: true
|
|
example: [1, 2]
|
|
description: 'Default Sonarr tags for TV requests'
|
|
ServiceUserSettings:
|
|
type: object
|
|
properties:
|
|
userCreationMode:
|
|
type: string
|
|
enum: ['single', 'per-service', 'granular']
|
|
example: 'per-service'
|
|
description: 'How to create service users - single (one Agregarr user), per-service (TraktAgregarr, TMDbAgregarr), or granular (TraktTrendingAgregarr, TMDbPopularAgregarr)'
|
|
RadarrSettings:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: number
|
|
example: 0
|
|
readOnly: true
|
|
name:
|
|
type: string
|
|
example: 'Radarr Main'
|
|
hostname:
|
|
type: string
|
|
example: '127.0.0.1'
|
|
port:
|
|
type: number
|
|
example: 7878
|
|
apiKey:
|
|
type: string
|
|
example: 'exampleapikey'
|
|
useSsl:
|
|
type: boolean
|
|
example: false
|
|
baseUrl:
|
|
type: string
|
|
activeProfileId:
|
|
type: number
|
|
example: 1
|
|
activeProfileName:
|
|
type: string
|
|
example: 720p/1080p
|
|
activeDirectory:
|
|
type: string
|
|
example: '/movies'
|
|
minimumAvailability:
|
|
type: string
|
|
example: 'In Cinema'
|
|
isDefault:
|
|
type: boolean
|
|
example: false
|
|
externalUrl:
|
|
type: string
|
|
example: http://radarr.example.com
|
|
syncEnabled:
|
|
type: boolean
|
|
example: false
|
|
preventSearch:
|
|
type: boolean
|
|
example: false
|
|
pathMappings:
|
|
type: array
|
|
description: 'Path mappings for cross-platform/remote setups (e.g., Windows Radarr → Linux Agregarr)'
|
|
items:
|
|
type: object
|
|
properties:
|
|
from:
|
|
type: string
|
|
description: 'Remote path from Radarr (e.g., "C:\\serverdata\\media")'
|
|
example: 'C:\\serverdata\\media'
|
|
to:
|
|
type: string
|
|
description: 'Local path accessible by Agregarr (e.g., "/mnt/serverdata/media")'
|
|
example: '/mnt/serverdata/media'
|
|
required:
|
|
- from
|
|
- to
|
|
required:
|
|
- hostname
|
|
- port
|
|
- apiKey
|
|
- useSsl
|
|
- activeProfileId
|
|
- activeProfileName
|
|
- activeDirectory
|
|
- minimumAvailability
|
|
- isDefault
|
|
SonarrSettings:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: number
|
|
example: 0
|
|
readOnly: true
|
|
name:
|
|
type: string
|
|
example: 'Sonarr Main'
|
|
hostname:
|
|
type: string
|
|
example: '127.0.0.1'
|
|
port:
|
|
type: number
|
|
example: 8989
|
|
apiKey:
|
|
type: string
|
|
example: 'exampleapikey'
|
|
useSsl:
|
|
type: boolean
|
|
example: false
|
|
baseUrl:
|
|
type: string
|
|
activeProfileId:
|
|
type: number
|
|
example: 1
|
|
activeProfileName:
|
|
type: string
|
|
example: 720p/1080p
|
|
activeDirectory:
|
|
type: string
|
|
example: '/tv/'
|
|
activeLanguageProfileId:
|
|
type: number
|
|
example: 1
|
|
activeAnimeProfileId:
|
|
type: number
|
|
nullable: true
|
|
activeAnimeLanguageProfileId:
|
|
type: number
|
|
nullable: true
|
|
activeAnimeProfileName:
|
|
type: string
|
|
example: 720p/1080p
|
|
nullable: true
|
|
activeAnimeDirectory:
|
|
type: string
|
|
nullable: true
|
|
enableSeasonFolders:
|
|
type: boolean
|
|
example: false
|
|
seriesType:
|
|
type: string
|
|
enum: [standard, daily, anime]
|
|
example: standard
|
|
tags:
|
|
type: array
|
|
items:
|
|
type: number
|
|
example: [1, 2]
|
|
is4k:
|
|
type: boolean
|
|
example: false
|
|
isDefault:
|
|
type: boolean
|
|
example: false
|
|
externalUrl:
|
|
type: string
|
|
example: http://radarr.example.com
|
|
syncEnabled:
|
|
type: boolean
|
|
example: false
|
|
preventSearch:
|
|
type: boolean
|
|
example: false
|
|
tagRequests:
|
|
type: boolean
|
|
example: false
|
|
tagRequestsMode:
|
|
type: string
|
|
enum: [off, single, per-service, granular]
|
|
example: off
|
|
pathMappings:
|
|
type: array
|
|
description: 'Path mappings for cross-platform/remote setups (e.g., Windows Sonarr → Linux Agregarr)'
|
|
items:
|
|
type: object
|
|
properties:
|
|
from:
|
|
type: string
|
|
description: 'Remote path from Sonarr (e.g., "C:\\serverdata\\media")'
|
|
example: 'C:\\serverdata\\tv'
|
|
to:
|
|
type: string
|
|
description: 'Local path accessible by Agregarr (e.g., "/mnt/serverdata/tv")'
|
|
example: '/mnt/serverdata/tv'
|
|
required:
|
|
- from
|
|
- to
|
|
required:
|
|
- hostname
|
|
- port
|
|
- apiKey
|
|
- useSsl
|
|
- activeProfileId
|
|
- activeProfileName
|
|
- activeDirectory
|
|
- isDefault
|
|
ServarrTag:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: number
|
|
example: 1
|
|
label:
|
|
type: string
|
|
example: A Label
|
|
WatchlistSyncSettings:
|
|
type: object
|
|
properties:
|
|
enableOwner:
|
|
type: boolean
|
|
example: false
|
|
description: Enable watchlist sync for the server owner/admin
|
|
enableUsers:
|
|
type: boolean
|
|
example: false
|
|
description: Enable watchlist sync for all Plex users on the server
|
|
radarr:
|
|
type: object
|
|
properties:
|
|
enabled:
|
|
type: boolean
|
|
example: false
|
|
description: Enable movie watchlist sync to Radarr
|
|
serverId:
|
|
type: number
|
|
example: 1
|
|
nullable: true
|
|
description: Selected Radarr server ID
|
|
profileId:
|
|
type: number
|
|
example: 1
|
|
nullable: true
|
|
description: Quality profile override
|
|
rootFolder:
|
|
type: string
|
|
example: /movies/
|
|
nullable: true
|
|
description: Root folder override
|
|
tags:
|
|
type: array
|
|
items:
|
|
type: number
|
|
example: [1, 2]
|
|
nullable: true
|
|
description: Tags to apply to watchlist items
|
|
monitor:
|
|
type: boolean
|
|
example: true
|
|
nullable: true
|
|
description: Monitor by default override
|
|
searchOnAdd:
|
|
type: boolean
|
|
example: true
|
|
nullable: true
|
|
description: Search on add override
|
|
sonarr:
|
|
type: object
|
|
properties:
|
|
enabled:
|
|
type: boolean
|
|
example: false
|
|
description: Enable TV show watchlist sync to Sonarr
|
|
serverId:
|
|
type: number
|
|
example: 1
|
|
nullable: true
|
|
description: Selected Sonarr server ID
|
|
profileId:
|
|
type: number
|
|
example: 1
|
|
nullable: true
|
|
description: Quality profile override
|
|
rootFolder:
|
|
type: string
|
|
example: /tv/
|
|
nullable: true
|
|
description: Root folder override
|
|
tags:
|
|
type: array
|
|
items:
|
|
type: number
|
|
example: [1, 2]
|
|
nullable: true
|
|
description: Tags to apply to watchlist items
|
|
monitor:
|
|
type: boolean
|
|
example: true
|
|
nullable: true
|
|
description: Monitor by default override
|
|
searchOnAdd:
|
|
type: boolean
|
|
example: true
|
|
nullable: true
|
|
description: Search on add override
|
|
seasonFolder:
|
|
type: boolean
|
|
example: true
|
|
nullable: true
|
|
description: Season folder override
|
|
lastSyncAt:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
description: Timestamp of last successful sync
|
|
lastSyncError:
|
|
type: string
|
|
nullable: true
|
|
description: Last sync error message if any
|
|
PublicSettings:
|
|
type: object
|
|
properties:
|
|
initialized:
|
|
type: boolean
|
|
example: false
|
|
MovieResult:
|
|
type: object
|
|
required:
|
|
- id
|
|
- mediaType
|
|
- title
|
|
properties:
|
|
id:
|
|
type: number
|
|
example: 1234
|
|
mediaType:
|
|
type: string
|
|
popularity:
|
|
type: number
|
|
example: 10
|
|
posterPath:
|
|
type: string
|
|
backdropPath:
|
|
type: string
|
|
voteCount:
|
|
type: number
|
|
voteAverage:
|
|
type: number
|
|
genreIds:
|
|
type: array
|
|
items:
|
|
type: number
|
|
overview:
|
|
type: string
|
|
example: 'Overview of the movie'
|
|
originalLanguage:
|
|
type: string
|
|
example: 'en'
|
|
title:
|
|
type: string
|
|
example: Movie Title
|
|
originalTitle:
|
|
type: string
|
|
example: Original Movie Title
|
|
releaseDate:
|
|
type: string
|
|
adult:
|
|
type: boolean
|
|
example: false
|
|
video:
|
|
type: boolean
|
|
example: false
|
|
TvResult:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: number
|
|
example: 1234
|
|
mediaType:
|
|
type: string
|
|
popularity:
|
|
type: number
|
|
example: 10
|
|
posterPath:
|
|
type: string
|
|
backdropPath:
|
|
type: string
|
|
voteCount:
|
|
type: number
|
|
voteAverage:
|
|
type: number
|
|
genreIds:
|
|
type: array
|
|
items:
|
|
type: number
|
|
overview:
|
|
type: string
|
|
example: 'Overview of the movie'
|
|
originalLanguage:
|
|
type: string
|
|
example: 'en'
|
|
name:
|
|
type: string
|
|
example: TV Show Name
|
|
originalName:
|
|
type: string
|
|
example: Original TV Show Name
|
|
originCountry:
|
|
type: array
|
|
items:
|
|
type: string
|
|
firstAirDate:
|
|
type: string
|
|
PersonResult:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: number
|
|
example: 12345
|
|
profilePath:
|
|
type: string
|
|
adult:
|
|
type: boolean
|
|
example: false
|
|
mediaType:
|
|
type: string
|
|
default: 'person'
|
|
knownFor:
|
|
type: array
|
|
items:
|
|
oneOf:
|
|
- $ref: '#/components/schemas/MovieResult'
|
|
- $ref: '#/components/schemas/TvResult'
|
|
Genre:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: number
|
|
example: 1
|
|
name:
|
|
type: string
|
|
example: Adventure
|
|
Company:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: number
|
|
example: 1
|
|
logo_path:
|
|
type: string
|
|
nullable: true
|
|
name:
|
|
type: string
|
|
ProductionCompany:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: number
|
|
example: 1
|
|
logoPath:
|
|
type: string
|
|
nullable: true
|
|
originCountry:
|
|
type: string
|
|
name:
|
|
type: string
|
|
Network:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: number
|
|
example: 1
|
|
logoPath:
|
|
type: string
|
|
nullable: true
|
|
originCountry:
|
|
type: string
|
|
name:
|
|
type: string
|
|
RelatedVideo:
|
|
type: object
|
|
properties:
|
|
url:
|
|
type: string
|
|
example: https://www.youtube.com/watch?v=9qhL2_UxXM0/
|
|
key:
|
|
type: string
|
|
example: 9qhL2_UxXM0
|
|
name:
|
|
type: string
|
|
example: Trailer for some movie (1978)
|
|
size:
|
|
type: number
|
|
example: 1080
|
|
type:
|
|
type: string
|
|
example: Trailer
|
|
enum:
|
|
- Clip
|
|
- Teaser
|
|
- Trailer
|
|
- Featurette
|
|
- Opening Credits
|
|
- Behind the Scenes
|
|
- Bloopers
|
|
site:
|
|
type: string
|
|
enum:
|
|
- 'YouTube'
|
|
MovieDetails:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: number
|
|
example: 123
|
|
readOnly: true
|
|
imdbId:
|
|
type: string
|
|
example: 'tt123'
|
|
adult:
|
|
type: boolean
|
|
backdropPath:
|
|
type: string
|
|
posterPath:
|
|
type: string
|
|
budget:
|
|
type: number
|
|
example: 1000000
|
|
genres:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/Genre'
|
|
homepage:
|
|
type: string
|
|
relatedVideos:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/RelatedVideo'
|
|
originalLanguage:
|
|
type: string
|
|
originalTitle:
|
|
type: string
|
|
overview:
|
|
type: string
|
|
popularity:
|
|
type: number
|
|
productionCompanies:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/ProductionCompany'
|
|
productionCountries:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
iso_3166_1:
|
|
type: string
|
|
name:
|
|
type: string
|
|
releaseDate:
|
|
type: string
|
|
releases:
|
|
type: object
|
|
properties:
|
|
results:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
iso_3166_1:
|
|
type: string
|
|
example: 'US'
|
|
rating:
|
|
type: string
|
|
nullable: true
|
|
release_dates:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
certification:
|
|
type: string
|
|
example: 'PG-13'
|
|
iso_639_1:
|
|
type: string
|
|
nullable: true
|
|
note:
|
|
type: string
|
|
nullable: true
|
|
example: 'Blu ray'
|
|
release_date:
|
|
type: string
|
|
example: '2017-07-12T00:00:00.000Z'
|
|
type:
|
|
type: number
|
|
example: 1
|
|
revenue:
|
|
type: number
|
|
nullable: true
|
|
runtime:
|
|
type: number
|
|
status:
|
|
type: string
|
|
tagline:
|
|
type: string
|
|
title:
|
|
type: string
|
|
video:
|
|
type: boolean
|
|
voteAverage:
|
|
type: number
|
|
voteCount:
|
|
type: number
|
|
collection:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: number
|
|
example: 1
|
|
name:
|
|
type: string
|
|
example: A collection
|
|
posterPath:
|
|
type: string
|
|
backdropPath:
|
|
type: string
|
|
externalIds:
|
|
$ref: '#/components/schemas/ExternalIds'
|
|
watchProviders:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/WatchProviders'
|
|
Episode:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: number
|
|
name:
|
|
type: string
|
|
airDate:
|
|
type: string
|
|
nullable: true
|
|
episodeNumber:
|
|
type: number
|
|
overview:
|
|
type: string
|
|
productionCode:
|
|
type: string
|
|
seasonNumber:
|
|
type: number
|
|
showId:
|
|
type: number
|
|
stillPath:
|
|
type: string
|
|
nullable: true
|
|
voteAverage:
|
|
type: number
|
|
voteCount:
|
|
type: number
|
|
Season:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: number
|
|
airDate:
|
|
type: string
|
|
nullable: true
|
|
episodeCount:
|
|
type: number
|
|
name:
|
|
type: string
|
|
overview:
|
|
type: string
|
|
posterPath:
|
|
type: string
|
|
seasonNumber:
|
|
type: number
|
|
episodes:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/Episode'
|
|
TvDetails:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: number
|
|
example: 123
|
|
backdropPath:
|
|
type: string
|
|
posterPath:
|
|
type: string
|
|
contentRatings:
|
|
type: object
|
|
properties:
|
|
results:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
iso_3166_1:
|
|
type: string
|
|
example: 'US'
|
|
rating:
|
|
type: string
|
|
example: 'TV-14'
|
|
createdBy:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: number
|
|
name:
|
|
type: string
|
|
gender:
|
|
type: number
|
|
profilePath:
|
|
type: string
|
|
nullable: true
|
|
episodeRunTime:
|
|
type: array
|
|
items:
|
|
type: number
|
|
firstAirDate:
|
|
type: string
|
|
genres:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/Genre'
|
|
homepage:
|
|
type: string
|
|
inProduction:
|
|
type: boolean
|
|
languages:
|
|
type: array
|
|
items:
|
|
type: string
|
|
lastAirDate:
|
|
type: string
|
|
lastEpisodeToAir:
|
|
$ref: '#/components/schemas/Episode'
|
|
name:
|
|
type: string
|
|
nextEpisodeToAir:
|
|
$ref: '#/components/schemas/Episode'
|
|
networks:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/ProductionCompany'
|
|
numberOfEpisodes:
|
|
type: number
|
|
numberOfSeason:
|
|
type: number
|
|
originCountry:
|
|
type: array
|
|
items:
|
|
type: string
|
|
originalLanguage:
|
|
type: string
|
|
originalName:
|
|
type: string
|
|
overview:
|
|
type: string
|
|
popularity:
|
|
type: number
|
|
productionCompanies:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/ProductionCompany'
|
|
productionCountries:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
iso_3166_1:
|
|
type: string
|
|
name:
|
|
type: string
|
|
seasons:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/Season'
|
|
status:
|
|
type: string
|
|
tagline:
|
|
type: string
|
|
type:
|
|
type: string
|
|
voteAverage:
|
|
type: number
|
|
voteCount:
|
|
type: number
|
|
externalIds:
|
|
$ref: '#/components/schemas/ExternalIds'
|
|
keywords:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/Keyword'
|
|
watchProviders:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/WatchProviders'
|
|
ExternalIds:
|
|
type: object
|
|
properties:
|
|
facebookId:
|
|
type: string
|
|
nullable: true
|
|
freebaseId:
|
|
type: string
|
|
nullable: true
|
|
freebaseMid:
|
|
type: string
|
|
nullable: true
|
|
imdbId:
|
|
type: string
|
|
nullable: true
|
|
instagramId:
|
|
type: string
|
|
nullable: true
|
|
tvdbId:
|
|
type: number
|
|
nullable: true
|
|
tvrageId:
|
|
type: number
|
|
nullable: true
|
|
twitterId:
|
|
type: string
|
|
nullable: true
|
|
ServiceProfile:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: number
|
|
example: 1
|
|
name:
|
|
type: string
|
|
example: 720p/1080p
|
|
PageInfo:
|
|
type: object
|
|
properties:
|
|
page:
|
|
type: number
|
|
example: 1
|
|
pages:
|
|
type: number
|
|
example: 10
|
|
results:
|
|
type: number
|
|
example: 100
|
|
Job:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
example: job-name
|
|
type:
|
|
type: string
|
|
enum: [process, command]
|
|
interval:
|
|
type: string
|
|
enum: [seconds, minutes, hours, fixed]
|
|
name:
|
|
type: string
|
|
example: A Job Name
|
|
cronSchedule:
|
|
type: string
|
|
example: '0 */15 * * * *'
|
|
nextExecutionTime:
|
|
type: string
|
|
example: '2020-09-02T05:02:23.000Z'
|
|
followingExecutionTime:
|
|
type: string
|
|
nullable: true
|
|
example: '2020-09-02T05:17:23.000Z'
|
|
running:
|
|
type: boolean
|
|
example: false
|
|
Keyword:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: number
|
|
example: 1
|
|
name:
|
|
type: string
|
|
example: 'anime'
|
|
SonarrSeries:
|
|
type: object
|
|
properties:
|
|
title:
|
|
type: string
|
|
example: COVID-25
|
|
sortTitle:
|
|
type: string
|
|
example: covid 25
|
|
seasonCount:
|
|
type: number
|
|
example: 1
|
|
status:
|
|
type: string
|
|
example: upcoming
|
|
overview:
|
|
type: string
|
|
example: The thread is picked up again by Marianne Schmidt which ...
|
|
network:
|
|
type: string
|
|
example: CBS
|
|
airTime:
|
|
type: string
|
|
example: 02:15
|
|
images:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
coverType:
|
|
type: string
|
|
example: banner
|
|
url:
|
|
type: string
|
|
example: /sonarr/MediaCoverProxy/6467f05d9872726ad08cbf920e5fee4bf69198682260acab8eab5d3c2c958e92/5c8f116c6aa5c.jpg
|
|
remotePoster:
|
|
type: string
|
|
example: https://artworks.thetvdb.com/banners/posters/5c8f116129983.jpg
|
|
seasons:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
seasonNumber:
|
|
type: number
|
|
example: 1
|
|
monitored:
|
|
type: boolean
|
|
example: true
|
|
year:
|
|
type: number
|
|
example: 2015
|
|
path:
|
|
type: string
|
|
profileId:
|
|
type: number
|
|
languageProfileId:
|
|
type: number
|
|
seasonFolder:
|
|
type: boolean
|
|
monitored:
|
|
type: boolean
|
|
useSceneNumbering:
|
|
type: boolean
|
|
runtime:
|
|
type: number
|
|
tvdbId:
|
|
type: number
|
|
example: 12345
|
|
tvRageId:
|
|
type: number
|
|
tvMazeId:
|
|
type: number
|
|
firstAired:
|
|
type: string
|
|
lastInfoSync:
|
|
type: string
|
|
nullable: true
|
|
seriesType:
|
|
type: string
|
|
cleanTitle:
|
|
type: string
|
|
imdbId:
|
|
type: string
|
|
titleSlug:
|
|
type: string
|
|
certification:
|
|
type: string
|
|
genres:
|
|
type: array
|
|
items:
|
|
type: string
|
|
tags:
|
|
type: array
|
|
items:
|
|
type: string
|
|
added:
|
|
type: string
|
|
ratings:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
votes:
|
|
type: number
|
|
value:
|
|
type: number
|
|
qualityProfileId:
|
|
type: number
|
|
id:
|
|
type: number
|
|
nullable: true
|
|
rootFolderPath:
|
|
type: string
|
|
nullable: true
|
|
addOptions:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
ignoreEpisodesWithFiles:
|
|
type: boolean
|
|
nullable: true
|
|
ignoreEpisodesWithoutFiles:
|
|
type: boolean
|
|
nullable: true
|
|
searchForMissingEpisodes:
|
|
type: boolean
|
|
nullable: true
|
|
WatchProviders:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
iso_3166_1:
|
|
type: string
|
|
link:
|
|
type: string
|
|
buy:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/WatchProviderDetails'
|
|
flatrate:
|
|
items:
|
|
$ref: '#/components/schemas/WatchProviderDetails'
|
|
WatchProviderDetails:
|
|
type: object
|
|
properties:
|
|
displayPriority:
|
|
type: number
|
|
logoPath:
|
|
type: string
|
|
id:
|
|
type: number
|
|
name:
|
|
type: string
|
|
WatchProviderRegion:
|
|
type: object
|
|
properties:
|
|
iso_3166_1:
|
|
type: string
|
|
english_name:
|
|
type: string
|
|
native_name:
|
|
type: string
|
|
MissingItemRequest:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
example: 1
|
|
tmdbId:
|
|
type: integer
|
|
example: 550
|
|
mediaType:
|
|
type: string
|
|
enum: [movie, tv]
|
|
example: movie
|
|
title:
|
|
type: string
|
|
example: 'Fight Club'
|
|
posterPath:
|
|
type: string
|
|
nullable: true
|
|
example: '/pB8BM7pdSp6B6Ih7QZ4DrQ3PmJK.jpg'
|
|
year:
|
|
type: integer
|
|
nullable: true
|
|
example: 1999
|
|
collectionName:
|
|
type: string
|
|
example: 'Trending Movies'
|
|
collectionSource:
|
|
type: string
|
|
enum:
|
|
[
|
|
trakt,
|
|
tmdb,
|
|
imdb,
|
|
letterboxd,
|
|
mdblist,
|
|
tautulli,
|
|
networks,
|
|
originals,
|
|
overseerr,
|
|
anilist,
|
|
myanimelist,
|
|
radarrtag,
|
|
sonarrtag,
|
|
comingsoon,
|
|
filtered_hub,
|
|
multi-source,
|
|
]
|
|
example: 'trakt'
|
|
collectionSubtype:
|
|
type: string
|
|
nullable: true
|
|
example: 'trending'
|
|
requestService:
|
|
type: string
|
|
enum: [overseerr, radarr, sonarr]
|
|
example: 'overseerr'
|
|
requestMethod:
|
|
type: string
|
|
enum: [auto, manual]
|
|
example: 'auto'
|
|
requestStatus:
|
|
type: string
|
|
enum:
|
|
[
|
|
pending,
|
|
approved,
|
|
declined,
|
|
available,
|
|
processing,
|
|
failed,
|
|
partially_available,
|
|
]
|
|
example: 'approved'
|
|
overseerrRequestId:
|
|
type: integer
|
|
nullable: true
|
|
example: 123
|
|
requestedBy:
|
|
type: object
|
|
nullable: true
|
|
properties:
|
|
id:
|
|
type: integer
|
|
example: 1
|
|
displayName:
|
|
type: string
|
|
example: 'TraktAgregarr'
|
|
createdAt:
|
|
type: string
|
|
format: date-time
|
|
example: '2023-12-01T10:30:00Z'
|
|
requestedAt:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
example: '2023-12-01T10:35:00Z'
|
|
MissingItemsResponse:
|
|
type: object
|
|
properties:
|
|
results:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/MissingItemRequest'
|
|
total:
|
|
type: integer
|
|
example: 150
|
|
limit:
|
|
type: integer
|
|
example: 20
|
|
offset:
|
|
type: integer
|
|
example: 0
|
|
MissingItemStats:
|
|
type: object
|
|
properties:
|
|
stats:
|
|
type: object
|
|
properties:
|
|
total:
|
|
type: integer
|
|
example: 150
|
|
pending:
|
|
type: integer
|
|
example: 45
|
|
approved:
|
|
type: integer
|
|
example: 90
|
|
declined:
|
|
type: integer
|
|
example: 10
|
|
available:
|
|
type: integer
|
|
example: 5
|
|
processing:
|
|
type: integer
|
|
example: 12
|
|
failed:
|
|
type: integer
|
|
example: 2
|
|
partially_available:
|
|
type: integer
|
|
example: 3
|
|
byMediaType:
|
|
type: object
|
|
properties:
|
|
movie:
|
|
type: integer
|
|
example: 85
|
|
tv:
|
|
type: integer
|
|
example: 65
|
|
bySource:
|
|
type: object
|
|
properties:
|
|
trakt:
|
|
type: integer
|
|
example: 60
|
|
tmdb:
|
|
type: integer
|
|
example: 45
|
|
imdb:
|
|
type: integer
|
|
example: 30
|
|
letterboxd:
|
|
type: integer
|
|
example: 15
|
|
anilist:
|
|
type: integer
|
|
example: 7
|
|
myanimelist:
|
|
type: integer
|
|
example: 5
|
|
DashboardStats:
|
|
type: object
|
|
properties:
|
|
collections:
|
|
type: object
|
|
properties:
|
|
configured:
|
|
type: integer
|
|
example: 25
|
|
active:
|
|
type: integer
|
|
example: 18
|
|
stats:
|
|
type: object
|
|
nullable: true
|
|
properties:
|
|
topCollections:
|
|
type: array
|
|
items:
|
|
type: object
|
|
totalCollections:
|
|
type: integer
|
|
example: 15
|
|
activity:
|
|
type: object
|
|
nullable: true
|
|
properties:
|
|
totalPlays:
|
|
type: integer
|
|
example: 156
|
|
moviePlays:
|
|
type: integer
|
|
example: 89
|
|
tvPlays:
|
|
type: integer
|
|
example: 67
|
|
tautulli:
|
|
type: object
|
|
nullable: true
|
|
properties:
|
|
isConnected:
|
|
type: boolean
|
|
example: true
|
|
error:
|
|
type: string
|
|
nullable: true
|
|
example: null
|
|
weeklyActivity:
|
|
type: object
|
|
nullable: true
|
|
properties:
|
|
totalPlays:
|
|
type: integer
|
|
example: 156
|
|
moviePlays:
|
|
type: integer
|
|
example: 89
|
|
tvPlays:
|
|
type: integer
|
|
example: 67
|
|
timestamp:
|
|
type: string
|
|
format: date-time
|
|
example: '2024-01-15T10:30:00Z'
|
|
CollectionStatsResponse:
|
|
type: object
|
|
properties:
|
|
collections:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/CollectionStats'
|
|
metadata:
|
|
type: object
|
|
properties:
|
|
limit:
|
|
type: integer
|
|
example: 10
|
|
statType:
|
|
type: string
|
|
enum: [plays, duration]
|
|
example: 'plays'
|
|
days:
|
|
type: integer
|
|
example: 30
|
|
timestamp:
|
|
type: string
|
|
format: date-time
|
|
example: '2024-01-15T10:30:00Z'
|
|
CollectionStats:
|
|
type: object
|
|
properties:
|
|
rating_key:
|
|
type: string
|
|
example: '12345'
|
|
title:
|
|
type: string
|
|
example: 'Marvel Movies'
|
|
media_type:
|
|
type: string
|
|
example: 'collection'
|
|
section_id:
|
|
type: integer
|
|
example: 1
|
|
section_name:
|
|
type: string
|
|
example: 'Movies'
|
|
item_count:
|
|
type: integer
|
|
example: 28
|
|
total_plays:
|
|
type: integer
|
|
example: 145
|
|
total_duration:
|
|
type: integer
|
|
example: 18000
|
|
last_played:
|
|
type: integer
|
|
nullable: true
|
|
example: 1642291200
|
|
play_count:
|
|
type: integer
|
|
nullable: true
|
|
example: 145
|
|
watch_time_stats:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
query_days:
|
|
type: integer
|
|
example: 30
|
|
total_time:
|
|
type: integer
|
|
example: 18000
|
|
total_plays:
|
|
type: integer
|
|
example: 145
|
|
user_stats:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
friendly_name:
|
|
type: string
|
|
example: 'John Doe'
|
|
user_id:
|
|
type: integer
|
|
example: 1
|
|
total_plays:
|
|
type: integer
|
|
example: 45
|
|
total_time:
|
|
type: integer
|
|
example: 5400
|
|
ActivityStatsResponse:
|
|
type: object
|
|
properties:
|
|
activity:
|
|
type: object
|
|
properties:
|
|
topMovies:
|
|
type: array
|
|
items:
|
|
type: object
|
|
topTV:
|
|
type: array
|
|
items:
|
|
type: object
|
|
tautulliInfo:
|
|
type: object
|
|
nullable: true
|
|
metadata:
|
|
type: object
|
|
properties:
|
|
days:
|
|
type: integer
|
|
example: 7
|
|
limit:
|
|
type: integer
|
|
example: 10
|
|
timestamp:
|
|
type: string
|
|
format: date-time
|
|
example: '2024-01-15T10:30:00Z'
|
|
# Discovery-specific schemas that allow collectionType to be sent (not readOnly)
|
|
PlexHubConfigForDiscovery:
|
|
type: object
|
|
description: 'PlexHubConfig schema for discovery operations - allows collectionType to be sent'
|
|
properties:
|
|
id:
|
|
type: string
|
|
description: 'Unique hub identifier (libraryId-hubIdentifier)'
|
|
example: '1-movie.recentlyadded'
|
|
hubIdentifier:
|
|
type: string
|
|
description: 'Plex built-in hub identifier'
|
|
example: 'movie.recentlyadded'
|
|
name:
|
|
type: string
|
|
description: 'Display name for the hub'
|
|
example: 'Recently Added Movies'
|
|
libraryId:
|
|
type: string
|
|
description: 'Plex library ID'
|
|
example: '1'
|
|
libraryName:
|
|
type: string
|
|
description: 'Plex library display name'
|
|
example: 'Films'
|
|
mediaType:
|
|
type: string
|
|
enum: ['movie', 'tv', 'both']
|
|
description: 'Media type of the hub'
|
|
example: 'movie'
|
|
sortOrderLibrary:
|
|
type: integer
|
|
description: 'Position/order within the library'
|
|
example: 0
|
|
visibilityConfig:
|
|
type: object
|
|
properties:
|
|
usersHome:
|
|
type: boolean
|
|
description: "Show on shared users' home screens"
|
|
example: true
|
|
serverOwnerHome:
|
|
type: boolean
|
|
description: "Show on server owner's home screen"
|
|
example: false
|
|
libraryRecommended:
|
|
type: boolean
|
|
description: 'Show in library recommended section'
|
|
example: false
|
|
required:
|
|
- usersHome
|
|
- serverOwnerHome
|
|
- libraryRecommended
|
|
isActive:
|
|
type: boolean
|
|
description: 'Whether hub is currently active'
|
|
example: true
|
|
readOnly: true
|
|
collectionType:
|
|
type: string
|
|
enum: ['default_plex_hub', 'agregarr_created', 'pre_existing']
|
|
description: 'Type of collection (determined during discovery)'
|
|
example: 'default_plex_hub'
|
|
isLinked:
|
|
type: boolean
|
|
description: 'True if hub is actively linked to other hubs'
|
|
example: false
|
|
linkId:
|
|
type: integer
|
|
description: 'Group ID for linked hubs'
|
|
example: 1
|
|
isUnlinked:
|
|
type: boolean
|
|
description: 'True if this hub was deliberately unlinked'
|
|
example: false
|
|
required:
|
|
- id
|
|
- hubIdentifier
|
|
- name
|
|
- libraryId
|
|
- libraryName
|
|
- mediaType
|
|
- sortOrderLibrary
|
|
- visibilityConfig
|
|
- isActive
|
|
|
|
PlexHubManagementResponse:
|
|
type: object
|
|
description: 'Raw Plex hub management API response with hub visibility and promotion data'
|
|
properties:
|
|
MediaContainer:
|
|
type: object
|
|
properties:
|
|
size:
|
|
type: integer
|
|
description: 'Number of hubs in the response'
|
|
example: 5
|
|
Hub:
|
|
type: array
|
|
description: 'Array of hub management data'
|
|
items:
|
|
type: object
|
|
properties:
|
|
identifier:
|
|
type: string
|
|
description: 'Plex hub identifier'
|
|
example: 'movie.recentlyadded'
|
|
title:
|
|
type: string
|
|
description: 'Hub display title'
|
|
example: 'Recently Added'
|
|
recommendationsVisibility:
|
|
type: string
|
|
enum: ['all', 'none']
|
|
description: 'Visibility in recommendations section'
|
|
example: 'all'
|
|
homeVisibility:
|
|
type: string
|
|
enum: ['all', 'none', 'admin']
|
|
description: 'Visibility on home screen'
|
|
example: 'all'
|
|
promotedToRecommended:
|
|
type: boolean
|
|
description: 'Whether hub is promoted to recommended section'
|
|
example: true
|
|
promotedToOwnHome:
|
|
type: boolean
|
|
description: "Whether hub is promoted to server owner's home"
|
|
example: false
|
|
promotedToSharedHome:
|
|
type: boolean
|
|
description: "Whether hub is promoted to shared users' home"
|
|
example: true
|
|
deletable:
|
|
type: boolean
|
|
description: 'Whether hub can be deleted (only for custom collections)'
|
|
example: true
|
|
required:
|
|
- identifier
|
|
- title
|
|
- recommendationsVisibility
|
|
- homeVisibility
|
|
- promotedToRecommended
|
|
- promotedToOwnHome
|
|
- promotedToSharedHome
|
|
required:
|
|
- size
|
|
- Hub
|
|
required:
|
|
- MediaContainer
|
|
|
|
PreExistingCollectionConfigForDiscovery:
|
|
type: object
|
|
description: 'PreExistingCollectionConfig schema for discovery operations - allows collectionType to be sent'
|
|
properties:
|
|
id:
|
|
type: string
|
|
description: 'Unique collection identifier (libraryId-collectionRatingKey)'
|
|
example: '1-35954'
|
|
collectionRatingKey:
|
|
type: string
|
|
description: 'Plex collection rating key'
|
|
example: '35954'
|
|
name:
|
|
type: string
|
|
description: 'Display name from Plex'
|
|
example: 'Action Movies'
|
|
libraryId:
|
|
type: string
|
|
description: 'Plex library ID'
|
|
example: '1'
|
|
libraryName:
|
|
type: string
|
|
description: 'Plex library display name'
|
|
example: 'Films'
|
|
mediaType:
|
|
type: string
|
|
enum: ['movie', 'tv', 'both']
|
|
description: 'Media type based on collection contents'
|
|
example: 'movie'
|
|
sortOrderHome:
|
|
type: integer
|
|
description: 'Position on Plex home screen'
|
|
example: 0
|
|
sortOrderLibrary:
|
|
type: integer
|
|
description: 'Position in library'
|
|
example: 0
|
|
visibilityConfig:
|
|
type: object
|
|
properties:
|
|
usersHome:
|
|
type: boolean
|
|
description: "Show on shared users' home screens"
|
|
example: true
|
|
serverOwnerHome:
|
|
type: boolean
|
|
description: "Show on server owner's home screen"
|
|
example: false
|
|
libraryRecommended:
|
|
type: boolean
|
|
description: 'Show in library recommended section'
|
|
example: false
|
|
required:
|
|
- usersHome
|
|
- serverOwnerHome
|
|
- libraryRecommended
|
|
isActive:
|
|
type: boolean
|
|
description: 'Whether collection is currently active'
|
|
example: true
|
|
readOnly: true
|
|
collectionType:
|
|
type: string
|
|
enum: ['default_plex_hub', 'agregarr_created', 'pre_existing']
|
|
description: 'Type of collection (determined during discovery)'
|
|
example: 'pre_existing'
|
|
isLinked:
|
|
type: boolean
|
|
description: 'True if collection is actively linked to other collections'
|
|
example: false
|
|
linkId:
|
|
type: integer
|
|
description: 'Group ID for linked collections'
|
|
example: 1
|
|
isUnlinked:
|
|
type: boolean
|
|
description: 'True if this collection was deliberately unlinked'
|
|
example: false
|
|
timeRestriction:
|
|
type: object
|
|
properties:
|
|
alwaysActive:
|
|
type: boolean
|
|
example: true
|
|
dateRanges:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
startDate:
|
|
type: string
|
|
description: 'DD-MM format'
|
|
example: '05-12'
|
|
endDate:
|
|
type: string
|
|
description: 'DD-MM format'
|
|
example: '26-12'
|
|
nullable: true
|
|
weeklySchedule:
|
|
type: object
|
|
properties:
|
|
monday:
|
|
type: boolean
|
|
tuesday:
|
|
type: boolean
|
|
wednesday:
|
|
type: boolean
|
|
thursday:
|
|
type: boolean
|
|
friday:
|
|
type: boolean
|
|
saturday:
|
|
type: boolean
|
|
sunday:
|
|
type: boolean
|
|
nullable: true
|
|
nullable: true
|
|
customPoster:
|
|
type: string
|
|
description: 'Custom poster filename'
|
|
nullable: true
|
|
autoPoster:
|
|
type: boolean
|
|
description: 'Auto-generate poster during sync'
|
|
example: true
|
|
nullable: true
|
|
required:
|
|
- id
|
|
- collectionRatingKey
|
|
- name
|
|
- libraryId
|
|
- libraryName
|
|
- mediaType
|
|
- sortOrderHome
|
|
- sortOrderLibrary
|
|
- visibilityConfig
|
|
- isActive
|
|
|
|
NetworksCountryOption:
|
|
type: object
|
|
description: 'Country option for Networks collections'
|
|
properties:
|
|
value:
|
|
type: string
|
|
description: 'Country code/identifier'
|
|
example: 'united-states'
|
|
label:
|
|
type: string
|
|
description: 'Display name for country'
|
|
example: 'United States'
|
|
required:
|
|
- value
|
|
- label
|
|
|
|
NetworksPlatformOption:
|
|
type: object
|
|
description: 'Platform option for Networks collections'
|
|
properties:
|
|
value:
|
|
type: string
|
|
description: 'Platform identifier for Networks collections'
|
|
example: 'netflix_top_10'
|
|
label:
|
|
type: string
|
|
description: 'Display name for platform'
|
|
example: 'Netflix Top 10'
|
|
required:
|
|
- value
|
|
- label
|
|
|
|
OriginalsPlatformOption:
|
|
type: object
|
|
description: 'Streaming service provider option for Originals collections'
|
|
properties:
|
|
value:
|
|
type: string
|
|
description: 'Provider identifier for Originals collections'
|
|
example: 'netflix_originals'
|
|
label:
|
|
type: string
|
|
description: 'Display name for streaming service provider'
|
|
example: 'Netflix Originals'
|
|
required:
|
|
- value
|
|
- label
|
|
|
|
responses:
|
|
NotFound:
|
|
description: Resource not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: 'not found'
|
|
errors:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
path:
|
|
type: string
|
|
example: '/api/v1/source-colors'
|
|
message:
|
|
type: string
|
|
example: 'not found'
|
|
required:
|
|
- path
|
|
- message
|
|
required:
|
|
- message
|
|
- errors
|
|
|
|
securitySchemes:
|
|
cookieAuth:
|
|
type: apiKey
|
|
name: agregarr.sid
|
|
in: cookie
|
|
apiKey:
|
|
type: apiKey
|
|
in: header
|
|
name: X-Api-Key
|
|
|
|
paths:
|
|
/genres/combined:
|
|
get:
|
|
summary: Get combined movie and TV genres
|
|
description: Returns a merged and deduplicated list of all TMDB movie and TV genres
|
|
tags:
|
|
- tmdb
|
|
responses:
|
|
'200':
|
|
description: Combined genres list
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
example: 28
|
|
name:
|
|
type: string
|
|
example: Action
|
|
/countries/combined:
|
|
get:
|
|
summary: Get combined movie and TV origin countries
|
|
description: Returns a curated list of common origin countries with localized names
|
|
tags:
|
|
- tmdb
|
|
responses:
|
|
'200':
|
|
description: Combined countries list
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
code:
|
|
type: string
|
|
example: JP
|
|
name:
|
|
type: string
|
|
example: Japan
|
|
/languages/combined:
|
|
get:
|
|
summary: Get combined movie and TV spoken languages
|
|
description: Returns a curated list of common spoken languages with localized names
|
|
tags:
|
|
- tmdb
|
|
responses:
|
|
'200':
|
|
description: Combined languages list
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
code:
|
|
type: string
|
|
example: ja
|
|
name:
|
|
type: string
|
|
example: Japanese
|
|
/movie/{id}:
|
|
get:
|
|
summary: Get movie details
|
|
description: Returns detailed information about a movie from TMDB
|
|
tags:
|
|
- movies
|
|
parameters:
|
|
- in: path
|
|
name: id
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
description: TMDB movie ID
|
|
responses:
|
|
'200':
|
|
description: Movie details
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
title:
|
|
type: string
|
|
backdrop_path:
|
|
type: string
|
|
nullable: true
|
|
poster_path:
|
|
type: string
|
|
nullable: true
|
|
'500':
|
|
description: Unable to retrieve movie
|
|
/tv/{id}:
|
|
get:
|
|
summary: Get TV show details
|
|
description: Returns detailed information about a TV show from TMDB including seasons
|
|
tags:
|
|
- tv
|
|
parameters:
|
|
- in: path
|
|
name: id
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
description: TMDB TV show ID
|
|
responses:
|
|
'200':
|
|
description: TV show details
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
name:
|
|
type: string
|
|
backdrop_path:
|
|
type: string
|
|
nullable: true
|
|
poster_path:
|
|
type: string
|
|
nullable: true
|
|
seasons:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
season_number:
|
|
type: integer
|
|
name:
|
|
type: string
|
|
episode_count:
|
|
type: integer
|
|
air_date:
|
|
type: string
|
|
nullable: true
|
|
'500':
|
|
description: Unable to retrieve TV show
|
|
/status:
|
|
get:
|
|
summary: Get Agregarr status
|
|
description: Returns the current Agregarr status in a JSON object.
|
|
security: []
|
|
tags:
|
|
- public
|
|
responses:
|
|
'200':
|
|
description: Returned status
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
version:
|
|
type: string
|
|
example: 1.0.0
|
|
commitTag:
|
|
type: string
|
|
updateAvailable:
|
|
type: boolean
|
|
commitsBehind:
|
|
type: number
|
|
restartRequired:
|
|
type: boolean
|
|
/status/appdata:
|
|
get:
|
|
summary: Get application data volume status
|
|
description: For Docker installs, returns whether or not the volume mount was configured properly. Always returns true for non-Docker installs.
|
|
security: []
|
|
tags:
|
|
- public
|
|
responses:
|
|
'200':
|
|
description: Application data volume status and path
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
appData:
|
|
type: boolean
|
|
example: true
|
|
appDataPath:
|
|
type: string
|
|
example: /app/config
|
|
/filesystem/browse:
|
|
get:
|
|
summary: Browse filesystem directories
|
|
description: Browse directories on the server filesystem for folder selection (e.g., placeholder root folders)
|
|
tags:
|
|
- filesystem
|
|
parameters:
|
|
- in: query
|
|
name: path
|
|
schema:
|
|
type: string
|
|
required: false
|
|
description: Directory path to browse (defaults to /)
|
|
example: /data/media
|
|
responses:
|
|
'200':
|
|
description: Directory listing
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
currentPath:
|
|
type: string
|
|
example: /data/media
|
|
parentPath:
|
|
type: string
|
|
nullable: true
|
|
example: /data
|
|
directories:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
example: movies
|
|
path:
|
|
type: string
|
|
example: /data/media/movies
|
|
isDirectory:
|
|
type: boolean
|
|
example: true
|
|
'400':
|
|
description: Path is not a directory
|
|
'404':
|
|
description: Directory not found or not accessible
|
|
'500':
|
|
description: Failed to browse directory
|
|
/exclusions:
|
|
get:
|
|
summary: Get global exclusions with metadata
|
|
description: Returns all globally excluded items for collections enriched with TMDB metadata (title, year, poster).
|
|
tags:
|
|
- exclusions
|
|
responses:
|
|
'200':
|
|
description: Global exclusions retrieved successfully with TMDB metadata
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
movies:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
tmdbId:
|
|
type: integer
|
|
example: 550
|
|
title:
|
|
type: string
|
|
example: Fight Club
|
|
year:
|
|
type: integer
|
|
example: 1999
|
|
posterPath:
|
|
type: string
|
|
example: /pB8BM7pdSp6B6Ih7QZ4DrQ3PmJK.jpg
|
|
description: Array of excluded movies with TMDB metadata
|
|
shows:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
example: 1399
|
|
type:
|
|
type: string
|
|
enum: [tmdb, tvdb]
|
|
example: tmdb
|
|
title:
|
|
type: string
|
|
example: Game of Thrones
|
|
year:
|
|
type: integer
|
|
example: 2011
|
|
posterPath:
|
|
type: string
|
|
example: /7WUHnWGx5OO145IRxPDUkQSh4C7.jpg
|
|
description: Array of excluded TV shows with metadata
|
|
post:
|
|
summary: Add item to global exclusions
|
|
description: Adds an item to the global exclusions list.
|
|
tags:
|
|
- exclusions
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- mediaType
|
|
properties:
|
|
tmdbId:
|
|
type: integer
|
|
example: 550
|
|
description: TMDB ID (required for movies, optional for TV)
|
|
tvdbId:
|
|
type: integer
|
|
example: 121361
|
|
description: TVDB ID (optional for TV shows)
|
|
mediaType:
|
|
type: string
|
|
enum: [movie, tv]
|
|
example: movie
|
|
responses:
|
|
'200':
|
|
description: Item added to exclusions successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
movies:
|
|
type: array
|
|
items:
|
|
type: integer
|
|
shows:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
type:
|
|
type: string
|
|
enum: [tmdb, tvdb]
|
|
'400':
|
|
description: Invalid request parameters
|
|
delete:
|
|
summary: Remove item from global exclusions
|
|
description: Removes an item from the global exclusions list.
|
|
tags:
|
|
- exclusions
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- mediaType
|
|
properties:
|
|
tmdbId:
|
|
type: integer
|
|
example: 550
|
|
description: TMDB ID (required for movies, optional for TV)
|
|
tvdbId:
|
|
type: integer
|
|
example: 121361
|
|
description: TVDB ID (optional for TV shows)
|
|
mediaType:
|
|
type: string
|
|
enum: [movie, tv]
|
|
example: movie
|
|
responses:
|
|
'200':
|
|
description: Item removed from exclusions successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
movies:
|
|
type: array
|
|
items:
|
|
type: integer
|
|
shows:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
type:
|
|
type: string
|
|
enum: [tmdb, tvdb]
|
|
'400':
|
|
description: Invalid request parameters
|
|
/collections:
|
|
get:
|
|
summary: Get collection configurations
|
|
description: Returns all collection configurations.
|
|
tags:
|
|
- collections
|
|
responses:
|
|
'200':
|
|
description: Collection configurations retrieved successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
collectionConfigs:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/CollectionConfig'
|
|
post:
|
|
summary: Save collection configurations
|
|
description: Updates collection configurations with the provided values.
|
|
tags:
|
|
- collections
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
collectionConfigs:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/CollectionConfig'
|
|
responses:
|
|
'200':
|
|
description: Collection configurations saved successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
collectionConfigs:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/CollectionConfig'
|
|
message:
|
|
type: string
|
|
example: 'Collection configurations saved successfully'
|
|
'500':
|
|
description: Failed to save collection configurations
|
|
/collections/create:
|
|
post:
|
|
summary: Create a new collection
|
|
description: Creates a new collection configuration.
|
|
tags:
|
|
- collections
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/CollectionConfigCreate'
|
|
responses:
|
|
'201':
|
|
description: Collection created successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
collectionConfig:
|
|
$ref: '#/components/schemas/CollectionConfig'
|
|
message:
|
|
type: string
|
|
example: 'Collection created successfully'
|
|
'400':
|
|
description: Bad request (e.g., duplicate collection name in library)
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Collection "Top 10 Movies" already exists in this library'
|
|
message:
|
|
type: string
|
|
example: 'A collection with the name "Top 10 Movies" already exists in library "Movies". Please choose a different name or template.'
|
|
'500':
|
|
description: Failed to create collection
|
|
/collections/{id}/settings:
|
|
put:
|
|
summary: Update individual collection settings
|
|
description: Updates settings for a specific collection while preserving computed fields.
|
|
tags:
|
|
- collections
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: Collection ID
|
|
schema:
|
|
type: string
|
|
example: 'collection-123'
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/CollectionConfigUpdate'
|
|
responses:
|
|
'200':
|
|
description: Collection settings updated successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
collectionConfig:
|
|
$ref: '#/components/schemas/CollectionConfig'
|
|
message:
|
|
type: string
|
|
example: 'Collection settings updated successfully'
|
|
'400':
|
|
description: Bad request (e.g., duplicate collection name in library)
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Collection "Top 10 Movies" already exists in this library'
|
|
message:
|
|
type: string
|
|
example: 'A collection with the name "Top 10 Movies" already exists in library "Movies". Please choose a different name or template.'
|
|
'404':
|
|
description: Collection not found
|
|
'500':
|
|
description: Failed to update collection settings
|
|
/collections/{id}:
|
|
delete:
|
|
summary: Delete individual collection
|
|
description: Delete individual collection and recalculate sort orders. If the collection is linked, all linked collections will be deleted.
|
|
tags:
|
|
- collections
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: Collection ID
|
|
schema:
|
|
type: string
|
|
example: 'collection-123'
|
|
responses:
|
|
'200':
|
|
description: Collection(s) deleted successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: '1 collection(s) deleted successfully'
|
|
deletedConfigs:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
name:
|
|
type: string
|
|
'404':
|
|
description: Collection not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Collection not found'
|
|
message:
|
|
type: string
|
|
example: 'Collection with id "collection-123" not found'
|
|
'500':
|
|
description: Failed to delete collection
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Failed to delete collection'
|
|
message:
|
|
type: string
|
|
/collections/{id}/sync:
|
|
post:
|
|
summary: Sync individual collection
|
|
description: Triggers sync for a specific collection by ID. This performs the same sync operation as the global sync but only for the specified collection, without the global preprocessing overhead.
|
|
tags:
|
|
- collections
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: Collection ID to sync
|
|
schema:
|
|
type: string
|
|
example: '10000'
|
|
responses:
|
|
'200':
|
|
description: Collection sync started successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
status:
|
|
type: string
|
|
example: 'success'
|
|
message:
|
|
type: string
|
|
example: 'Collection sync started for "Movie Collection"'
|
|
collectionId:
|
|
type: string
|
|
example: '10000'
|
|
collectionName:
|
|
type: string
|
|
example: 'Movie Collection'
|
|
'404':
|
|
description: Collection not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
status:
|
|
type: string
|
|
example: 'error'
|
|
message:
|
|
type: string
|
|
example: 'Collection with ID 10000 not found'
|
|
'500':
|
|
description: Failed to start collection sync
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
status:
|
|
type: string
|
|
example: 'error'
|
|
message:
|
|
type: string
|
|
example: 'Admin user not found'
|
|
/collections/{id}/promote:
|
|
patch:
|
|
summary: Promote collection to top section
|
|
description: Moves a collection from the A-Z alphabetical section to the promoted section with custom ordering.
|
|
tags:
|
|
- collections
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: Collection ID
|
|
schema:
|
|
type: string
|
|
example: 'collection-123'
|
|
responses:
|
|
'200':
|
|
description: Collection promoted successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
example: true
|
|
config:
|
|
$ref: '#/components/schemas/CollectionConfig'
|
|
'400':
|
|
description: Collection is already in promoted section
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Collection is already in promoted section'
|
|
'404':
|
|
description: Collection not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Collection not found'
|
|
'500':
|
|
description: Failed to promote collection
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Failed to promote collection'
|
|
/collections/{id}/demote:
|
|
patch:
|
|
summary: Demote collection to A-Z section
|
|
description: Moves a collection from the promoted section to the A-Z alphabetical section.
|
|
tags:
|
|
- collections
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: Collection ID
|
|
schema:
|
|
type: string
|
|
example: 'collection-123'
|
|
responses:
|
|
'200':
|
|
description: Collection demoted successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
example: true
|
|
config:
|
|
$ref: '#/components/schemas/CollectionConfig'
|
|
'400':
|
|
description: Collection is already in A-Z section
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Collection is already in A-Z section'
|
|
'404':
|
|
description: Collection not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Collection not found'
|
|
'500':
|
|
description: Failed to demote collection
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Failed to demote collection'
|
|
/collections/sync:
|
|
get:
|
|
summary: Get collections sync status
|
|
description: Returns the current status of collection synchronization.
|
|
tags:
|
|
- collections
|
|
responses:
|
|
'200':
|
|
description: Sync status retrieved successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
running:
|
|
type: boolean
|
|
example: false
|
|
message:
|
|
type: string
|
|
example: 'Not running'
|
|
post:
|
|
summary: Start collection sync
|
|
description: Starts a collection synchronization process in the background.
|
|
tags:
|
|
- collections
|
|
responses:
|
|
'200':
|
|
description: Collection sync started successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
status:
|
|
type: string
|
|
example: 'success'
|
|
message:
|
|
type: string
|
|
example: 'Collections sync started in background'
|
|
'400':
|
|
description: Bad request - missing configuration or connection issue
|
|
'500':
|
|
description: Failed to start collection sync
|
|
/collections/sync/status:
|
|
get:
|
|
summary: Get detailed collections sync status
|
|
description: Returns detailed sync status including current stage, progress, and global sync information.
|
|
tags:
|
|
- collections
|
|
responses:
|
|
'200':
|
|
description: Detailed sync status retrieved successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
running:
|
|
type: boolean
|
|
description: Whether a sync is currently running
|
|
example: true
|
|
currentStage:
|
|
type: string
|
|
description: Current stage of the sync process
|
|
example: 'Processing collections...'
|
|
totalCollections:
|
|
type: integer
|
|
description: Total number of collections to process
|
|
example: 15
|
|
processedCollections:
|
|
type: integer
|
|
description: Number of collections processed so far
|
|
example: 8
|
|
progress:
|
|
type: integer
|
|
description: Sync progress percentage (0-100)
|
|
example: 53
|
|
lastGlobalSyncAt:
|
|
type: string
|
|
format: date-time
|
|
description: ISO timestamp of last successful global sync
|
|
example: '2024-01-15T10:30:00.000Z'
|
|
globalSyncError:
|
|
type: string
|
|
nullable: true
|
|
description: Last global sync error message, if any
|
|
example: null
|
|
collectionsNeedingSync:
|
|
type: integer
|
|
description: Number of collections that need to be synced
|
|
example: 7
|
|
/collections/preview-template:
|
|
post:
|
|
summary: Preview a collection template
|
|
description: Generates a preview of a collection name template with given context.
|
|
tags:
|
|
- collections-utility
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
template:
|
|
type: string
|
|
example: '{{mediaType}} {{type}} Collection'
|
|
mediaType:
|
|
type: string
|
|
enum: [movie, tv]
|
|
example: 'movie'
|
|
type:
|
|
type: string
|
|
example: 'trakt'
|
|
subtype:
|
|
type: string
|
|
example: ''
|
|
customDays:
|
|
type: number
|
|
example: 30
|
|
minimumPlays:
|
|
type: number
|
|
example: 3
|
|
required:
|
|
- template
|
|
- mediaType
|
|
responses:
|
|
'200':
|
|
description: Template preview generated successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
status:
|
|
type: string
|
|
example: 'success'
|
|
preview:
|
|
type: string
|
|
example: 'Movie Trakt Collection'
|
|
'400':
|
|
description: Bad request - invalid template or parameters
|
|
'500':
|
|
description: Failed to generate template preview
|
|
/collections/fetch-title:
|
|
post:
|
|
summary: Quick validation and title extraction from external collection URL
|
|
description: Performs quick validation (first 10 items) and extracts the title from external collection URLs (Trakt, TMDB, IMDb, Letterboxd). Returns immediately with basic media type detection for fast UX. For comprehensive media type analysis, use the /collections/detect-media-type endpoint.
|
|
tags:
|
|
- collections-utility
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
url:
|
|
type: string
|
|
example: 'https://trakt.tv/users/username/lists/my-list'
|
|
type:
|
|
type: string
|
|
enum:
|
|
[
|
|
trakt,
|
|
tmdb,
|
|
imdb,
|
|
mdblist,
|
|
letterboxd,
|
|
anilist,
|
|
myanimelist,
|
|
]
|
|
example: 'trakt'
|
|
required:
|
|
- url
|
|
- type
|
|
responses:
|
|
'200':
|
|
description: Title fetched successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
status:
|
|
type: string
|
|
example: 'success'
|
|
title:
|
|
type: string
|
|
example: 'My List'
|
|
mediaType:
|
|
type: string
|
|
enum: [movie, tv, both]
|
|
example: 'movie'
|
|
'400':
|
|
description: Bad request - invalid URL or unsupported type
|
|
'429':
|
|
description: Too many requests - rate limited
|
|
'500':
|
|
description: Failed to fetch title
|
|
/collections/detect-media-type:
|
|
post:
|
|
summary: Comprehensive media type detection from external collection URL
|
|
description: Performs comprehensive analysis (up to 1000 items) to accurately detect media types from external collection URLs. This endpoint runs in the background after quick title validation to provide detailed media type information for better user guidance.
|
|
tags:
|
|
- collections-utility
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
url:
|
|
type: string
|
|
example: 'https://trakt.tv/users/username/lists/my-list'
|
|
type:
|
|
type: string
|
|
enum: [trakt, tmdb, imdb, mdblist, letterboxd]
|
|
example: 'trakt'
|
|
required:
|
|
- url
|
|
- type
|
|
responses:
|
|
'200':
|
|
description: Media type detected successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
status:
|
|
type: string
|
|
example: 'success'
|
|
mediaType:
|
|
type: string
|
|
enum: [movie, tv, both]
|
|
example: 'both'
|
|
description: 'Detected media type based on comprehensive list analysis'
|
|
'400':
|
|
description: Bad request - invalid URL, unsupported type, or failed to analyze list content
|
|
'429':
|
|
description: Too many requests - rate limited
|
|
'500':
|
|
description: Internal server error while detecting media type
|
|
/collections/poster:
|
|
post:
|
|
summary: Upload a poster image for collections
|
|
description: Uploads a custom poster image that can be used for collections. Supports JPEG, PNG, and WebP formats.
|
|
tags:
|
|
- collections-posters
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
multipart/form-data:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
poster:
|
|
type: string
|
|
format: binary
|
|
description: The poster image file
|
|
required:
|
|
- poster
|
|
responses:
|
|
'200':
|
|
description: Poster uploaded successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
filename:
|
|
type: string
|
|
example: 'f47ac10b-58cc-4372-a567-0e02b2c3d479.jpg'
|
|
url:
|
|
type: string
|
|
example: '/api/v1/collections/poster/f47ac10b-58cc-4372-a567-0e02b2c3d479.jpg'
|
|
'400':
|
|
description: Bad request - invalid file or upload error
|
|
'403':
|
|
description: Authentication required
|
|
'500':
|
|
description: Internal server error
|
|
/collections/generate-poster:
|
|
post:
|
|
summary: Generate a poster for a collection
|
|
description: Generates a custom poster based on collection configuration data. Creates text-based posters with collection type styling.
|
|
tags:
|
|
- collections-posters
|
|
security:
|
|
- cookieAuth: []
|
|
- apiKeyAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
collectionName:
|
|
type: string
|
|
description: Name of the collection to generate poster for
|
|
example: 'Top Trakt Movies'
|
|
collectionType:
|
|
type: string
|
|
description: Type of collection (trakt, tmdb, imdb, mdblist, letterboxd, tautulli, overseerr, hub)
|
|
example: 'trakt'
|
|
collectionSubtype:
|
|
type: string
|
|
description: Subtype of the collection
|
|
example: 'popular'
|
|
mediaType:
|
|
type: string
|
|
enum: [movie, tv]
|
|
description: Media type for the collection
|
|
example: 'movie'
|
|
template:
|
|
type: string
|
|
description: Collection template for additional context
|
|
example: 'Top {count} {type} from Trakt'
|
|
required:
|
|
- collectionName
|
|
responses:
|
|
'200':
|
|
description: Poster generated successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
filename:
|
|
type: string
|
|
example: 'generated_abc123def.jpg'
|
|
url:
|
|
type: string
|
|
example: '/api/v1/collections/poster/generated_abc123def.jpg'
|
|
message:
|
|
type: string
|
|
example: 'Poster generated successfully'
|
|
'400':
|
|
description: Bad request - missing or invalid collection name
|
|
'401':
|
|
description: Authentication required
|
|
'500':
|
|
description: Internal server error
|
|
/collections/download-poster:
|
|
post:
|
|
summary: Download a poster from a URL
|
|
description: Downloads a poster image from a given URL and saves it to the system. Supports JPEG, PNG, and WebP formats with automatic validation and processing.
|
|
tags:
|
|
- collections-posters
|
|
security:
|
|
- cookieAuth: []
|
|
- apiKeyAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
url:
|
|
type: string
|
|
format: uri
|
|
description: URL of the poster image to download
|
|
example: 'https://example.com/poster.jpg'
|
|
required:
|
|
- url
|
|
responses:
|
|
'200':
|
|
description: Poster downloaded successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
filename:
|
|
type: string
|
|
example: 'f47ac10b-58cc-4372-a567-0e02b2c3d479.jpg'
|
|
url:
|
|
type: string
|
|
example: '/api/v1/collections/poster/f47ac10b-58cc-4372-a567-0e02b2c3d479.jpg'
|
|
message:
|
|
type: string
|
|
example: 'Poster downloaded successfully'
|
|
'400':
|
|
description: Bad request - invalid URL, unsupported format, or file too large
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Invalid URL format'
|
|
'401':
|
|
description: Authentication required
|
|
'429':
|
|
description: Too many requests - rate limit exceeded
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Too many requests. Please try again later.'
|
|
'500':
|
|
description: Internal server error
|
|
/collections/posters:
|
|
get:
|
|
summary: List all stored poster files
|
|
description: Returns a list of all poster files currently stored in the system with their URLs.
|
|
tags:
|
|
- collections-posters
|
|
security:
|
|
- cookieAuth: []
|
|
- apiKeyAuth: []
|
|
responses:
|
|
'200':
|
|
description: List of poster files
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
posters:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
filename:
|
|
type: string
|
|
description: The filename of the poster
|
|
example: 'f47ac10b-58cc-4372-a567-0e02b2c3d479.jpg'
|
|
url:
|
|
type: string
|
|
description: The URL to access the poster
|
|
example: '/api/v1/collections/poster/f47ac10b-58cc-4372-a567-0e02b2c3d479.jpg'
|
|
'401':
|
|
description: Authentication required
|
|
'500':
|
|
description: Internal server error
|
|
/collections/poster/{filename}:
|
|
get:
|
|
summary: Serve poster image
|
|
description: Serves a poster image by filename. No authentication required.
|
|
tags:
|
|
- collections-posters
|
|
parameters:
|
|
- in: path
|
|
name: filename
|
|
required: true
|
|
description: The filename of the resource to retrieve or delete.
|
|
schema:
|
|
type: string
|
|
example: 'f47ac10b-58cc-4372-a567-0e02b2c3d479.jpg'
|
|
- in: query
|
|
name: v
|
|
required: false
|
|
description: Cache-busting version parameter (typically file modification timestamp)
|
|
schema:
|
|
type: number
|
|
responses:
|
|
'200':
|
|
description: Poster image served successfully
|
|
content:
|
|
image/jpeg:
|
|
schema:
|
|
type: string
|
|
format: binary
|
|
'404':
|
|
description: Poster not found
|
|
'500':
|
|
description: Internal server error
|
|
delete:
|
|
summary: Delete a poster image
|
|
description: Deletes a poster image by filename. If poster is in use by collections, returns 409 unless force=true is specified. Authentication required.
|
|
tags:
|
|
- collections-posters
|
|
parameters:
|
|
- in: path
|
|
name: filename
|
|
required: true
|
|
description: The filename of the resource to retrieve or delete.
|
|
schema:
|
|
type: string
|
|
example: 'f47ac10b-58cc-4372-a567-0e02b2c3d479.jpg'
|
|
- in: query
|
|
name: force
|
|
required: false
|
|
description: If true, delete poster even if it's currently in use by collections
|
|
schema:
|
|
type: boolean
|
|
default: false
|
|
responses:
|
|
'200':
|
|
description: Poster deleted successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: 'Poster deleted successfully'
|
|
'403':
|
|
description: Authentication required
|
|
'404':
|
|
description: Poster not found
|
|
'409':
|
|
description: Poster is currently in use by collections
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Poster is currently in use'
|
|
inUse:
|
|
type: boolean
|
|
example: true
|
|
usedBy:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
type:
|
|
type: string
|
|
enum: [collection, preExisting]
|
|
example: 'collection'
|
|
id:
|
|
type: string
|
|
example: 'col_123'
|
|
name:
|
|
type: string
|
|
example: 'Marvel Movies'
|
|
libraryName:
|
|
type: string
|
|
example: 'Movies'
|
|
'500':
|
|
description: Internal server error
|
|
/collections/poster/{filename}/usage:
|
|
get:
|
|
summary: Check poster usage
|
|
description: Check which collections are currently using a specific poster file. Authentication required.
|
|
tags:
|
|
- collections-posters
|
|
parameters:
|
|
- in: path
|
|
name: filename
|
|
required: true
|
|
description: The filename of the poster to check.
|
|
schema:
|
|
type: string
|
|
example: 'f47ac10b-58cc-4372-a567-0e02b2c3d479.jpg'
|
|
responses:
|
|
'200':
|
|
description: Usage information retrieved successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
filename:
|
|
type: string
|
|
example: 'f47ac10b-58cc-4372-a567-0e02b2c3d479.jpg'
|
|
inUse:
|
|
type: boolean
|
|
example: true
|
|
usedBy:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
type:
|
|
type: string
|
|
enum: [collection, preExisting]
|
|
example: 'collection'
|
|
id:
|
|
type: string
|
|
example: 'col_123'
|
|
name:
|
|
type: string
|
|
example: 'Marvel Movies'
|
|
libraryName:
|
|
type: string
|
|
example: 'Movies'
|
|
'403':
|
|
description: Authentication required
|
|
'404':
|
|
description: Poster not found
|
|
'500':
|
|
description: Internal server error
|
|
/collections/cleanup-missing:
|
|
delete:
|
|
summary: Clean up missing collections
|
|
description: Removes all collection configurations where missing is true (collections that no longer exist in Plex) and also deletes them from Plex hubs if they are present there.
|
|
tags:
|
|
- collections
|
|
responses:
|
|
'200':
|
|
description: Missing collections cleaned up successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: '3 missing collection configurations removed successfully (2 also deleted from Plex hubs)'
|
|
cleanupCount:
|
|
type: integer
|
|
description: 'Number of configurations that were removed'
|
|
example: 3
|
|
hubDeleteCount:
|
|
type: integer
|
|
description: 'Number of collections that were deleted from Plex hubs'
|
|
example: 2
|
|
'403':
|
|
description: Authentication required
|
|
'500':
|
|
description: Failed to cleanup missing collections
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Failed to cleanup missing collections'
|
|
/collections/networks/countries:
|
|
get:
|
|
summary: Get available countries for Networks collections
|
|
description: Returns all available countries/regions that can be used for Networks streaming platform collections.
|
|
tags:
|
|
- collections-utility
|
|
responses:
|
|
'200':
|
|
description: Countries retrieved successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/NetworksCountryOption'
|
|
'500':
|
|
description: Failed to fetch countries
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Failed to load available countries'
|
|
/collections/networks/platforms:
|
|
get:
|
|
summary: Get available platforms for a country
|
|
description: Returns all available streaming platforms for the specified country/region.
|
|
tags:
|
|
- collections-utility
|
|
parameters:
|
|
- name: country
|
|
in: query
|
|
required: true
|
|
schema:
|
|
type: string
|
|
description: Country code to get platforms for
|
|
example: 'united-states'
|
|
responses:
|
|
'200':
|
|
description: Platforms retrieved successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/NetworksPlatformOption'
|
|
'400':
|
|
description: Country parameter is required
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Country parameter is required'
|
|
'500':
|
|
description: Failed to fetch platforms
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Failed to load platforms for country'
|
|
/collections/originals/providers:
|
|
get:
|
|
summary: Get available streaming providers for Originals collections
|
|
description: Returns all available streaming service providers for Originals collections (Netflix, Amazon, Disney+, HBO, etc.).
|
|
tags:
|
|
- collections-utility
|
|
responses:
|
|
'200':
|
|
description: Providers retrieved successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/OriginalsPlatformOption'
|
|
'500':
|
|
description: Failed to fetch originals providers
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Failed to fetch originals providers'
|
|
/collections/preview:
|
|
post:
|
|
summary: Start a collection preview
|
|
description: Starts an asynchronous preview process and returns a session ID immediately. Client should poll /collections/preview/status/{sessionId} for progress and results.
|
|
tags:
|
|
- collections-utility
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- type
|
|
- libraryId
|
|
properties:
|
|
type:
|
|
type: string
|
|
description: Collection source type
|
|
enum:
|
|
[
|
|
trakt,
|
|
tmdb,
|
|
imdb,
|
|
letterboxd,
|
|
mdblist,
|
|
tautulli,
|
|
networks,
|
|
originals,
|
|
overseerr,
|
|
anilist,
|
|
myanimelist,
|
|
radarrtag,
|
|
sonarrtag,
|
|
comingsoon,
|
|
filtered_hub,
|
|
plex,
|
|
multi-source,
|
|
]
|
|
example: imdb
|
|
subtype:
|
|
type: string
|
|
description: Collection sub-type (e.g., 'top_250' for IMDb)
|
|
example: top_250
|
|
libraryId:
|
|
type: string
|
|
description: Plex library ID to match items against
|
|
example: '1'
|
|
customUrl:
|
|
type: string
|
|
description: Custom list URL (for custom list types)
|
|
example: 'https://www.imdb.com/list/ls123456789/'
|
|
maxItems:
|
|
type: number
|
|
description: Maximum number of items to fetch
|
|
example: 50
|
|
timePeriod:
|
|
type: string
|
|
description: Time period for Tautulli collections
|
|
enum: [daily, weekly, monthly, all, custom]
|
|
example: weekly
|
|
minimumPlays:
|
|
type: number
|
|
description: Minimum play count for Tautulli collections
|
|
example: 1
|
|
customDays:
|
|
type: number
|
|
description: Number of days for custom time period (Tautulli)
|
|
example: 30
|
|
network:
|
|
type: string
|
|
description: Network name for network collections
|
|
example: 'Netflix'
|
|
country:
|
|
type: string
|
|
description: Country code for network collections
|
|
example: 'us'
|
|
provider:
|
|
type: string
|
|
description: Provider name for originals collections
|
|
example: 'netflix'
|
|
isMultiSource:
|
|
type: boolean
|
|
description: Whether this is a multi-source collection
|
|
example: true
|
|
sources:
|
|
type: array
|
|
description: Array of source configurations for multi-source collections
|
|
items:
|
|
type: object
|
|
required:
|
|
- id
|
|
- type
|
|
- priority
|
|
properties:
|
|
id:
|
|
type: string
|
|
description: Unique identifier for this source
|
|
example: 'source-1'
|
|
type:
|
|
type: string
|
|
description: Collection source type
|
|
enum:
|
|
[
|
|
trakt,
|
|
tmdb,
|
|
imdb,
|
|
letterboxd,
|
|
mdblist,
|
|
tautulli,
|
|
networks,
|
|
originals,
|
|
overseerr,
|
|
anilist,
|
|
myanimelist,
|
|
radarrtag,
|
|
sonarrtag,
|
|
comingsoon,
|
|
filtered_hub,
|
|
]
|
|
example: 'imdb'
|
|
subtype:
|
|
type: string
|
|
description: Collection sub-type
|
|
example: 'top_250'
|
|
customUrl:
|
|
type: string
|
|
description: Custom list URL for this source
|
|
example: 'https://www.imdb.com/list/ls123456789/'
|
|
timePeriod:
|
|
type: string
|
|
description: Time period for Tautulli sources
|
|
enum: [daily, weekly, monthly, all, custom]
|
|
example: 'weekly'
|
|
priority:
|
|
type: number
|
|
description: Order priority when combining (0 = highest)
|
|
example: 0
|
|
customDays:
|
|
type: number
|
|
description: Number of days for custom time period (Tautulli)
|
|
example: 30
|
|
minimumPlays:
|
|
type: number
|
|
description: Minimum play count for Tautulli sources
|
|
example: 1
|
|
networksCountry:
|
|
type: string
|
|
description: Country code for network sources
|
|
example: 'us'
|
|
combineMode:
|
|
type: string
|
|
description: How to combine items from multiple sources
|
|
enum: [interleaved, list_order, randomised, cycle_lists]
|
|
example: 'interleaved'
|
|
cycleIndex:
|
|
type: number
|
|
description: For cycle_lists mode, which source to show (0-based index)
|
|
example: 0
|
|
default: 0
|
|
responses:
|
|
'202':
|
|
description: Preview started successfully, poll /status/{sessionId} for progress
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
sessionId:
|
|
type: string
|
|
example: 'preview-1234567890-abc123'
|
|
message:
|
|
type: string
|
|
example: 'Preview started, poll /status/:sessionId for progress'
|
|
'400':
|
|
description: Bad request - missing required fields
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Missing required fields: type and libraryId are required'
|
|
'500':
|
|
description: Failed to start preview
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Failed to start preview'
|
|
message:
|
|
type: string
|
|
/collections/preview/status/{sessionId}:
|
|
get:
|
|
summary: Get preview progress status
|
|
description: Poll this endpoint to get real-time progress updates for a preview session
|
|
tags:
|
|
- collections-utility
|
|
parameters:
|
|
- name: sessionId
|
|
in: path
|
|
required: true
|
|
description: Session ID returned from POST /collections/preview
|
|
schema:
|
|
type: string
|
|
example: 'preview-1234567890-abc123'
|
|
responses:
|
|
'200':
|
|
description: Preview status
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
running:
|
|
type: boolean
|
|
description: Whether preview is still running
|
|
example: true
|
|
currentStage:
|
|
type: string
|
|
description: Current processing stage
|
|
example: 'Fetching posters (75/250)...'
|
|
totalItems:
|
|
type: number
|
|
description: Total items to process
|
|
example: 250
|
|
processedItems:
|
|
type: number
|
|
description: Items processed so far
|
|
example: 75
|
|
progress:
|
|
type: number
|
|
description: Progress percentage (0-100)
|
|
example: 65
|
|
completed:
|
|
type: boolean
|
|
description: Whether preview is complete
|
|
example: false
|
|
error:
|
|
type: string
|
|
description: Error message if preview failed
|
|
example: null
|
|
result:
|
|
type: object
|
|
description: Preview results (only present when completed=true)
|
|
properties:
|
|
items:
|
|
type: array
|
|
description: All items in original list order
|
|
items:
|
|
type: object
|
|
properties:
|
|
ratingKey:
|
|
type: string
|
|
example: '12345'
|
|
title:
|
|
type: string
|
|
example: 'The Shawshank Redemption'
|
|
year:
|
|
type: number
|
|
example: 1994
|
|
tmdbId:
|
|
type: number
|
|
example: 278
|
|
mediaType:
|
|
type: string
|
|
enum: [movie, tv]
|
|
example: movie
|
|
posterUrl:
|
|
type: string
|
|
example: 'https://image.tmdb.org/t/p/w500/q6y0Go1tsGEsmtFryDOJo3dEmqu.jpg'
|
|
inLibrary:
|
|
type: boolean
|
|
example: true
|
|
totalItems:
|
|
type: number
|
|
example: 250
|
|
matchedCount:
|
|
type: number
|
|
example: 200
|
|
missingCount:
|
|
type: number
|
|
example: 50
|
|
'404':
|
|
description: Preview session not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Preview session not found'
|
|
/collections/preview/download:
|
|
post:
|
|
summary: Download a missing item from preview
|
|
description: Sends a download request for a missing item to Radarr, Sonarr, or Overseerr.
|
|
tags:
|
|
- collections-utility
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- tmdbId
|
|
- mediaType
|
|
- service
|
|
properties:
|
|
tmdbId:
|
|
type: number
|
|
description: TMDB ID of the item to download
|
|
example: 680
|
|
mediaType:
|
|
type: string
|
|
description: Media type
|
|
enum: [movie, tv]
|
|
example: movie
|
|
service:
|
|
type: string
|
|
description: Download service to use
|
|
enum: [radarr, sonarr, overseerr]
|
|
example: radarr
|
|
serverId:
|
|
type: number
|
|
description: Server ID for Radarr/Sonarr (optional)
|
|
example: 1
|
|
profileId:
|
|
type: number
|
|
description: Quality profile ID for Radarr/Sonarr (optional)
|
|
example: 1
|
|
rootFolder:
|
|
type: string
|
|
description: Root folder path for Radarr/Sonarr (optional)
|
|
example: /media/movies
|
|
seasons:
|
|
description: Seasons to download for TV shows (optional, array of season numbers or 'all')
|
|
oneOf:
|
|
- type: array
|
|
items:
|
|
type: number
|
|
example: [1, 2, 3]
|
|
- type: string
|
|
enum: [all]
|
|
example: all
|
|
sourceType:
|
|
type: string
|
|
description: Collection source type for service user determination (optional)
|
|
example: trakt
|
|
responses:
|
|
'200':
|
|
description: Download request sent successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
oneOf:
|
|
- type: object
|
|
description: Radarr response
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
example: true
|
|
service:
|
|
type: string
|
|
example: radarr
|
|
autoApproved:
|
|
type: number
|
|
example: 1
|
|
serverId:
|
|
type: number
|
|
example: 1
|
|
- type: object
|
|
description: Sonarr response
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
example: true
|
|
service:
|
|
type: string
|
|
example: sonarr
|
|
autoApproved:
|
|
type: number
|
|
example: 1
|
|
serverId:
|
|
type: number
|
|
example: 1
|
|
- type: object
|
|
description: Overseerr response
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
example: true
|
|
service:
|
|
type: string
|
|
example: overseerr
|
|
requestId:
|
|
type: number
|
|
example: 12345
|
|
status:
|
|
type: number
|
|
example: 2
|
|
'400':
|
|
description: Bad request
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Missing required fields: tmdbId, mediaType, and service'
|
|
'500':
|
|
description: Failed to download item
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Failed to download item'
|
|
message:
|
|
type: string
|
|
/collections/preexisting:
|
|
get:
|
|
summary: Get pre-existing Plex collections
|
|
description: Returns all Plex collections that were not created by Agregarr (collections without Agregarr labels).
|
|
tags:
|
|
- collections
|
|
responses:
|
|
'200':
|
|
description: Pre-existing collections retrieved successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
collections:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
example: '12345'
|
|
name:
|
|
type: string
|
|
example: 'My Collection'
|
|
summary:
|
|
type: string
|
|
example: 'A collection of my favorite movies'
|
|
libraryId:
|
|
type: string
|
|
example: '1'
|
|
libraryTitle:
|
|
type: string
|
|
example: 'Movies'
|
|
itemCount:
|
|
type: number
|
|
example: 25
|
|
thumb:
|
|
type: string
|
|
example: '/library/metadata/12345/thumb'
|
|
art:
|
|
type: string
|
|
example: '/library/metadata/12345/art'
|
|
guid:
|
|
type: string
|
|
example: 'com.plexapp.agents.none://12345'
|
|
updatedAt:
|
|
type: number
|
|
example: 1640995200
|
|
addedAt:
|
|
type: number
|
|
example: 1640995200
|
|
labels:
|
|
type: array
|
|
items:
|
|
type: object
|
|
'400':
|
|
description: Bad request - Plex server not configured or no admin token
|
|
'500':
|
|
description: Failed to fetch pre-existing collections
|
|
/anilist/test-trending:
|
|
get:
|
|
summary: Test AniList trending endpoint
|
|
description: Test endpoint for fetching trending anime from AniList with detailed logging.
|
|
tags:
|
|
- other
|
|
responses:
|
|
'200':
|
|
description: Trending anime fetched successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
example: true
|
|
data:
|
|
type: array
|
|
items:
|
|
type: object
|
|
'500':
|
|
description: Failed to fetch trending anime
|
|
/anilist/list:
|
|
get:
|
|
summary: Fetch AniList data
|
|
description: Fetches anime data from AniList based on the specified type (trending or popular).
|
|
tags:
|
|
- other
|
|
parameters:
|
|
- in: query
|
|
name: type
|
|
schema:
|
|
type: string
|
|
enum: [trending, popular]
|
|
required: true
|
|
description: Type of anime list to fetch
|
|
responses:
|
|
'200':
|
|
description: AniList data fetched successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
example: true
|
|
data:
|
|
type: array
|
|
items:
|
|
type: object
|
|
'400':
|
|
description: Invalid type parameter
|
|
'500':
|
|
description: Failed to fetch AniList data
|
|
/defaulthubs:
|
|
get:
|
|
summary: Get default Plex hub configurations
|
|
description: Returns all default Plex hub configurations.
|
|
tags:
|
|
- default-hubs
|
|
responses:
|
|
'200':
|
|
description: Default hub configurations retrieved successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/PlexHubConfig'
|
|
'500':
|
|
description: Failed to retrieve hub configurations
|
|
post:
|
|
summary: Save default Plex hub configurations
|
|
description: Updates default Plex hub configurations with the provided values.
|
|
tags:
|
|
- default-hubs
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
hubConfigs:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/PlexHubConfig'
|
|
responses:
|
|
'200':
|
|
description: Hub configurations saved successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/PlexHubConfig'
|
|
'500':
|
|
description: Failed to save hub configurations
|
|
/defaulthubs/{id}/settings:
|
|
put:
|
|
summary: Update individual default hub settings
|
|
description: Updates settings for a specific default hub while preserving computed fields.
|
|
tags:
|
|
- default-hubs
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: Default hub ID
|
|
schema:
|
|
type: string
|
|
example: '1-movie.recentlyadded'
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/PlexHubConfigUpdate'
|
|
responses:
|
|
'200':
|
|
description: Default hub settings updated successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
hubConfig:
|
|
$ref: '#/components/schemas/PlexHubConfig'
|
|
message:
|
|
type: string
|
|
example: 'Default hub settings updated successfully'
|
|
'404':
|
|
description: Default hub not found
|
|
'500':
|
|
description: Failed to update default hub settings
|
|
/defaulthubs/discover:
|
|
post:
|
|
summary: Discover new default hubs
|
|
description: Discovery operation for new default hubs (replaces /append for discovery).
|
|
tags:
|
|
- default-hubs
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
hubConfigs:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/PlexHubConfigForDiscovery'
|
|
responses:
|
|
'200':
|
|
description: Default hubs discovered successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
hubConfigs:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/PlexHubConfig'
|
|
message:
|
|
type: string
|
|
example: 'Default hubs discovered successfully'
|
|
'500':
|
|
description: Failed to discover default hubs
|
|
/defaulthubs/append:
|
|
post:
|
|
summary: Append default Plex hub configurations
|
|
description: Appends new default hub configurations to existing ones (for discovery).
|
|
tags:
|
|
- default-hubs
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
hubConfigs:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/PlexHubConfig'
|
|
responses:
|
|
'200':
|
|
description: Hub configurations appended successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
hubConfigs:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/PlexHubConfig'
|
|
message:
|
|
type: string
|
|
example: 'Default hub configurations appended successfully'
|
|
'400':
|
|
description: Invalid request body
|
|
'500':
|
|
description: Failed to append hub configurations
|
|
/preexisting:
|
|
get:
|
|
summary: Get pre-existing collection configurations
|
|
description: Returns all pre-existing Plex collection configurations.
|
|
tags:
|
|
- pre-existing-collections
|
|
responses:
|
|
'200':
|
|
description: Pre-existing collection configurations retrieved successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/PreExistingCollectionConfig'
|
|
'500':
|
|
description: Failed to retrieve pre-existing collection configurations
|
|
post:
|
|
summary: Save pre-existing collection configurations
|
|
description: Updates pre-existing collection configurations with the provided values.
|
|
tags:
|
|
- pre-existing-collections
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
preExistingConfigs:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/PreExistingCollectionConfig'
|
|
responses:
|
|
'200':
|
|
description: Pre-existing collection configurations saved successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/PreExistingCollectionConfig'
|
|
'500':
|
|
description: Failed to save pre-existing collection configurations
|
|
/preexisting/{id}/settings:
|
|
put:
|
|
summary: Update individual pre-existing collection settings
|
|
description: Updates settings for a specific pre-existing collection while preserving computed fields.
|
|
tags:
|
|
- pre-existing-collections
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: Pre-existing collection ID
|
|
schema:
|
|
type: string
|
|
example: '1-35954'
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/PreExistingCollectionConfigUpdate'
|
|
responses:
|
|
'200':
|
|
description: Pre-existing collection settings updated successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
preExistingCollectionConfig:
|
|
$ref: '#/components/schemas/PreExistingCollectionConfig'
|
|
message:
|
|
type: string
|
|
example: 'Pre-existing collection settings updated successfully'
|
|
'404':
|
|
description: Pre-existing collection not found
|
|
'500':
|
|
description: Failed to update pre-existing collection settings
|
|
/preexisting/{id}/promote:
|
|
patch:
|
|
summary: Promote pre-existing collection to top section
|
|
description: Moves a pre-existing collection from the A-Z alphabetical section to the promoted section with custom ordering.
|
|
tags:
|
|
- pre-existing-collections
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: Pre-existing collection ID
|
|
schema:
|
|
type: string
|
|
example: '1-35954'
|
|
responses:
|
|
'200':
|
|
description: Pre-existing collection promoted successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
example: true
|
|
config:
|
|
$ref: '#/components/schemas/PreExistingCollectionConfig'
|
|
'400':
|
|
description: Collection is already in promoted section
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Collection is already in promoted section'
|
|
'404':
|
|
description: Pre-existing collection not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Pre-existing collection not found'
|
|
'500':
|
|
description: Failed to promote pre-existing collection
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Failed to promote pre-existing collection'
|
|
/preexisting/{id}/demote:
|
|
patch:
|
|
summary: Demote pre-existing collection to A-Z section
|
|
description: Moves a pre-existing collection from the promoted section to the A-Z alphabetical section.
|
|
tags:
|
|
- pre-existing-collections
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: Pre-existing collection ID
|
|
schema:
|
|
type: string
|
|
example: '1-35954'
|
|
responses:
|
|
'200':
|
|
description: Pre-existing collection demoted successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
example: true
|
|
config:
|
|
$ref: '#/components/schemas/PreExistingCollectionConfig'
|
|
'400':
|
|
description: Collection is already in A-Z section
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Collection is already in A-Z section'
|
|
'404':
|
|
description: Pre-existing collection not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Pre-existing collection not found'
|
|
'500':
|
|
description: Failed to demote pre-existing collection
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Failed to demote pre-existing collection'
|
|
/preexisting/discover:
|
|
post:
|
|
summary: Discover new pre-existing collections
|
|
description: Discovery operation for new pre-existing collections (replaces /append for discovery).
|
|
tags:
|
|
- pre-existing-collections
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
preExistingCollectionConfigs:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/PreExistingCollectionConfigForDiscovery'
|
|
responses:
|
|
'200':
|
|
description: Pre-existing collections discovered successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
preExistingCollectionConfigs:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/PreExistingCollectionConfig'
|
|
message:
|
|
type: string
|
|
example: 'Pre-existing collections discovered successfully'
|
|
'500':
|
|
description: Failed to discover pre-existing collections
|
|
/preexisting/append:
|
|
post:
|
|
summary: Append pre-existing collection configurations
|
|
description: Appends new pre-existing collection configurations to existing ones (for discovery).
|
|
tags:
|
|
- pre-existing-collections
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
preExistingCollectionConfigs:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/DiscoveredCollectionConfig'
|
|
responses:
|
|
'200':
|
|
description: Pre-existing collection configurations appended successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
preExistingCollectionConfigs:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/PreExistingCollectionConfig'
|
|
message:
|
|
type: string
|
|
example: 'Pre-existing collection configurations appended successfully'
|
|
'400':
|
|
description: Invalid request body
|
|
'500':
|
|
description: Failed to append pre-existing collection configurations
|
|
/ratings/movie/{tmdbId}:
|
|
get:
|
|
summary: Get movie ratings
|
|
description: Returns IMDB and Rotten Tomatoes ratings for a movie
|
|
tags:
|
|
- other
|
|
parameters:
|
|
- in: path
|
|
name: tmdbId
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
description: TMDB movie ID
|
|
- in: query
|
|
name: title
|
|
schema:
|
|
type: string
|
|
description: Movie title (required for RT rating lookup)
|
|
- in: query
|
|
name: year
|
|
schema:
|
|
type: integer
|
|
description: Movie release year (required for RT rating lookup)
|
|
- in: query
|
|
name: imdbId
|
|
schema:
|
|
type: string
|
|
description: IMDB ID (e.g. tt1234567) for IMDB rating lookup
|
|
responses:
|
|
'200':
|
|
description: Movie ratings
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
imdb:
|
|
type: object
|
|
nullable: true
|
|
properties:
|
|
imdbId:
|
|
type: string
|
|
example: tt1234567
|
|
rating:
|
|
type: number
|
|
nullable: true
|
|
example: 8.5
|
|
votes:
|
|
type: number
|
|
nullable: true
|
|
example: 123456
|
|
rt:
|
|
type: object
|
|
nullable: true
|
|
properties:
|
|
title:
|
|
type: string
|
|
year:
|
|
type: number
|
|
criticsRating:
|
|
type: string
|
|
enum: [Certified Fresh, Fresh, Rotten]
|
|
criticsScore:
|
|
type: number
|
|
audienceRating:
|
|
type: string
|
|
enum: [Upright, Spilled]
|
|
audienceScore:
|
|
type: number
|
|
url:
|
|
type: string
|
|
'400':
|
|
description: Invalid request
|
|
'500':
|
|
description: Failed to fetch ratings
|
|
/ratings/tv/{tmdbId}:
|
|
get:
|
|
summary: Get TV show ratings
|
|
description: Returns IMDB and Rotten Tomatoes ratings for a TV show
|
|
tags:
|
|
- other
|
|
parameters:
|
|
- in: path
|
|
name: tmdbId
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
description: TMDB TV show ID
|
|
- in: query
|
|
name: title
|
|
schema:
|
|
type: string
|
|
description: TV show title (required for RT rating lookup)
|
|
- in: query
|
|
name: year
|
|
schema:
|
|
type: integer
|
|
description: First air date year (optional for RT rating lookup)
|
|
- in: query
|
|
name: imdbId
|
|
schema:
|
|
type: string
|
|
description: IMDB ID (e.g. tt1234567) for IMDB rating lookup
|
|
responses:
|
|
'200':
|
|
description: TV show ratings
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
imdb:
|
|
type: object
|
|
nullable: true
|
|
properties:
|
|
imdbId:
|
|
type: string
|
|
example: tt1234567
|
|
rating:
|
|
type: number
|
|
nullable: true
|
|
example: 8.5
|
|
votes:
|
|
type: number
|
|
nullable: true
|
|
example: 123456
|
|
rt:
|
|
type: object
|
|
nullable: true
|
|
properties:
|
|
title:
|
|
type: string
|
|
year:
|
|
type: number
|
|
criticsRating:
|
|
type: string
|
|
enum: [Fresh, Rotten]
|
|
criticsScore:
|
|
type: number
|
|
audienceRating:
|
|
type: string
|
|
enum: [Upright, Spilled]
|
|
audienceScore:
|
|
type: number
|
|
url:
|
|
type: string
|
|
'400':
|
|
description: Invalid request
|
|
'500':
|
|
description: Failed to fetch ratings
|
|
/reorder:
|
|
post:
|
|
summary: True unified reordering for mixed collection lists
|
|
description: Reorders mixed collection lists in a single operation, eliminating race conditions and multiple API calls.
|
|
tags:
|
|
- collections
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
libraryId:
|
|
type: string
|
|
description: 'Plex library ID where reordering occurs'
|
|
example: '1'
|
|
mixedItems:
|
|
type: array
|
|
description: 'Array of mixed collection items in their new order'
|
|
items:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
description: 'Item ID'
|
|
configType:
|
|
type: string
|
|
enum: ['collection', 'hub', 'preExisting']
|
|
description: 'Type of collection item'
|
|
position:
|
|
type: number
|
|
description: 'Position in the mixed list'
|
|
additionalProperties: true
|
|
required:
|
|
- id
|
|
- configType
|
|
- position
|
|
context:
|
|
type: string
|
|
enum: ['home', 'recommended', 'library']
|
|
description: 'Context determining which sortOrder field to update'
|
|
example: 'home'
|
|
required:
|
|
- libraryId
|
|
- mixedItems
|
|
- context
|
|
responses:
|
|
'200':
|
|
description: Items reordered successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
example: true
|
|
message:
|
|
type: string
|
|
example: 'Successfully reordered 3 collections'
|
|
updatedItems:
|
|
type: array
|
|
description: 'Items with updated sort orders'
|
|
items:
|
|
oneOf:
|
|
- $ref: '#/components/schemas/CollectionConfig'
|
|
- $ref: '#/components/schemas/PlexHubConfig'
|
|
- $ref: '#/components/schemas/PreExistingCollectionConfig'
|
|
'400':
|
|
description: Invalid request parameters
|
|
'500':
|
|
description: Failed to reorder items
|
|
/settings/main:
|
|
get:
|
|
summary: Get main settings
|
|
description: Retrieves all main settings in a JSON object.
|
|
tags:
|
|
- settings-general
|
|
responses:
|
|
'200':
|
|
description: OK
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/MainSettings'
|
|
post:
|
|
summary: Update main settings
|
|
description: Updates main settings with the provided values.
|
|
tags:
|
|
- settings-general
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/MainSettings'
|
|
responses:
|
|
'200':
|
|
description: 'Values were sucessfully updated'
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/MainSettings'
|
|
/settings/main/regenerate:
|
|
post:
|
|
summary: Get main settings with newly-generated API key
|
|
description: Returns main settings in a JSON object, using the new API key.
|
|
tags:
|
|
- settings-general
|
|
responses:
|
|
'200':
|
|
description: OK
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/MainSettings'
|
|
/settings/reset:
|
|
post:
|
|
summary: Reset all Agregarr collections
|
|
description: Removes all Agregarr collections from Plex and clears all user labels. This action cannot be undone.
|
|
tags:
|
|
- settings
|
|
responses:
|
|
'200':
|
|
description: Reset completed successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
example: true
|
|
'500':
|
|
description: Reset failed
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: Failed to reset collections
|
|
/settings/plex:
|
|
get:
|
|
summary: Get Plex settings
|
|
description: Retrieves current Plex settings.
|
|
tags:
|
|
- settings-plex
|
|
responses:
|
|
'200':
|
|
description: OK
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/PlexSettings'
|
|
post:
|
|
summary: Update Plex settings
|
|
description: Updates Plex settings with the provided values.
|
|
tags:
|
|
- settings-plex
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/PlexSettings'
|
|
responses:
|
|
'200':
|
|
description: 'Values were successfully updated'
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/PlexSettings'
|
|
/settings/plex/libraries:
|
|
get:
|
|
summary: Get Plex libraries directly from Plex server
|
|
description: Fetches all available libraries directly from the connected Plex server.
|
|
tags:
|
|
- settings-plex
|
|
responses:
|
|
'200':
|
|
description: Plex libraries retrieved successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
description: Library ID from Plex
|
|
example: '1'
|
|
name:
|
|
type: string
|
|
description: Library name
|
|
example: 'Movies'
|
|
type:
|
|
type: string
|
|
enum: [movie, show]
|
|
description: Library media type
|
|
example: 'movie'
|
|
enabled:
|
|
type: boolean
|
|
description: Always true for direct Plex libraries
|
|
example: true
|
|
'400':
|
|
description: No admin Plex token found
|
|
'500':
|
|
description: Failed to fetch Plex libraries
|
|
/settings/plex/library:
|
|
get:
|
|
summary: Get Plex libraries
|
|
description: Returns a list of Plex libraries in a JSON array.
|
|
tags:
|
|
- settings-plex
|
|
parameters:
|
|
- in: query
|
|
name: sync
|
|
description: Syncs the current libraries with the current Plex server
|
|
schema:
|
|
type: string
|
|
nullable: true
|
|
responses:
|
|
'200':
|
|
description: 'Plex libraries returned'
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/PlexLibrary'
|
|
/settings/plex/sync:
|
|
get:
|
|
summary: Get status of full Plex library scan
|
|
description: Returns scan progress in a JSON array.
|
|
tags:
|
|
- settings-plex
|
|
responses:
|
|
'200':
|
|
description: Status of Plex scan
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
running:
|
|
type: boolean
|
|
example: false
|
|
progress:
|
|
type: number
|
|
example: 0
|
|
total:
|
|
type: number
|
|
example: 100
|
|
currentLibrary:
|
|
$ref: '#/components/schemas/PlexLibrary'
|
|
libraries:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/PlexLibrary'
|
|
post:
|
|
summary: Start full Plex library scan
|
|
description: Runs a full Plex library scan and returns the progress in a JSON array.
|
|
tags:
|
|
- settings-plex
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
cancel:
|
|
type: boolean
|
|
example: false
|
|
start:
|
|
type: boolean
|
|
example: false
|
|
responses:
|
|
'200':
|
|
description: Status of Plex scan
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
running:
|
|
type: boolean
|
|
example: false
|
|
progress:
|
|
type: number
|
|
example: 0
|
|
total:
|
|
type: number
|
|
example: 100
|
|
currentLibrary:
|
|
$ref: '#/components/schemas/PlexLibrary'
|
|
libraries:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/PlexLibrary'
|
|
/settings/plex/devices/servers:
|
|
get:
|
|
summary: Gets the user's available Plex servers
|
|
description: Returns a list of available Plex servers and their connectivity state
|
|
tags:
|
|
- settings-plex
|
|
responses:
|
|
'200':
|
|
description: OK
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/PlexDevice'
|
|
/settings/plex/users:
|
|
get:
|
|
summary: Get Plex users
|
|
description: |
|
|
Returns a list of Plex users in a JSON array.
|
|
|
|
Requires the `MANAGE_USERS` permission.
|
|
tags:
|
|
- settings-plex
|
|
- users
|
|
responses:
|
|
'200':
|
|
description: Plex users
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
title:
|
|
type: string
|
|
username:
|
|
type: string
|
|
email:
|
|
type: string
|
|
thumb:
|
|
type: string
|
|
/settings/collections/poster:
|
|
post:
|
|
summary: Upload collection poster image
|
|
description: |
|
|
Uploads a custom poster image for collections. The image will be processed, optimized, and stored securely.
|
|
|
|
**Important: Sync-Based Behavior**
|
|
- Posters are only validated and stored when uploaded
|
|
- Posters are applied to Plex collections during the next collection sync run
|
|
- Changes are not immediately visible in Plex until sync occurs
|
|
|
|
**Security Features:**
|
|
- Admin-only access required
|
|
- File type validation (JPEG, PNG, WebP only)
|
|
- File size limit (10MB maximum)
|
|
- Automatic image processing and optimization
|
|
- Secure filename generation using UUIDs
|
|
|
|
**Processing:**
|
|
- Images are automatically resized to 1000x1500 pixels (2:3 aspect ratio)
|
|
- All images are converted to JPEG format for consistency
|
|
- Quality optimization applied (85% quality)
|
|
tags:
|
|
- settings-general
|
|
security:
|
|
- cookieAuth: []
|
|
- apiKeyAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
multipart/form-data:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
poster:
|
|
type: string
|
|
format: binary
|
|
description: The poster image file (JPEG, PNG, or WebP, max 10MB)
|
|
required:
|
|
- poster
|
|
responses:
|
|
'200':
|
|
description: Poster uploaded successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
filename:
|
|
type: string
|
|
description: The generated filename for the uploaded poster
|
|
example: 'f47ac10b-58cc-4372-a567-0e02b2c3d479.jpg'
|
|
url:
|
|
type: string
|
|
description: The URL to access the uploaded poster
|
|
example: '/api/v1/settings/collections/poster/f47ac10b-58cc-4372-a567-0e02b2c3d479.jpg'
|
|
'400':
|
|
description: Bad request - Invalid file or upload error
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
enum:
|
|
- 'No file uploaded'
|
|
- 'Invalid file type. Only JPEG, PNG, and WebP are allowed.'
|
|
- 'File extension does not match file type.'
|
|
- 'File size too large. Maximum size: 10MB'
|
|
- 'Invalid image format detected'
|
|
- 'Image dimensions too large'
|
|
- 'Failed to process poster'
|
|
example: 'Invalid file type. Only JPEG, PNG, and WebP are allowed.'
|
|
'403':
|
|
description: Insufficient permissions
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Insufficient permissions'
|
|
'500':
|
|
description: Internal server error
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Internal server error'
|
|
/settings/collections/poster/{filename}:
|
|
get:
|
|
summary: Serve collection poster image
|
|
description: |
|
|
Serves a collection poster image by filename. Images are cached for optimal performance.
|
|
|
|
**Security Features:**
|
|
- Filename validation to prevent path traversal attacks
|
|
- UUID-based filenames make guessing difficult
|
|
- No authentication required (images are already admin-uploaded)
|
|
|
|
**Caching:**
|
|
- Images are cached for 1 year for optimal performance
|
|
- Content-Type is always image/jpeg (all images are converted)
|
|
tags:
|
|
- settings-general
|
|
parameters:
|
|
- name: filename
|
|
in: path
|
|
required: true
|
|
description: The filename of the poster image (UUID format with extension)
|
|
schema:
|
|
type: string
|
|
pattern: '^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}\.(jpg|jpeg|png|webp)$'
|
|
example: 'f47ac10b-58cc-4372-a567-0e02b2c3d479.jpg'
|
|
responses:
|
|
'200':
|
|
description: Poster image served successfully
|
|
content:
|
|
image/jpeg:
|
|
schema:
|
|
type: string
|
|
format: binary
|
|
headers:
|
|
Cache-Control:
|
|
description: Caching directive
|
|
schema:
|
|
type: string
|
|
example: 'public, max-age=31536000'
|
|
Content-Type:
|
|
description: Content type header
|
|
schema:
|
|
type: string
|
|
example: 'image/jpeg'
|
|
'400':
|
|
description: Invalid filename format
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Invalid filename'
|
|
'404':
|
|
description: Poster not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Poster not found'
|
|
'500':
|
|
description: Internal server error
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Failed to serve poster'
|
|
delete:
|
|
summary: Delete collection poster image
|
|
description: |
|
|
Deletes a collection poster image by filename. Requires admin permissions.
|
|
|
|
**Important: Sync-Based Behavior**
|
|
- Poster file is immediately deleted from storage
|
|
- Collections using this poster will revert to default during the next collection sync run
|
|
- Changes are not immediately visible in Plex until sync occurs
|
|
|
|
**Security Features:**
|
|
- Admin-only access required
|
|
- Filename validation to prevent path traversal attacks
|
|
- Safe deletion with error handling
|
|
tags:
|
|
- settings-general
|
|
security:
|
|
- cookieAuth: []
|
|
- apiKeyAuth: []
|
|
parameters:
|
|
- name: filename
|
|
in: path
|
|
required: true
|
|
description: The filename of the poster image to delete
|
|
schema:
|
|
type: string
|
|
pattern: '^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}\.(jpg|jpeg|png|webp)$'
|
|
example: 'f47ac10b-58cc-4372-a567-0e02b2c3d479.jpg'
|
|
responses:
|
|
'200':
|
|
description: Poster deleted successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: 'Poster deleted successfully'
|
|
'400':
|
|
description: Invalid filename format
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Invalid filename'
|
|
'403':
|
|
description: Insufficient permissions
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Insufficient permissions'
|
|
'404':
|
|
description: Poster not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Poster not found'
|
|
'500':
|
|
description: Internal server error
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Internal server error'
|
|
/settings/tautulli:
|
|
get:
|
|
summary: Get Tautulli settings
|
|
description: Retrieves current Tautulli settings.
|
|
tags:
|
|
- settings-integrations
|
|
responses:
|
|
'200':
|
|
description: OK
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/TautulliSettings'
|
|
post:
|
|
summary: Update Tautulli settings
|
|
description: Updates Tautulli settings with the provided values.
|
|
tags:
|
|
- settings-integrations
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/TautulliSettings'
|
|
responses:
|
|
'200':
|
|
description: 'Values were successfully updated'
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/TautulliSettings'
|
|
/settings/tautulli/test:
|
|
post:
|
|
summary: Test Tautulli connection
|
|
description: Tests connection to a Tautulli instance.
|
|
tags:
|
|
- settings-integrations
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
hostname:
|
|
type: string
|
|
example: 'tautulli.example.com'
|
|
port:
|
|
type: number
|
|
example: 8181
|
|
apiKey:
|
|
type: string
|
|
example: 'your-api-key-here'
|
|
useSsl:
|
|
type: boolean
|
|
example: false
|
|
urlBase:
|
|
type: string
|
|
example: '/tautulli'
|
|
required:
|
|
- hostname
|
|
- apiKey
|
|
responses:
|
|
'200':
|
|
description: 'Connection test successful'
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
example: true
|
|
'400':
|
|
description: 'Invalid API key - Authentication failed (Tautulli returns 400 for bad API keys)'
|
|
'401':
|
|
description: 'Invalid API key - Authentication failed'
|
|
'403':
|
|
description: 'API key lacks required permissions'
|
|
'404':
|
|
description: 'Tautulli API not found at specified URL'
|
|
'500':
|
|
description: 'Connection test failed - Server error or network issue'
|
|
/settings/maintainerr:
|
|
get:
|
|
summary: Get Maintainerr settings
|
|
description: Retrieves current Maintainerr settings.
|
|
tags:
|
|
- settings-integrations
|
|
responses:
|
|
'200':
|
|
description: OK
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/MaintainerrSettings'
|
|
post:
|
|
summary: Update Maintainerr settings
|
|
description: Updates Maintainerr settings with the provided values.
|
|
tags:
|
|
- settings-integrations
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/MaintainerrSettings'
|
|
responses:
|
|
'200':
|
|
description: 'Values were successfully updated'
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/MaintainerrSettings'
|
|
/settings/maintainerr/test:
|
|
post:
|
|
summary: Test Maintainerr connection
|
|
description: Tests connection to a Maintainerr instance.
|
|
tags:
|
|
- settings-integrations
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
hostname:
|
|
type: string
|
|
example: 'maintainerr.example.com'
|
|
port:
|
|
type: number
|
|
example: 6246
|
|
apiKey:
|
|
type: string
|
|
example: 'your-api-key-here'
|
|
useSsl:
|
|
type: boolean
|
|
example: false
|
|
urlBase:
|
|
type: string
|
|
example: ''
|
|
required:
|
|
- hostname
|
|
- apiKey
|
|
responses:
|
|
'200':
|
|
description: 'Connection test successful'
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
example: true
|
|
'400':
|
|
description: 'Invalid API key - Authentication failed'
|
|
'401':
|
|
description: 'Invalid API key - Authentication failed'
|
|
'403':
|
|
description: 'API key lacks required permissions'
|
|
'404':
|
|
description: 'Maintainerr API not found at specified URL'
|
|
'500':
|
|
description: 'Connection test failed - Server error or network issue'
|
|
/settings/trakt:
|
|
get:
|
|
summary: Get Trakt settings
|
|
description: Retrieves current Trakt settings.
|
|
tags:
|
|
- settings-integrations
|
|
responses:
|
|
'200':
|
|
description: OK
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/TraktSettings'
|
|
post:
|
|
summary: Update Trakt settings
|
|
description: Updates Trakt settings with the provided values.
|
|
tags:
|
|
- settings-integrations
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/TraktSettings'
|
|
responses:
|
|
'200':
|
|
description: 'Values were successfully updated'
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/TraktSettings'
|
|
/settings/trakt/test:
|
|
post:
|
|
summary: Test Trakt connection
|
|
description: Tests connection to Trakt API. Supports basic mode (clientId only) or OAuth mode (clientId + clientSecret + accessToken).
|
|
tags:
|
|
- settings-integrations
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
clientId:
|
|
type: string
|
|
description: Trakt client ID (required for all modes)
|
|
clientSecret:
|
|
type: string
|
|
description: Trakt client secret (optional, required for OAuth mode)
|
|
accessToken:
|
|
type: string
|
|
description: Trakt access token (optional, required for OAuth mode)
|
|
refreshToken:
|
|
type: string
|
|
description: Trakt refresh token (optional)
|
|
required:
|
|
- clientId
|
|
responses:
|
|
'200':
|
|
description: 'Connection test successful'
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
example: true
|
|
'400':
|
|
description: 'Missing required parameters'
|
|
'500':
|
|
description: 'Connection test failed'
|
|
/settings/trakt/oauth/start:
|
|
get:
|
|
summary: Start Trakt OAuth flow
|
|
description: Returns the authorization URL to redirect the user to Trakt for OAuth.
|
|
tags:
|
|
- settings-integrations
|
|
responses:
|
|
'200':
|
|
description: 'Authorization URL generated'
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
url:
|
|
type: string
|
|
description: 'Trakt OAuth authorization URL'
|
|
state:
|
|
type: string
|
|
description: 'Opaque state value for CSRF protection'
|
|
'400':
|
|
description: 'Client ID/Secret missing or application URL not configured'
|
|
'500':
|
|
description: 'Failed to create authorization URL'
|
|
/settings/trakt/oauth/exchange:
|
|
post:
|
|
summary: Exchange Trakt authorization code for tokens
|
|
description: Exchanges the provided Trakt authorization code for access and refresh tokens.
|
|
tags:
|
|
- settings-integrations
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
code:
|
|
type: string
|
|
description: Authorization code returned by Trakt
|
|
clientId:
|
|
type: string
|
|
description: Optional client ID override
|
|
clientSecret:
|
|
type: string
|
|
description: Optional client secret override
|
|
required:
|
|
- code
|
|
responses:
|
|
'200':
|
|
description: 'Tokens exchanged successfully'
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
example: true
|
|
accessToken:
|
|
type: string
|
|
refreshToken:
|
|
type: string
|
|
tokenExpiresAt:
|
|
type: integer
|
|
description: Expiration timestamp (ms since epoch)
|
|
'400':
|
|
description: 'Missing or invalid parameters'
|
|
'500':
|
|
description: 'Failed to exchange authorization code'
|
|
/trakt/oauth/exchange:
|
|
post:
|
|
summary: Exchange Trakt authorization code (public endpoint)
|
|
description: Public duplicate endpoint to exchange a Trakt authorization code for tokens.
|
|
tags:
|
|
- settings-integrations
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
code:
|
|
type: string
|
|
description: Authorization code returned by Trakt
|
|
clientId:
|
|
type: string
|
|
description: Optional client ID override
|
|
clientSecret:
|
|
type: string
|
|
description: Optional client secret override
|
|
required:
|
|
- code
|
|
responses:
|
|
'200':
|
|
description: 'Tokens exchanged successfully'
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
example: true
|
|
accessToken:
|
|
type: string
|
|
refreshToken:
|
|
type: string
|
|
tokenExpiresAt:
|
|
type: integer
|
|
description: Expiration timestamp (ms since epoch)
|
|
'400':
|
|
description: 'Missing or invalid parameters'
|
|
'500':
|
|
description: 'Failed to exchange authorization code'
|
|
/settings/mdblist:
|
|
get:
|
|
summary: Get MDBList settings
|
|
description: Retrieves current MDBList settings.
|
|
tags:
|
|
- settings-integrations
|
|
responses:
|
|
'200':
|
|
description: OK
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/MDBListSettings'
|
|
post:
|
|
summary: Update MDBList settings
|
|
description: Updates MDBList settings with the provided values.
|
|
tags:
|
|
- settings-integrations
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/MDBListSettings'
|
|
responses:
|
|
'200':
|
|
description: 'Values were successfully updated'
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/MDBListSettings'
|
|
/settings/mdblist/test:
|
|
post:
|
|
summary: Test MDBList connection
|
|
description: Tests connection to MDBList API with the provided API key.
|
|
tags:
|
|
- settings-integrations
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
apiKey:
|
|
type: string
|
|
description: MDBList API key
|
|
required:
|
|
- apiKey
|
|
responses:
|
|
'200':
|
|
description: 'Connection test successful'
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
example: true
|
|
'400':
|
|
description: 'Missing required parameters'
|
|
'500':
|
|
description: 'Connection test failed'
|
|
/settings/myanimelist:
|
|
get:
|
|
summary: Get MyAnimeList settings
|
|
description: Retrieves current MyAnimeList settings.
|
|
tags:
|
|
- settings-integrations
|
|
responses:
|
|
'200':
|
|
description: OK
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/MyAnimeListSettings'
|
|
post:
|
|
summary: Update MyAnimeList settings
|
|
description: Updates MyAnimeList settings with the provided values.
|
|
tags:
|
|
- settings-integrations
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/MyAnimeListSettings'
|
|
responses:
|
|
'200':
|
|
description: 'Values were successfully updated'
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/MyAnimeListSettings'
|
|
/settings/myanimelist/test:
|
|
post:
|
|
summary: Test MyAnimeList connection
|
|
description: Tests connection to MyAnimeList API with the provided API key.
|
|
tags:
|
|
- settings-integrations
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
apiKey:
|
|
type: string
|
|
description: MyAnimeList API key
|
|
required:
|
|
- apiKey
|
|
responses:
|
|
'200':
|
|
description: 'Connection test successful'
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
example: true
|
|
'400':
|
|
description: 'Missing required parameters'
|
|
'500':
|
|
description: 'Connection test failed'
|
|
/settings/overseerr:
|
|
get:
|
|
summary: Get Overseerr settings
|
|
description: Retrieves current Overseerr connection settings for external instances.
|
|
tags:
|
|
- settings-integrations
|
|
responses:
|
|
'200':
|
|
description: OK
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/OverseerrSettings'
|
|
post:
|
|
summary: Update Overseerr settings
|
|
description: Updates Overseerr connection settings and tests the connection.
|
|
tags:
|
|
- settings-integrations
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/OverseerrSettings'
|
|
responses:
|
|
'200':
|
|
description: 'Values were successfully updated'
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/OverseerrSettings'
|
|
'500':
|
|
description: 'Connection test failed'
|
|
delete:
|
|
summary: Delete Overseerr settings
|
|
description: Clears all Overseerr connection settings.
|
|
tags:
|
|
- settings-integrations
|
|
responses:
|
|
'200':
|
|
description: 'Settings were successfully cleared'
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/OverseerrSettings'
|
|
/overseerr/test:
|
|
post:
|
|
summary: Test Overseerr connection
|
|
description: Tests connection to an external Overseerr instance.
|
|
tags:
|
|
- other
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
hostname:
|
|
type: string
|
|
example: 'overseerr.example.com'
|
|
port:
|
|
type: number
|
|
example: 5055
|
|
apiKey:
|
|
type: string
|
|
example: 'your-api-key-here'
|
|
useSsl:
|
|
type: boolean
|
|
example: false
|
|
urlBase:
|
|
type: string
|
|
nullable: true
|
|
example: '/overseerr'
|
|
required:
|
|
- hostname
|
|
- port
|
|
- apiKey
|
|
responses:
|
|
'200':
|
|
description: 'Connection test successful with all server options'
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
example: true
|
|
templateDataSuccess:
|
|
type: boolean
|
|
example: true
|
|
description: 'Whether template variables were successfully fetched'
|
|
templateDataMessage:
|
|
type: string
|
|
example: 'Template variables updated: Overseerr (https://overseerr.example.com)'
|
|
description: 'Message about template variable fetch result'
|
|
servers:
|
|
type: object
|
|
properties:
|
|
radarr:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: number
|
|
example: 0
|
|
name:
|
|
type: string
|
|
example: 'Radarr'
|
|
hostname:
|
|
type: string
|
|
example: '192.168.0.236'
|
|
port:
|
|
type: number
|
|
example: 7878
|
|
is4k:
|
|
type: boolean
|
|
example: false
|
|
isDefault:
|
|
type: boolean
|
|
example: true
|
|
sonarr:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: number
|
|
example: 0
|
|
name:
|
|
type: string
|
|
example: 'Sonarr'
|
|
hostname:
|
|
type: string
|
|
example: '192.168.0.236'
|
|
port:
|
|
type: number
|
|
example: 8989
|
|
is4k:
|
|
type: boolean
|
|
example: false
|
|
isDefault:
|
|
type: boolean
|
|
example: true
|
|
radarrServerOptions:
|
|
type: object
|
|
description: 'Quality profiles and root folders for all Radarr servers, keyed by server ID'
|
|
additionalProperties:
|
|
type: object
|
|
properties:
|
|
profiles:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: number
|
|
example: 8
|
|
name:
|
|
type: string
|
|
example: '1080p Quality'
|
|
rootFolders:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: number
|
|
example: 4
|
|
path:
|
|
type: string
|
|
example: '/data/media/movies'
|
|
sonarrServerOptions:
|
|
type: object
|
|
description: 'Quality profiles and root folders for all Sonarr servers, keyed by server ID'
|
|
additionalProperties:
|
|
type: object
|
|
properties:
|
|
profiles:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: number
|
|
example: 14
|
|
name:
|
|
type: string
|
|
example: '1080p Quality'
|
|
rootFolders:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: number
|
|
example: 3
|
|
path:
|
|
type: string
|
|
example: '/data/media/series'
|
|
'400':
|
|
description: 'Missing required parameters'
|
|
'401':
|
|
description: 'Invalid API key - Authentication failed'
|
|
'403':
|
|
description: 'API key lacks required permissions'
|
|
'404':
|
|
description: 'Overseerr API not found at specified URL'
|
|
'500':
|
|
description: 'Connection test failed - Server error or network issue'
|
|
/settings/serviceuser:
|
|
get:
|
|
summary: Get service user settings
|
|
description: Returns service user creation settings.
|
|
tags:
|
|
- settings-general
|
|
responses:
|
|
'200':
|
|
description: 'Service user settings returned successfully'
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ServiceUserSettings'
|
|
post:
|
|
summary: Update service user settings
|
|
description: Updates service user creation settings.
|
|
tags:
|
|
- settings-general
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ServiceUserSettings'
|
|
responses:
|
|
'200':
|
|
description: 'Service user settings updated successfully'
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ServiceUserSettings'
|
|
'500':
|
|
description: 'Settings update failed'
|
|
/settings/radarr:
|
|
get:
|
|
summary: Get Radarr settings
|
|
description: Returns all Radarr settings in a JSON array.
|
|
tags:
|
|
- settings-services
|
|
responses:
|
|
'200':
|
|
description: 'Values were returned'
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/RadarrSettings'
|
|
post:
|
|
summary: Create Radarr instance
|
|
description: Creates a new Radarr instance from the request body.
|
|
tags:
|
|
- settings-services
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/RadarrSettings'
|
|
responses:
|
|
'201':
|
|
description: 'New Radarr instance created'
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/RadarrSettings'
|
|
/settings/radarr/test:
|
|
post:
|
|
summary: Test Radarr configuration
|
|
description: Tests if the Radarr configuration is valid. Returns profiles and root folders on success.
|
|
tags:
|
|
- settings-services
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
hostname:
|
|
type: string
|
|
example: '127.0.0.1'
|
|
port:
|
|
type: number
|
|
example: 7878
|
|
apiKey:
|
|
type: string
|
|
example: yourapikey
|
|
useSsl:
|
|
type: boolean
|
|
example: false
|
|
baseUrl:
|
|
type: string
|
|
required:
|
|
- hostname
|
|
- apiKey
|
|
responses:
|
|
'200':
|
|
description: Succesfully connected to Radarr instance
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
profiles:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/ServiceProfile'
|
|
/settings/radarr/alltags:
|
|
get:
|
|
summary: Get all Radarr tags from all instances
|
|
description: Returns a deduplicated list of tags from all configured Radarr instances.
|
|
tags:
|
|
- settings-services
|
|
responses:
|
|
'200':
|
|
description: List of tags from all Radarr instances
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/ServarrTag'
|
|
/settings/radarr/{radarrId}:
|
|
put:
|
|
summary: Update Radarr instance
|
|
description: Updates an existing Radarr instance with the provided values.
|
|
tags:
|
|
- settings-services
|
|
parameters:
|
|
- in: path
|
|
name: radarrId
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
description: Radarr instance ID
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/RadarrSettings'
|
|
responses:
|
|
'200':
|
|
description: 'Radarr instance updated'
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/RadarrSettings'
|
|
delete:
|
|
summary: Delete Radarr instance
|
|
description: Deletes an existing Radarr instance based on the radarrId parameter.
|
|
tags:
|
|
- settings-services
|
|
parameters:
|
|
- in: path
|
|
name: radarrId
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
description: Radarr instance ID
|
|
responses:
|
|
'200':
|
|
description: 'Radarr instance updated'
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/RadarrSettings'
|
|
/settings/radarr/{radarrId}/profiles:
|
|
get:
|
|
summary: Get available Radarr profiles
|
|
description: Returns a list of profiles available on the Radarr server instance in a JSON array.
|
|
tags:
|
|
- settings-services
|
|
parameters:
|
|
- in: path
|
|
name: radarrId
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
description: Radarr instance ID
|
|
responses:
|
|
'200':
|
|
description: Returned list of profiles
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/ServiceProfile'
|
|
/settings/radarr/{radarrId}/rootfolders:
|
|
get:
|
|
summary: Get available Radarr root folders
|
|
description: Returns a list of root folders available on the Radarr server instance in a JSON array.
|
|
tags:
|
|
- settings-services
|
|
parameters:
|
|
- in: path
|
|
name: radarrId
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
description: Radarr instance ID
|
|
responses:
|
|
'200':
|
|
description: Returned list of root folders
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: number
|
|
path:
|
|
type: string
|
|
/settings/radarr/{radarrId}/tags:
|
|
get:
|
|
summary: Get available Radarr tags
|
|
description: Returns a list of tags available on the Radarr server instance in a JSON array.
|
|
tags:
|
|
- settings-services
|
|
parameters:
|
|
- in: path
|
|
name: radarrId
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
description: Radarr instance ID
|
|
responses:
|
|
'200':
|
|
description: Returned list of tags
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/ServarrTag'
|
|
post:
|
|
summary: Create a new Radarr tag
|
|
description: Creates a new tag in the Radarr instance and returns the created tag with its ID.
|
|
tags:
|
|
- settings-services
|
|
parameters:
|
|
- in: path
|
|
name: radarrId
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
description: Radarr instance ID
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- label
|
|
properties:
|
|
label:
|
|
type: string
|
|
description: Tag label/name
|
|
example: agregarr-watchlist
|
|
responses:
|
|
'201':
|
|
description: Tag created successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ServarrTag'
|
|
'404':
|
|
description: Radarr instance not found
|
|
'500':
|
|
description: Failed to create tag
|
|
/settings/sonarr:
|
|
get:
|
|
summary: Get Sonarr settings
|
|
description: Returns all Sonarr settings in a JSON array.
|
|
tags:
|
|
- settings-services
|
|
responses:
|
|
'200':
|
|
description: 'Values were returned'
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/SonarrSettings'
|
|
post:
|
|
summary: Create Sonarr instance
|
|
description: Creates a new Sonarr instance from the request body.
|
|
tags:
|
|
- settings-services
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SonarrSettings'
|
|
responses:
|
|
'201':
|
|
description: 'New Sonarr instance created'
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SonarrSettings'
|
|
/settings/sonarr/test:
|
|
post:
|
|
summary: Test Sonarr configuration
|
|
description: Tests if the Sonarr configuration is valid. Returns profiles and root folders on success.
|
|
tags:
|
|
- settings-services
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
hostname:
|
|
type: string
|
|
example: '127.0.0.1'
|
|
port:
|
|
type: number
|
|
example: 8989
|
|
apiKey:
|
|
type: string
|
|
example: yourapikey
|
|
useSsl:
|
|
type: boolean
|
|
example: false
|
|
baseUrl:
|
|
type: string
|
|
required:
|
|
- hostname
|
|
- apiKey
|
|
responses:
|
|
'200':
|
|
description: Succesfully connected to Sonarr instance
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
profiles:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/ServiceProfile'
|
|
/settings/sonarr/alltags:
|
|
get:
|
|
summary: Get all Sonarr tags from all instances
|
|
description: Returns a deduplicated list of tags from all configured Sonarr instances.
|
|
tags:
|
|
- settings-services
|
|
responses:
|
|
'200':
|
|
description: List of tags from all Sonarr instances
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/ServarrTag'
|
|
/settings/sonarr/{sonarrId}:
|
|
put:
|
|
summary: Update Sonarr instance
|
|
description: Updates an existing Sonarr instance with the provided values.
|
|
tags:
|
|
- settings-services
|
|
parameters:
|
|
- in: path
|
|
name: sonarrId
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
description: Sonarr instance ID
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SonarrSettings'
|
|
responses:
|
|
'200':
|
|
description: 'Sonarr instance updated'
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SonarrSettings'
|
|
delete:
|
|
summary: Delete Sonarr instance
|
|
description: Deletes an existing Sonarr instance based on the sonarrId parameter.
|
|
tags:
|
|
- settings-services
|
|
parameters:
|
|
- in: path
|
|
name: sonarrId
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
description: Sonarr instance ID
|
|
responses:
|
|
'200':
|
|
description: 'Sonarr instance updated'
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SonarrSettings'
|
|
/settings/sonarr/{sonarrId}/profiles:
|
|
get:
|
|
summary: Get available Sonarr profiles
|
|
description: Returns a list of profiles available on the Sonarr server instance in a JSON array.
|
|
tags:
|
|
- settings-services
|
|
parameters:
|
|
- in: path
|
|
name: sonarrId
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
description: Sonarr instance ID
|
|
responses:
|
|
'200':
|
|
description: Returned list of profiles
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/ServiceProfile'
|
|
/settings/sonarr/{sonarrId}/rootfolders:
|
|
get:
|
|
summary: Get available Sonarr root folders
|
|
description: Returns a list of root folders available on the Sonarr server instance in a JSON array.
|
|
tags:
|
|
- settings-services
|
|
parameters:
|
|
- in: path
|
|
name: sonarrId
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
description: Sonarr instance ID
|
|
responses:
|
|
'200':
|
|
description: Returned list of root folders
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: number
|
|
path:
|
|
type: string
|
|
/settings/sonarr/{sonarrId}/tags:
|
|
get:
|
|
summary: Get available Sonarr tags
|
|
description: Returns a list of tags available on the Sonarr server instance in a JSON array.
|
|
tags:
|
|
- settings-services
|
|
parameters:
|
|
- in: path
|
|
name: sonarrId
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
description: Sonarr instance ID
|
|
responses:
|
|
'200':
|
|
description: Returned list of tags
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/ServarrTag'
|
|
post:
|
|
summary: Create a new Sonarr tag
|
|
description: Creates a new tag in the Sonarr instance and returns the created tag with its ID.
|
|
tags:
|
|
- settings-services
|
|
parameters:
|
|
- in: path
|
|
name: sonarrId
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
description: Sonarr instance ID
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- label
|
|
properties:
|
|
label:
|
|
type: string
|
|
description: Tag label/name
|
|
example: agregarr-watchlist
|
|
responses:
|
|
'201':
|
|
description: Tag created successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ServarrTag'
|
|
'404':
|
|
description: Sonarr instance not found
|
|
'500':
|
|
description: Failed to create tag
|
|
/settings/watchlistsync:
|
|
get:
|
|
summary: Get watchlist sync settings
|
|
description: Returns the current Plex watchlist sync settings including enable flags and Radarr/Sonarr configurations.
|
|
tags:
|
|
- settings-services
|
|
responses:
|
|
'200':
|
|
description: Watchlist sync settings returned
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/WatchlistSyncSettings'
|
|
post:
|
|
summary: Update watchlist sync settings
|
|
description: Updates the Plex watchlist sync settings including enable flags and Radarr/Sonarr configurations.
|
|
tags:
|
|
- settings-services
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/WatchlistSyncSettings'
|
|
responses:
|
|
'200':
|
|
description: Watchlist sync settings updated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/WatchlistSyncSettings'
|
|
/settings/public:
|
|
get:
|
|
summary: Get public settings
|
|
security: []
|
|
description: Returns settings that are not protected or sensitive. Mainly used to determine if the application has been configured for the first time.
|
|
tags:
|
|
- settings-general
|
|
responses:
|
|
'200':
|
|
description: Public settings returned
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/PublicSettings'
|
|
/settings/initialize:
|
|
post:
|
|
summary: Initialize application
|
|
description: Sets the app as initialized, allowing the user to navigate to pages other than the setup page.
|
|
tags:
|
|
- settings-general
|
|
responses:
|
|
'200':
|
|
description: Public settings returned
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/PublicSettings'
|
|
/settings/jobs:
|
|
get:
|
|
summary: Get scheduled jobs
|
|
description: Returns list of all scheduled jobs and details about their next execution time in a JSON array.
|
|
tags:
|
|
- settings-system
|
|
responses:
|
|
'200':
|
|
description: Scheduled jobs returned
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/Job'
|
|
/settings/jobs/{jobId}/run:
|
|
post:
|
|
summary: Invoke a specific job
|
|
description: Invokes a specific job to run. Will return the new job status in JSON format.
|
|
tags:
|
|
- settings-system
|
|
parameters:
|
|
- in: path
|
|
name: jobId
|
|
required: true
|
|
description: The unique identifier of the job.
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Invoked job returned
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Job'
|
|
/settings/jobs/{jobId}/cancel:
|
|
post:
|
|
summary: Cancel a specific job
|
|
description: Cancels a specific job. Will return the new job status in JSON format.
|
|
tags:
|
|
- settings-system
|
|
parameters:
|
|
- in: path
|
|
name: jobId
|
|
required: true
|
|
description: The unique identifier of the job.
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Canceled job returned
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Job'
|
|
/settings/jobs/{jobId}/schedule:
|
|
post:
|
|
summary: Modify job schedule
|
|
description: Re-registers the job with the schedule specified. Will return the job in JSON format.
|
|
tags:
|
|
- settings-system
|
|
parameters:
|
|
- in: path
|
|
name: jobId
|
|
required: true
|
|
description: The unique identifier of the job.
|
|
schema:
|
|
type: string
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
schedule:
|
|
type: string
|
|
example: '0 */5 * * * *'
|
|
responses:
|
|
'200':
|
|
description: Rescheduled job
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Job'
|
|
/settings/cache:
|
|
get:
|
|
summary: Get a list of active caches
|
|
description: Retrieves a list of all active caches and their current stats.
|
|
tags:
|
|
- settings-system
|
|
responses:
|
|
'200':
|
|
description: Caches returned
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
imageCache:
|
|
type: object
|
|
properties:
|
|
tmdb:
|
|
type: object
|
|
properties:
|
|
size:
|
|
type: number
|
|
example: 123456
|
|
imageCount:
|
|
type: number
|
|
example: 123
|
|
apiCaches:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
example: cache-id
|
|
name:
|
|
type: string
|
|
example: cache name
|
|
stats:
|
|
type: object
|
|
properties:
|
|
hits:
|
|
type: number
|
|
misses:
|
|
type: number
|
|
keys:
|
|
type: number
|
|
ksize:
|
|
type: number
|
|
vsize:
|
|
type: number
|
|
/settings/cache/{cacheId}/flush:
|
|
post:
|
|
summary: Flush a specific cache
|
|
description: Flushes all data from the cache ID provided
|
|
tags:
|
|
- settings-system
|
|
parameters:
|
|
- in: path
|
|
name: cacheId
|
|
required: true
|
|
description: The unique identifier of the cached item.
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'204':
|
|
description: 'Flushed cache'
|
|
/settings/logs:
|
|
get:
|
|
summary: Returns logs
|
|
description: Returns list of all log items and details
|
|
tags:
|
|
- settings-system
|
|
parameters:
|
|
- in: query
|
|
name: take
|
|
description: The number of items to return (pagination limit).
|
|
schema:
|
|
type: number
|
|
nullable: true
|
|
example: 25
|
|
- in: query
|
|
name: skip
|
|
description: The number of items to skip (pagination offset).
|
|
schema:
|
|
type: number
|
|
nullable: true
|
|
example: 0
|
|
- in: query
|
|
name: filter
|
|
description: Filter criteria for narrowing results.
|
|
schema:
|
|
type: string
|
|
nullable: true
|
|
enum: [debug, info, warn, error]
|
|
default: debug
|
|
- in: query
|
|
name: search
|
|
description: Search query string for filtering results.
|
|
schema:
|
|
type: string
|
|
nullable: true
|
|
example: plex
|
|
responses:
|
|
'200':
|
|
description: Server log returned
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
label:
|
|
type: string
|
|
example: server
|
|
level:
|
|
type: string
|
|
example: info
|
|
message:
|
|
type: string
|
|
example: Server ready on port 5055
|
|
timestamp:
|
|
type: string
|
|
example: '2020-12-15T16:20:00.069Z'
|
|
/settings/export-debug:
|
|
post:
|
|
summary: Export debugging information
|
|
description: Exports selected debugging information (database, settings, logs) as a zip file for troubleshooting purposes.
|
|
tags:
|
|
- settings-system
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
includeDatabase:
|
|
type: boolean
|
|
description: Include database file (db.sqlite3) in export
|
|
example: true
|
|
includeSettings:
|
|
type: boolean
|
|
description: Include settings.json file in export
|
|
example: true
|
|
includeLogs:
|
|
type: boolean
|
|
description: Include logs directory in export
|
|
example: true
|
|
responses:
|
|
'200':
|
|
description: Debug export zip file
|
|
content:
|
|
application/zip:
|
|
schema:
|
|
type: string
|
|
format: binary
|
|
headers:
|
|
Content-Disposition:
|
|
schema:
|
|
type: string
|
|
example: 'attachment; filename="agregarr-debug-2025-12-19T10-30-45.zip"'
|
|
'400':
|
|
description: Invalid request (no items selected)
|
|
'500':
|
|
description: Server error during export
|
|
/settings/about:
|
|
get:
|
|
summary: Get server stats
|
|
description: Returns current server stats in a JSON object.
|
|
tags:
|
|
- settings-general
|
|
responses:
|
|
'200':
|
|
description: Returned about settings
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
version:
|
|
type: string
|
|
example: '1.0.0'
|
|
totalRequests:
|
|
type: number
|
|
example: 100
|
|
totalMediaItems:
|
|
type: number
|
|
example: 100
|
|
tz:
|
|
type: string
|
|
nullable: true
|
|
example: Asia/Tokyo
|
|
appDataPath:
|
|
type: string
|
|
example: /app/config
|
|
/auth/me:
|
|
get:
|
|
summary: Get logged-in user
|
|
description: Returns the currently logged-in user.
|
|
tags:
|
|
- auth
|
|
- users
|
|
responses:
|
|
'200':
|
|
description: Object containing the logged-in user in JSON
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/User'
|
|
/auth/plex:
|
|
post:
|
|
summary: Sign in using a Plex token
|
|
description: Takes an `authToken` (Plex token) to log the user in. Generates a session cookie for use in further requests. If the user does not exist, and there are no other users, then a user will be created with full admin privileges. If a user logs in with access to the main Plex server, they will also have an account created, but without any permissions.
|
|
security: []
|
|
tags:
|
|
- auth
|
|
responses:
|
|
'200':
|
|
description: OK
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/User'
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
authToken:
|
|
type: string
|
|
required:
|
|
- authToken
|
|
/auth/local:
|
|
post:
|
|
summary: Sign in using a local account
|
|
description: Takes an `email` and a `password` to log the user in. Generates a session cookie for use in further requests.
|
|
security: []
|
|
tags:
|
|
- auth
|
|
responses:
|
|
'200':
|
|
description: OK
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/User'
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
email:
|
|
type: string
|
|
password:
|
|
type: string
|
|
required:
|
|
- email
|
|
- password
|
|
/auth/logout:
|
|
post:
|
|
summary: Sign out and clear session cookie
|
|
description: Completely clear the session cookie and associated values, effectively signing the user out.
|
|
tags:
|
|
- auth
|
|
responses:
|
|
'200':
|
|
description: OK
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
status:
|
|
type: string
|
|
example: 'ok'
|
|
/auth/reset-password:
|
|
post:
|
|
summary: Send a reset password email
|
|
description: Sends a reset password email to the email if the user exists
|
|
security: []
|
|
tags:
|
|
- users
|
|
responses:
|
|
'200':
|
|
description: OK
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
status:
|
|
type: string
|
|
example: 'ok'
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
email:
|
|
type: string
|
|
required:
|
|
- email
|
|
/auth/reset-password/{guid}:
|
|
post:
|
|
summary: Reset the password for a user
|
|
description: Resets the password for a user if the given guid is connected to a user
|
|
security: []
|
|
tags:
|
|
- users
|
|
parameters:
|
|
- in: path
|
|
name: guid
|
|
required: true
|
|
description: The globally unique identifier for the media item.
|
|
schema:
|
|
type: string
|
|
example: '9afef5a7-ec89-4d5f-9397-261e96970b50'
|
|
responses:
|
|
'200':
|
|
description: OK
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
status:
|
|
type: string
|
|
example: 'ok'
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
password:
|
|
type: string
|
|
required:
|
|
- password
|
|
/user:
|
|
get:
|
|
summary: Get all users
|
|
description: Returns all users in a JSON object.
|
|
tags:
|
|
- users
|
|
parameters:
|
|
- in: query
|
|
name: take
|
|
description: The number of items to return (pagination limit).
|
|
schema:
|
|
type: number
|
|
nullable: true
|
|
example: 20
|
|
- in: query
|
|
name: skip
|
|
description: The number of items to skip (pagination offset).
|
|
schema:
|
|
type: number
|
|
nullable: true
|
|
example: 0
|
|
- in: query
|
|
name: sort
|
|
description: Sort order for the results.
|
|
schema:
|
|
type: string
|
|
enum: [created, updated, requests, displayname]
|
|
default: created
|
|
responses:
|
|
'200':
|
|
description: A JSON array of all users
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
pageInfo:
|
|
$ref: '#/components/schemas/PageInfo'
|
|
results:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/User'
|
|
post:
|
|
summary: Create new user
|
|
description: |
|
|
Creates a new user. Requires the `MANAGE_USERS` permission.
|
|
tags:
|
|
- users
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
email:
|
|
type: string
|
|
example: 'hey@itsme.com'
|
|
username:
|
|
type: string
|
|
permissions:
|
|
type: number
|
|
responses:
|
|
'201':
|
|
description: The created user
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/User'
|
|
put:
|
|
summary: Update batch of users
|
|
description: |
|
|
Update users with given IDs with provided values in request `body.settings`. You cannot update users' Plex tokens through this request.
|
|
|
|
Requires the `MANAGE_USERS` permission.
|
|
tags:
|
|
- users
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
ids:
|
|
type: array
|
|
items:
|
|
type: integer
|
|
permissions:
|
|
type: integer
|
|
responses:
|
|
'200':
|
|
description: Successfully updated user details
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/User'
|
|
/user/import-from-plex:
|
|
post:
|
|
summary: Import all users from Plex
|
|
description: |
|
|
Fetches and imports users from the Plex server. If a list of Plex IDs is provided in the request body, only the specified users will be imported. Otherwise, all users will be imported.
|
|
|
|
Requires the `MANAGE_USERS` permission.
|
|
tags:
|
|
- users
|
|
requestBody:
|
|
required: false
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
plexIds:
|
|
type: array
|
|
items:
|
|
type: string
|
|
responses:
|
|
'201':
|
|
description: A list of the newly created users
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/User'
|
|
/movie/{movieId}:
|
|
get:
|
|
summary: Get movie details
|
|
description: Returns full movie details in a JSON object.
|
|
tags:
|
|
- movies
|
|
parameters:
|
|
- in: path
|
|
name: movieId
|
|
required: true
|
|
description: The TMDb movie identifier.
|
|
schema:
|
|
type: number
|
|
example: 337401
|
|
- in: query
|
|
name: language
|
|
description: The ISO 639-1 language code for localized content (e.g., 'en', 'es').
|
|
schema:
|
|
type: string
|
|
example: en
|
|
responses:
|
|
'200':
|
|
description: Movie details
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/MovieDetails'
|
|
/movie/{movieId}/recommendations:
|
|
get:
|
|
summary: Get recommended movies
|
|
description: Returns list of recommended movies based on provided movie ID in a JSON object.
|
|
tags:
|
|
- movies
|
|
parameters:
|
|
- in: path
|
|
name: movieId
|
|
required: true
|
|
description: The TMDb movie identifier.
|
|
schema:
|
|
type: number
|
|
example: 337401
|
|
- in: query
|
|
name: page
|
|
description: The page number for paginated results.
|
|
schema:
|
|
type: number
|
|
example: 1
|
|
default: 1
|
|
- in: query
|
|
name: language
|
|
description: The ISO 639-1 language code for localized content (e.g., 'en', 'es').
|
|
schema:
|
|
type: string
|
|
example: en
|
|
responses:
|
|
'200':
|
|
description: List of movies
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
page:
|
|
type: number
|
|
example: 1
|
|
totalPages:
|
|
type: number
|
|
example: 20
|
|
totalResults:
|
|
type: number
|
|
example: 200
|
|
results:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/MovieResult'
|
|
/movie/{movieId}/similar:
|
|
get:
|
|
summary: Get similar movies
|
|
description: Returns list of similar movies based on the provided movieId in a JSON object.
|
|
tags:
|
|
- movies
|
|
parameters:
|
|
- in: path
|
|
name: movieId
|
|
required: true
|
|
description: The TMDb movie identifier.
|
|
schema:
|
|
type: number
|
|
example: 337401
|
|
- in: query
|
|
name: page
|
|
description: The page number for paginated results.
|
|
schema:
|
|
type: number
|
|
example: 1
|
|
default: 1
|
|
- in: query
|
|
name: language
|
|
description: The ISO 639-1 language code for localized content (e.g., 'en', 'es').
|
|
schema:
|
|
type: string
|
|
example: en
|
|
responses:
|
|
'200':
|
|
description: List of movies
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
page:
|
|
type: number
|
|
example: 1
|
|
totalPages:
|
|
type: number
|
|
example: 20
|
|
totalResults:
|
|
type: number
|
|
example: 200
|
|
results:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/MovieResult'
|
|
/movie/{movieId}/ratings:
|
|
get:
|
|
summary: Get movie ratings
|
|
description: Returns ratings based on the provided movieId in a JSON object.
|
|
tags:
|
|
- movies
|
|
parameters:
|
|
- in: path
|
|
name: movieId
|
|
required: true
|
|
description: The TMDb movie identifier.
|
|
schema:
|
|
type: number
|
|
example: 337401
|
|
responses:
|
|
'200':
|
|
description: Ratings returned
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
title:
|
|
type: string
|
|
example: Mulan
|
|
year:
|
|
type: number
|
|
example: 2020
|
|
url:
|
|
type: string
|
|
example: 'http://www.rottentomatoes.com/m/mulan_2020/'
|
|
criticsScore:
|
|
type: number
|
|
example: 85
|
|
criticsRating:
|
|
type: string
|
|
enum: ['Rotten', 'Fresh', 'Certified Fresh']
|
|
audienceScore:
|
|
type: number
|
|
example: 65
|
|
audienceRating:
|
|
type: string
|
|
enum: ['Spilled', 'Upright']
|
|
/movie/{movieId}/ratingscombined:
|
|
get:
|
|
summary: Get RT and IMDB movie ratings combined
|
|
description: Returns ratings from RottenTomatoes and IMDB based on the provided movieId in a JSON object.
|
|
tags:
|
|
- movies
|
|
parameters:
|
|
- in: path
|
|
name: movieId
|
|
description: The TMDb movie identifier.
|
|
required: true
|
|
schema:
|
|
type: number
|
|
example: 337401
|
|
responses:
|
|
'200':
|
|
description: Ratings returned
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
rt:
|
|
type: object
|
|
properties:
|
|
title:
|
|
type: string
|
|
example: Mulan
|
|
year:
|
|
type: number
|
|
example: 2020
|
|
url:
|
|
type: string
|
|
example: 'http://www.rottentomatoes.com/m/mulan_2020/'
|
|
criticsScore:
|
|
type: number
|
|
example: 85
|
|
criticsRating:
|
|
type: string
|
|
enum: ['Rotten', 'Fresh', 'Certified Fresh']
|
|
audienceScore:
|
|
type: number
|
|
example: 65
|
|
audienceRating:
|
|
type: string
|
|
enum: ['Spilled', 'Upright']
|
|
imdb:
|
|
type: object
|
|
properties:
|
|
title:
|
|
type: string
|
|
example: I am Legend
|
|
url:
|
|
type: string
|
|
example: 'https://www.imdb.com/title/tt0480249'
|
|
criticsScore:
|
|
type: number
|
|
example: 6.5
|
|
/tv/{tvId}:
|
|
get:
|
|
summary: Get TV details
|
|
description: Returns full TV details in a JSON object.
|
|
tags:
|
|
- tv
|
|
parameters:
|
|
- in: path
|
|
name: tvId
|
|
required: true
|
|
description: The TMDb TV series identifier.
|
|
schema:
|
|
type: number
|
|
example: 76479
|
|
- in: query
|
|
name: language
|
|
description: The ISO 639-1 language code for localized content (e.g., 'en', 'es').
|
|
schema:
|
|
type: string
|
|
example: en
|
|
responses:
|
|
'200':
|
|
description: TV details
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/TvDetails'
|
|
/tv/{tvId}/season/{seasonId}:
|
|
get:
|
|
summary: Get season details and episode list
|
|
description: Returns season details with a list of episodes in a JSON object.
|
|
tags:
|
|
- tv
|
|
parameters:
|
|
- in: path
|
|
name: tvId
|
|
required: true
|
|
description: The TMDb TV series identifier.
|
|
schema:
|
|
type: number
|
|
example: 76479
|
|
- in: path
|
|
name: seasonId
|
|
required: true
|
|
description: The TMDb season identifier.
|
|
schema:
|
|
type: number
|
|
example: 1
|
|
- in: query
|
|
name: language
|
|
description: The ISO 639-1 language code for localized content (e.g., 'en', 'es').
|
|
schema:
|
|
type: string
|
|
example: en
|
|
responses:
|
|
'200':
|
|
description: TV details
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Season'
|
|
/media:
|
|
get:
|
|
summary: Get media
|
|
description: Returns all media (can be filtered and limited) in a JSON object.
|
|
tags:
|
|
- media
|
|
parameters:
|
|
- in: query
|
|
name: take
|
|
description: The number of items to return (pagination limit).
|
|
schema:
|
|
type: number
|
|
nullable: true
|
|
example: 20
|
|
- in: query
|
|
name: skip
|
|
description: The number of items to skip (pagination offset).
|
|
schema:
|
|
type: number
|
|
nullable: true
|
|
example: 0
|
|
- in: query
|
|
name: filter
|
|
description: Filter criteria for narrowing results.
|
|
schema:
|
|
type: string
|
|
nullable: true
|
|
enum:
|
|
[
|
|
all,
|
|
available,
|
|
partial,
|
|
allavailable,
|
|
processing,
|
|
pending,
|
|
deleted,
|
|
]
|
|
- in: query
|
|
name: sort
|
|
description: Sort order for the results.
|
|
schema:
|
|
type: string
|
|
enum: [added, modified, mediaAdded]
|
|
default: added
|
|
responses:
|
|
'200':
|
|
description: Returned media
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
pageInfo:
|
|
$ref: '#/components/schemas/PageInfo'
|
|
results:
|
|
type: array
|
|
/media/{mediaId}:
|
|
delete:
|
|
summary: Delete media item
|
|
description: Removes a media item. The `MANAGE_REQUESTS` permission is required to perform this action.
|
|
tags:
|
|
- media
|
|
parameters:
|
|
- in: path
|
|
name: mediaId
|
|
description: Media ID
|
|
required: true
|
|
example: '1'
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'204':
|
|
description: Succesfully removed media item
|
|
/media/{mediaId}/{status}:
|
|
post:
|
|
summary: Update media status
|
|
description: Updates a media item's status and returns the media in JSON format
|
|
tags:
|
|
- media
|
|
parameters:
|
|
- in: path
|
|
name: mediaId
|
|
description: Media ID
|
|
required: true
|
|
example: '1'
|
|
schema:
|
|
type: string
|
|
- in: path
|
|
name: status
|
|
description: New status
|
|
required: true
|
|
example: available
|
|
schema:
|
|
type: string
|
|
enum: [available, partial, processing, pending, unknown, deleted]
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
is4k:
|
|
type: boolean
|
|
example: false
|
|
responses:
|
|
'200':
|
|
description: Returned media
|
|
/media/{mediaId}/watch_data:
|
|
get:
|
|
summary: Get watch data
|
|
description: |
|
|
Returns play count, play duration, and users who have watched the media.
|
|
|
|
Requires the `ADMIN` permission.
|
|
tags:
|
|
- media
|
|
parameters:
|
|
- in: path
|
|
name: mediaId
|
|
description: Media ID
|
|
required: true
|
|
example: '1'
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Users
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
data:
|
|
type: object
|
|
properties:
|
|
playCount7Days:
|
|
type: number
|
|
playCount30Days:
|
|
type: number
|
|
playCount:
|
|
type: number
|
|
users:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/User'
|
|
data4k:
|
|
type: object
|
|
properties:
|
|
playCount7Days:
|
|
type: number
|
|
playCount30Days:
|
|
type: number
|
|
playCount:
|
|
type: number
|
|
users:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/User'
|
|
/service/radarr:
|
|
get:
|
|
summary: Get non-sensitive Radarr server list
|
|
description: Returns a list of Radarr server IDs and names in a JSON object.
|
|
tags:
|
|
- service
|
|
responses:
|
|
'200':
|
|
description: Request successful
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/RadarrSettings'
|
|
/service/radarr/{radarrId}:
|
|
get:
|
|
summary: Get Radarr server quality profiles and root folders
|
|
description: Returns a Radarr server's quality profile and root folder details in a JSON object.
|
|
tags:
|
|
- service
|
|
parameters:
|
|
- in: path
|
|
name: radarrId
|
|
required: true
|
|
description: The Radarr service instance identifier.
|
|
schema:
|
|
type: number
|
|
example: 0
|
|
responses:
|
|
'200':
|
|
description: Request successful
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
server:
|
|
$ref: '#/components/schemas/RadarrSettings'
|
|
profiles:
|
|
$ref: '#/components/schemas/ServiceProfile'
|
|
/service/sonarr:
|
|
get:
|
|
summary: Get non-sensitive Sonarr server list
|
|
description: Returns a list of Sonarr server IDs and names in a JSON object.
|
|
tags:
|
|
- service
|
|
responses:
|
|
'200':
|
|
description: Request successful
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/SonarrSettings'
|
|
/service/sonarr/{sonarrId}:
|
|
get:
|
|
summary: Get Sonarr server quality profiles and root folders
|
|
description: Returns a Sonarr server's quality profile and root folder details in a JSON object.
|
|
tags:
|
|
- service
|
|
parameters:
|
|
- in: path
|
|
name: sonarrId
|
|
required: true
|
|
description: The Sonarr service instance identifier.
|
|
schema:
|
|
type: number
|
|
example: 0
|
|
responses:
|
|
'200':
|
|
description: Request successful
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
server:
|
|
$ref: '#/components/schemas/SonarrSettings'
|
|
profiles:
|
|
$ref: '#/components/schemas/ServiceProfile'
|
|
/service/sonarr/lookup/{tmdbId}:
|
|
get:
|
|
summary: Get series from Sonarr
|
|
description: Returns a list of series returned by searching for the name in Sonarr.
|
|
tags:
|
|
- service
|
|
parameters:
|
|
- in: path
|
|
name: tmdbId
|
|
required: true
|
|
description: The TMDb identifier for movies or TV series.
|
|
schema:
|
|
type: number
|
|
example: 0
|
|
responses:
|
|
'200':
|
|
description: Request successful
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/SonarrSeries'
|
|
/backdrops:
|
|
get:
|
|
summary: Get backdrops of trending items
|
|
description: Returns a list of backdrop image paths in a JSON array.
|
|
security: []
|
|
tags:
|
|
- tmdb
|
|
responses:
|
|
'200':
|
|
description: Results
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
type: string
|
|
/keyword/{keywordId}:
|
|
get:
|
|
summary: Get keyword
|
|
description: |
|
|
Returns a single keyword in JSON format.
|
|
tags:
|
|
- other
|
|
parameters:
|
|
- in: path
|
|
name: keywordId
|
|
required: true
|
|
description: The TMDb keyword identifier.
|
|
schema:
|
|
type: number
|
|
example: 1
|
|
responses:
|
|
'200':
|
|
description: Keyword returned
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Keyword'
|
|
/missing-items:
|
|
get:
|
|
summary: Get missing item requests
|
|
description: |
|
|
Returns a paginated list of missing item requests with optional filtering.
|
|
tags:
|
|
- missing-items
|
|
parameters:
|
|
- in: query
|
|
name: limit
|
|
schema:
|
|
type: integer
|
|
default: 10
|
|
minimum: 1
|
|
maximum: 100
|
|
description: Number of items to return
|
|
- in: query
|
|
name: offset
|
|
schema:
|
|
type: integer
|
|
default: 0
|
|
minimum: 0
|
|
description: Number of items to skip
|
|
- in: query
|
|
name: status
|
|
schema:
|
|
type: string
|
|
enum:
|
|
[
|
|
pending,
|
|
approved,
|
|
declined,
|
|
available,
|
|
processing,
|
|
failed,
|
|
partially_available,
|
|
]
|
|
description: Filter by request status
|
|
- in: query
|
|
name: mediaType
|
|
schema:
|
|
type: string
|
|
enum: [movie, tv]
|
|
description: Filter by media type
|
|
- in: query
|
|
name: collectionSource
|
|
schema:
|
|
type: string
|
|
enum:
|
|
[
|
|
trakt,
|
|
tmdb,
|
|
imdb,
|
|
letterboxd,
|
|
mdblist,
|
|
tautulli,
|
|
networks,
|
|
originals,
|
|
overseerr,
|
|
anilist,
|
|
myanimelist,
|
|
radarrtag,
|
|
sonarrtag,
|
|
comingsoon,
|
|
filtered_hub,
|
|
multi-source,
|
|
]
|
|
description: Filter by collection source
|
|
- in: query
|
|
name: requestService
|
|
schema:
|
|
type: string
|
|
enum: [overseerr, radarr, sonarr]
|
|
description: Filter by request service
|
|
responses:
|
|
'200':
|
|
description: Missing item requests returned
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/MissingItemsResponse'
|
|
/missing-items/recent:
|
|
get:
|
|
summary: Get recent missing item requests
|
|
description: |
|
|
Returns the most recent missing item requests for dashboard display.
|
|
tags:
|
|
- missing-items
|
|
parameters:
|
|
- in: query
|
|
name: limit
|
|
schema:
|
|
type: integer
|
|
default: 5
|
|
minimum: 1
|
|
maximum: 20
|
|
description: Number of recent items to return
|
|
responses:
|
|
'200':
|
|
description: Recent missing item requests returned
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
results:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/MissingItemRequest'
|
|
/missing-items/stats:
|
|
get:
|
|
summary: Get missing item statistics
|
|
description: |
|
|
Returns statistics about missing item requests including status breakdowns and source/service distribution.
|
|
tags:
|
|
- missing-items
|
|
responses:
|
|
'200':
|
|
description: Missing item statistics returned
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/MissingItemStats'
|
|
/missing-items/sync:
|
|
post:
|
|
summary: Sync missing item status
|
|
description: |
|
|
Synchronizes the status of missing item requests with their current status in Overseerr.
|
|
This endpoint checks recent missing item requests and updates their status based on
|
|
the current state in Overseerr (e.g., pending → declined, approved → available).
|
|
tags:
|
|
- missing-items
|
|
responses:
|
|
'200':
|
|
description: Missing item status sync completed successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: 'Missing item status sync completed'
|
|
'500':
|
|
description: Failed to sync missing item status
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: 'Failed to sync missing item status'
|
|
/dashboard/stats:
|
|
get:
|
|
summary: Get dashboard statistics
|
|
description: |
|
|
Returns general dashboard statistics including collection counts, activity stats from Tautulli, and weekly plays.
|
|
tags:
|
|
- dashboard
|
|
responses:
|
|
'200':
|
|
description: Dashboard statistics returned successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/DashboardStats'
|
|
'500':
|
|
description: Failed to get dashboard statistics
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Failed to get dashboard stats'
|
|
message:
|
|
type: string
|
|
example: 'Tautulli connection failed'
|
|
/dashboard/collections:
|
|
get:
|
|
summary: Get collection statistics
|
|
description: |
|
|
Returns detailed collection statistics from Tautulli including play counts, duration, and user activity.
|
|
tags:
|
|
- dashboard
|
|
parameters:
|
|
- in: query
|
|
name: limit
|
|
schema:
|
|
type: integer
|
|
default: 10
|
|
minimum: 1
|
|
maximum: 50
|
|
description: Number of collections to return
|
|
- in: query
|
|
name: statType
|
|
schema:
|
|
type: string
|
|
enum: [plays, duration]
|
|
default: plays
|
|
description: Type of statistics to sort by
|
|
- in: query
|
|
name: days
|
|
schema:
|
|
type: integer
|
|
default: 30
|
|
minimum: 1
|
|
maximum: 365
|
|
description: Number of days to include in statistics
|
|
responses:
|
|
'200':
|
|
description: Collection statistics returned successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/CollectionStatsResponse'
|
|
'400':
|
|
description: Tautulli not configured
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Tautulli not configured'
|
|
message:
|
|
type: string
|
|
example: 'Tautulli settings are required to fetch collection statistics'
|
|
'500':
|
|
description: Failed to get collection statistics
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Failed to get collection statistics'
|
|
message:
|
|
type: string
|
|
example: 'Tautulli API error'
|
|
/dashboard/activity:
|
|
get:
|
|
summary: Get activity statistics
|
|
description: |
|
|
Returns recent activity and general statistics from Tautulli including top movies and TV shows.
|
|
tags:
|
|
- dashboard
|
|
parameters:
|
|
- in: query
|
|
name: days
|
|
schema:
|
|
type: integer
|
|
default: 7
|
|
minimum: 1
|
|
maximum: 365
|
|
description: Number of days to include in activity statistics
|
|
- in: query
|
|
name: limit
|
|
schema:
|
|
type: integer
|
|
default: 10
|
|
minimum: 1
|
|
maximum: 50
|
|
description: Number of items to return
|
|
responses:
|
|
'200':
|
|
description: Activity statistics returned successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ActivityStatsResponse'
|
|
'400':
|
|
description: Tautulli not configured
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Tautulli not configured'
|
|
message:
|
|
type: string
|
|
example: 'Tautulli settings are required to fetch activity statistics'
|
|
'500':
|
|
description: Failed to get activity statistics
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Failed to get activity statistics'
|
|
message:
|
|
type: string
|
|
example: 'Tautulli API error'
|
|
|
|
# Hub Management Endpoints
|
|
/hubs/configs:
|
|
get:
|
|
summary: Get current Plex hub configurations
|
|
description: Retrieve all hub configurations across all libraries.
|
|
tags:
|
|
- hubs
|
|
responses:
|
|
'200':
|
|
description: Hub configurations returned successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
hubConfigs:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/PlexHubConfig'
|
|
preExistingCollectionConfigs:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/PlexHubConfig'
|
|
'500':
|
|
description: Failed to get hub configurations
|
|
post:
|
|
summary: Save Plex hub configurations
|
|
description: Create or update hub configurations.
|
|
tags:
|
|
- hubs
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
hubConfigs:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/PlexHubConfig'
|
|
preExistingCollectionConfigs:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/PlexHubConfig'
|
|
responses:
|
|
'200':
|
|
description: Configurations saved successfully
|
|
'400':
|
|
description: Invalid input
|
|
'500':
|
|
description: Failed to save configurations
|
|
|
|
/hubs/configs/append:
|
|
post:
|
|
summary: Append new hub configurations to existing ones
|
|
description: Append new hub configurations to existing ones.
|
|
tags:
|
|
- hubs
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
hubConfigs:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/PlexHubConfig'
|
|
preExistingCollectionConfigs:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/PlexHubConfig'
|
|
responses:
|
|
'200':
|
|
description: Configurations appended successfully
|
|
'400':
|
|
description: Invalid input
|
|
'500':
|
|
description: Failed to append configurations
|
|
|
|
/hubs/libraries/{sectionId}/move:
|
|
put:
|
|
summary: Move a hub to a new position in the library
|
|
description: Move a hub to a different position within a library.
|
|
tags:
|
|
- hubs
|
|
parameters:
|
|
- in: path
|
|
name: sectionId
|
|
required: true
|
|
schema:
|
|
type: string
|
|
description: Plex library section ID
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
hubId:
|
|
type: string
|
|
description: Hub identifier to move
|
|
afterHubId:
|
|
type: string
|
|
description: Hub identifier to move after (optional)
|
|
required:
|
|
- hubId
|
|
responses:
|
|
'200':
|
|
description: Hub moved successfully
|
|
'400':
|
|
description: Invalid input
|
|
'500':
|
|
description: Failed to move hub
|
|
|
|
/hubs/libraries/{sectionId}/reorder:
|
|
put:
|
|
summary: Reorder multiple hubs in a library section
|
|
description: Reorder hubs within a specific library section.
|
|
tags:
|
|
- hubs
|
|
parameters:
|
|
- in: path
|
|
name: sectionId
|
|
required: true
|
|
schema:
|
|
type: string
|
|
description: Plex library section ID
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
hubOrder:
|
|
type: array
|
|
items:
|
|
type: string
|
|
description: Array of hub IDs in desired order
|
|
required:
|
|
- hubOrder
|
|
responses:
|
|
'200':
|
|
description: Hubs reordered successfully
|
|
'400':
|
|
description: Invalid input
|
|
'500':
|
|
description: Failed to reorder hubs
|
|
|
|
/hubs/libraries/{sectionId}/visibility:
|
|
put:
|
|
summary: Update hub visibility settings
|
|
description: Update visibility settings for hubs in a specific library section.
|
|
tags:
|
|
- hubs
|
|
parameters:
|
|
- in: path
|
|
name: sectionId
|
|
required: true
|
|
schema:
|
|
type: string
|
|
description: Plex library section ID
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
hubId:
|
|
type: string
|
|
description: Hub identifier
|
|
visibility:
|
|
type: object
|
|
description: Visibility configuration
|
|
required:
|
|
- hubId
|
|
- visibility
|
|
responses:
|
|
'200':
|
|
description: Hub visibility updated successfully
|
|
'400':
|
|
description: Invalid input
|
|
'500':
|
|
description: Failed to update hub visibility
|
|
|
|
# Discovery Endpoints
|
|
/discovery/hubs/libraries:
|
|
get:
|
|
summary: Get all library hubs across all sections
|
|
description: Discover available Plex hubs across all libraries.
|
|
tags:
|
|
- search
|
|
responses:
|
|
'200':
|
|
description: Library hubs returned successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
description: 'Object with library section IDs as keys and hub data as values'
|
|
additionalProperties:
|
|
type: object
|
|
description: 'Raw Plex hub response data for a library section'
|
|
'500':
|
|
description: Failed to fetch library hubs
|
|
|
|
/discovery/hubs/libraries/{sectionId}:
|
|
get:
|
|
summary: Get hubs for a specific library section
|
|
description: Discover available Plex hubs for a specific library section.
|
|
tags:
|
|
- search
|
|
parameters:
|
|
- in: path
|
|
name: sectionId
|
|
required: true
|
|
schema:
|
|
type: string
|
|
description: Plex library section ID
|
|
responses:
|
|
'200':
|
|
description: Library hubs returned successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
description: 'Raw Plex hub response data for the specified library section'
|
|
'500':
|
|
description: Failed to fetch library hubs
|
|
|
|
/discovery/hubs/libraries/{sectionId}/manage:
|
|
get:
|
|
summary: Get hub management interface for a library section
|
|
description: Get hub management interface data for a specific library section.
|
|
tags:
|
|
- search
|
|
parameters:
|
|
- in: path
|
|
name: sectionId
|
|
required: true
|
|
schema:
|
|
type: string
|
|
description: Plex library section ID
|
|
responses:
|
|
'200':
|
|
description: Hub management data returned successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/PlexHubManagementResponse'
|
|
'500':
|
|
description: Failed to fetch hub management data
|
|
|
|
/discovery/hubs/scan:
|
|
get:
|
|
summary: Discover available Plex hubs and convert them to hub configurations
|
|
description: Scan Plex server for available hubs and their current state.
|
|
tags:
|
|
- search
|
|
responses:
|
|
'200':
|
|
description: Hub discovery completed successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
discoveredHubConfigs:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/PlexHubConfig'
|
|
discoveredPreExistingConfigs:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/PlexHubConfig'
|
|
totalHubsFound:
|
|
type: integer
|
|
totalPreExistingCollectionsFound:
|
|
type: integer
|
|
totalActualCollections:
|
|
type: integer
|
|
'500':
|
|
description: Failed to discover Plex hubs
|
|
|
|
/discovery/hubs/status:
|
|
get:
|
|
summary: Get hub management system status and capabilities
|
|
description: Get the current status of hub discovery operations.
|
|
tags:
|
|
- search
|
|
responses:
|
|
'200':
|
|
description: Hub management status returned successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
enabled:
|
|
type: boolean
|
|
plexConnected:
|
|
type: boolean
|
|
libraryCount:
|
|
type: integer
|
|
capabilities:
|
|
type: object
|
|
properties:
|
|
hubReordering:
|
|
type: boolean
|
|
visibilityControl:
|
|
type: boolean
|
|
builtInHubManagement:
|
|
type: boolean
|
|
collectionHubManagement:
|
|
type: boolean
|
|
'500':
|
|
description: Failed to get hub management status
|
|
|
|
# Poster Management Endpoints
|
|
/posters/templates:
|
|
get:
|
|
summary: Get all poster templates
|
|
description: Retrieves all active poster templates with their metadata and configuration.
|
|
tags:
|
|
- poster-templates
|
|
responses:
|
|
'200':
|
|
description: Templates retrieved successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
templates:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
example: 1
|
|
name:
|
|
type: string
|
|
example: 'Classic Movie Poster'
|
|
description:
|
|
type: string
|
|
example: 'A classic movie poster template with text overlays'
|
|
isDefault:
|
|
type: boolean
|
|
example: false
|
|
templateData:
|
|
type: object
|
|
properties:
|
|
width:
|
|
type: number
|
|
example: 1000
|
|
height:
|
|
type: number
|
|
example: 1500
|
|
background:
|
|
type: object
|
|
properties:
|
|
type:
|
|
type: string
|
|
enum: [color, gradient, radial]
|
|
example: 'gradient'
|
|
color:
|
|
type: string
|
|
example: '#6366f1'
|
|
secondaryColor:
|
|
type: string
|
|
example: '#1e1b4b'
|
|
intensity:
|
|
type: number
|
|
description: 'Gradient spread intensity (0-100)'
|
|
example: 50
|
|
useSourceColors:
|
|
type: boolean
|
|
example: false
|
|
# New unified layering system (preferred)
|
|
elements:
|
|
type: array
|
|
description: 'Unified element list with custom layer ordering (used when migrated=true)'
|
|
items:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
example: 'element-1'
|
|
layerOrder:
|
|
type: number
|
|
description: 'Layer order - lower numbers render behind higher numbers'
|
|
example: 20
|
|
type:
|
|
type: string
|
|
enum: [text, raster, svg, content-grid]
|
|
example: 'text'
|
|
x:
|
|
type: number
|
|
example: 50
|
|
y:
|
|
type: number
|
|
example: 100
|
|
width:
|
|
type: number
|
|
example: 400
|
|
height:
|
|
type: number
|
|
example: 60
|
|
properties:
|
|
type: object
|
|
description: 'Type-specific properties based on element type'
|
|
oneOf:
|
|
- type: object
|
|
title: 'Text Element Properties'
|
|
properties:
|
|
elementType:
|
|
type: string
|
|
enum:
|
|
[collection-title, custom-text]
|
|
text:
|
|
type: string
|
|
fontSize:
|
|
type: number
|
|
fontFamily:
|
|
type: string
|
|
fontWeight:
|
|
type: string
|
|
enum: [normal, bold]
|
|
fontStyle:
|
|
type: string
|
|
enum: [normal, italic]
|
|
color:
|
|
type: string
|
|
textAlign:
|
|
type: string
|
|
enum: [left, center, right]
|
|
maxLines:
|
|
type: number
|
|
- type: object
|
|
title: 'Raster Element Properties'
|
|
properties:
|
|
imagePath:
|
|
type: string
|
|
- type: object
|
|
title: 'SVG Element Properties'
|
|
properties:
|
|
iconType:
|
|
type: string
|
|
enum: [source-logo, svg-icon]
|
|
iconPath:
|
|
type: string
|
|
grayscale:
|
|
type: boolean
|
|
- type: object
|
|
title: 'Content Grid Properties'
|
|
properties:
|
|
columns:
|
|
type: number
|
|
rows:
|
|
type: number
|
|
spacing:
|
|
type: number
|
|
cornerRadius:
|
|
type: number
|
|
migrated:
|
|
type: boolean
|
|
description: 'Flag indicating if template has been migrated to unified layering system'
|
|
example: true
|
|
# Legacy structure (for backward compatibility)
|
|
textElements:
|
|
type: array
|
|
description: 'Legacy text elements (used when migrated=false)'
|
|
items:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
example: 'text-1'
|
|
type:
|
|
type: string
|
|
enum: [collection-title, custom-text]
|
|
example: 'collection-title'
|
|
text:
|
|
type: string
|
|
example: 'Collection Name'
|
|
x:
|
|
type: number
|
|
example: 50
|
|
y:
|
|
type: number
|
|
example: 100
|
|
width:
|
|
type: number
|
|
example: 400
|
|
height:
|
|
type: number
|
|
example: 60
|
|
fontSize:
|
|
type: number
|
|
example: 32
|
|
fontFamily:
|
|
type: string
|
|
example: 'Arial, sans-serif'
|
|
fontWeight:
|
|
type: string
|
|
enum: [normal, bold]
|
|
example: 'bold'
|
|
fontStyle:
|
|
type: string
|
|
enum: [normal, italic]
|
|
example: 'normal'
|
|
color:
|
|
type: string
|
|
example: '#ffffff'
|
|
textAlign:
|
|
type: string
|
|
enum: [left, center, right]
|
|
example: 'center'
|
|
maxLines:
|
|
type: number
|
|
example: 2
|
|
iconElements:
|
|
type: array
|
|
description: 'Legacy icon elements (used when migrated=false)'
|
|
items:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
example: 'icon-1'
|
|
type:
|
|
type: string
|
|
enum: [source-logo, custom-icon]
|
|
example: 'source-logo'
|
|
iconPath:
|
|
type: string
|
|
example: '/icons/tmdb-logo.svg'
|
|
x:
|
|
type: number
|
|
example: 25
|
|
y:
|
|
type: number
|
|
example: 25
|
|
width:
|
|
type: number
|
|
example: 50
|
|
height:
|
|
type: number
|
|
example: 50
|
|
grayscale:
|
|
type: boolean
|
|
example: false
|
|
rasterElements:
|
|
type: array
|
|
description: 'Legacy raster image elements (used when migrated=false)'
|
|
items:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
example: 'raster-1'
|
|
type:
|
|
type: string
|
|
enum: [raster-image]
|
|
example: 'raster-image'
|
|
imagePath:
|
|
type: string
|
|
example: '/uploads/background.jpg'
|
|
x:
|
|
type: number
|
|
example: 0
|
|
y:
|
|
type: number
|
|
example: 0
|
|
width:
|
|
type: number
|
|
example: 500
|
|
height:
|
|
type: number
|
|
example: 300
|
|
svgElements:
|
|
type: array
|
|
description: 'Legacy SVG elements (used when migrated=false)'
|
|
items:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
example: 'svg-1'
|
|
type:
|
|
type: string
|
|
enum: [source-logo, svg-icon]
|
|
example: 'svg-icon'
|
|
iconPath:
|
|
type: string
|
|
example: '/icons/custom.svg'
|
|
x:
|
|
type: number
|
|
example: 25
|
|
y:
|
|
type: number
|
|
example: 25
|
|
width:
|
|
type: number
|
|
example: 50
|
|
height:
|
|
type: number
|
|
example: 50
|
|
grayscale:
|
|
type: boolean
|
|
example: false
|
|
contentGrid:
|
|
type: object
|
|
description: 'Legacy content grid (used when migrated=false)'
|
|
properties:
|
|
id:
|
|
type: string
|
|
example: 'grid-1'
|
|
x:
|
|
type: number
|
|
example: 50
|
|
y:
|
|
type: number
|
|
example: 200
|
|
width:
|
|
type: number
|
|
example: 400
|
|
height:
|
|
type: number
|
|
example: 400
|
|
columns:
|
|
type: number
|
|
example: 3
|
|
rows:
|
|
type: number
|
|
example: 3
|
|
spacing:
|
|
type: number
|
|
example: 10
|
|
cornerRadius:
|
|
type: number
|
|
example: 8
|
|
createdAt:
|
|
type: string
|
|
format: date-time
|
|
updatedAt:
|
|
type: string
|
|
format: date-time
|
|
'500':
|
|
description: Failed to fetch poster templates
|
|
post:
|
|
summary: Create new poster template
|
|
description: Creates a new poster template with the provided configuration.
|
|
tags:
|
|
- poster-templates
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- name
|
|
- templateData
|
|
properties:
|
|
name:
|
|
type: string
|
|
example: 'My Custom Template'
|
|
description:
|
|
type: string
|
|
example: 'A custom poster template'
|
|
templateData:
|
|
type: object
|
|
description: 'Template configuration data (same structure as in GET response)'
|
|
responses:
|
|
'201':
|
|
description: Template created successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
description: 'Same structure as template object in GET response'
|
|
'400':
|
|
description: Invalid template data or validation failed
|
|
'401':
|
|
description: Authentication required
|
|
'500':
|
|
description: Failed to create poster template
|
|
|
|
/posters/templates/{id}:
|
|
put:
|
|
summary: Update poster template
|
|
description: Updates an existing poster template. Users can only update their own templates.
|
|
tags:
|
|
- poster-templates
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
description: Template ID
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
description:
|
|
type: string
|
|
templateData:
|
|
type: object
|
|
responses:
|
|
'200':
|
|
description: Template updated successfully
|
|
'400':
|
|
description: Invalid template data
|
|
'401':
|
|
description: Authentication required
|
|
'403':
|
|
description: Permission denied
|
|
'404':
|
|
description: Template not found
|
|
'500':
|
|
description: Failed to update poster template
|
|
delete:
|
|
summary: Delete poster template
|
|
description: Soft deletes a poster template. Users can only delete their own templates. Default templates cannot be deleted.
|
|
tags:
|
|
- poster-templates
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
description: Template ID
|
|
responses:
|
|
'204':
|
|
description: Template deleted successfully
|
|
'401':
|
|
description: Authentication required
|
|
'403':
|
|
description: Permission denied or cannot delete default template
|
|
'404':
|
|
description: Template not found
|
|
'500':
|
|
description: Failed to delete poster template
|
|
|
|
/posters/templates/{id}/set-default:
|
|
post:
|
|
summary: Set template as default
|
|
description: Sets the specified template as the default template for poster generation. Only one template can be default at a time.
|
|
tags:
|
|
- poster-templates
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
description: Template ID
|
|
example: 1
|
|
responses:
|
|
'200':
|
|
description: Template set as default successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: 'Template set as default successfully'
|
|
template:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
example: 1
|
|
name:
|
|
type: string
|
|
example: 'My Custom Template'
|
|
isDefault:
|
|
type: boolean
|
|
example: true
|
|
'401':
|
|
description: Authentication required
|
|
'404':
|
|
description: Template not found
|
|
'500':
|
|
description: Failed to set template as default
|
|
|
|
/posters/templates/{id}/preview:
|
|
get:
|
|
summary: Generate template preview
|
|
description: Generates a preview image of a poster template with optional collection data.
|
|
tags:
|
|
- poster-templates
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
description: Template ID
|
|
- name: collectionName
|
|
in: query
|
|
schema:
|
|
type: string
|
|
default: 'Preview Collection'
|
|
description: Collection name to use in preview
|
|
- name: collectionType
|
|
in: query
|
|
schema:
|
|
type: string
|
|
description: Collection type
|
|
- name: mediaType
|
|
in: query
|
|
schema:
|
|
type: string
|
|
enum: [movie, tv]
|
|
default: movie
|
|
description: Media type
|
|
- name: t
|
|
in: query
|
|
schema:
|
|
type: string
|
|
description: Cache-busting timestamp parameter
|
|
responses:
|
|
'200':
|
|
description: Preview image generated successfully
|
|
content:
|
|
image/png:
|
|
schema:
|
|
type: string
|
|
format: binary
|
|
'400':
|
|
description: Invalid template ID or failed to generate preview
|
|
'500':
|
|
description: Failed to generate template preview
|
|
|
|
/posters/templates/validate:
|
|
post:
|
|
summary: Validate template data
|
|
description: Validates poster template data structure and returns sanitized data if valid.
|
|
tags:
|
|
- poster-templates
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- templateData
|
|
properties:
|
|
templateData:
|
|
type: object
|
|
description: 'Template data to validate'
|
|
responses:
|
|
'200':
|
|
description: Validation completed
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
isValid:
|
|
type: boolean
|
|
example: true
|
|
errors:
|
|
type: array
|
|
items:
|
|
type: string
|
|
example: []
|
|
warnings:
|
|
type: array
|
|
items:
|
|
type: string
|
|
example: []
|
|
sanitizedData:
|
|
type: object
|
|
description: 'Sanitized template data (only present if isValid is true)'
|
|
'400':
|
|
description: Template data is required
|
|
'500':
|
|
description: Failed to validate template data
|
|
|
|
/posters/templates/{id}/export:
|
|
get:
|
|
summary: Export template as ZIP with assets
|
|
description: Exports a poster template as a downloadable ZIP file containing the template JSON and all required custom assets (icons, images).
|
|
tags:
|
|
- poster-templates
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: Template ID
|
|
schema:
|
|
type: integer
|
|
example: 1
|
|
responses:
|
|
'200':
|
|
description: Template exported successfully as ZIP file
|
|
content:
|
|
application/zip:
|
|
schema:
|
|
type: string
|
|
format: binary
|
|
description: ZIP file containing template.json and assets/ folder with custom icons and images
|
|
'400':
|
|
description: Invalid template ID
|
|
'404':
|
|
description: Template not found
|
|
'500':
|
|
description: Failed to export template
|
|
|
|
/posters/templates/import:
|
|
post:
|
|
summary: Import template from ZIP
|
|
description: Imports a poster template from a ZIP file exported from Agregarr. The ZIP file must contain template.json and any required custom assets.
|
|
tags:
|
|
- poster-templates
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
multipart/form-data:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- file
|
|
properties:
|
|
file:
|
|
type: string
|
|
format: binary
|
|
description: ZIP file containing template.json and assets
|
|
responses:
|
|
'201':
|
|
description: Template imported successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
example: 5
|
|
name:
|
|
type: string
|
|
example: 'Imported Template'
|
|
description:
|
|
type: string
|
|
example: 'A template imported from another instance'
|
|
isDefault:
|
|
type: boolean
|
|
example: false
|
|
templateData:
|
|
type: object
|
|
description: 'Complete template configuration data'
|
|
createdAt:
|
|
type: string
|
|
format: date-time
|
|
updatedAt:
|
|
type: string
|
|
format: date-time
|
|
'400':
|
|
description: Invalid template data or unsupported version
|
|
'401':
|
|
description: Authentication required
|
|
'500':
|
|
description: Failed to import template
|
|
|
|
/posters/saved:
|
|
get:
|
|
summary: Get saved posters
|
|
description: Retrieves all saved posters for the authenticated user.
|
|
tags:
|
|
- poster-saved
|
|
responses:
|
|
'200':
|
|
description: Saved posters retrieved successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
posters:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
example: 1
|
|
name:
|
|
type: string
|
|
example: 'My Custom Poster'
|
|
description:
|
|
type: string
|
|
example: 'A custom poster for my collection'
|
|
filename:
|
|
type: string
|
|
example: 'poster-abc123.jpg'
|
|
thumbnailFilename:
|
|
type: string
|
|
example: 'thumb-abc123.jpg'
|
|
posterData:
|
|
type: object
|
|
description: 'Poster configuration data'
|
|
createdAt:
|
|
type: string
|
|
format: date-time
|
|
updatedAt:
|
|
type: string
|
|
format: date-time
|
|
'401':
|
|
description: Authentication required
|
|
'500':
|
|
description: Failed to fetch saved posters
|
|
post:
|
|
summary: Create saved poster
|
|
description: Creates a new saved poster with the provided data.
|
|
tags:
|
|
- poster-saved
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- name
|
|
- posterData
|
|
properties:
|
|
name:
|
|
type: string
|
|
example: 'My Saved Poster'
|
|
description:
|
|
type: string
|
|
example: 'Description of my poster'
|
|
posterData:
|
|
type: object
|
|
description: 'Poster configuration data'
|
|
filename:
|
|
type: string
|
|
example: 'poster-abc123.jpg'
|
|
thumbnailFilename:
|
|
type: string
|
|
example: 'thumb-abc123.jpg'
|
|
responses:
|
|
'201':
|
|
description: Saved poster created successfully
|
|
'400':
|
|
description: Poster name and data are required
|
|
'401':
|
|
description: Authentication required
|
|
'500':
|
|
description: Failed to create saved poster
|
|
|
|
/posters/saved/{id}:
|
|
put:
|
|
summary: Update saved poster
|
|
description: Updates an existing saved poster. Users can only update their own posters.
|
|
tags:
|
|
- poster-saved
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
description: Poster ID
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
description:
|
|
type: string
|
|
posterData:
|
|
type: object
|
|
filename:
|
|
type: string
|
|
thumbnailFilename:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Saved poster updated successfully
|
|
'401':
|
|
description: Authentication required
|
|
'404':
|
|
description: Poster not found
|
|
'500':
|
|
description: Failed to update saved poster
|
|
delete:
|
|
summary: Delete saved poster
|
|
description: Deletes a saved poster. Supports both database posters (integer ID) and file-based posters (string ID with 'file-' prefix). If poster is in use by collections, returns 409 unless force=true is specified. Users can only delete their own posters.
|
|
tags:
|
|
- poster-saved
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
oneOf:
|
|
- type: integer
|
|
description: Database poster ID
|
|
- type: string
|
|
pattern: '^file-.+$'
|
|
description: File-based poster ID (starts with 'file-')
|
|
description: Poster ID (integer for database posters, or string starting with 'file-' for file-based posters)
|
|
- in: query
|
|
name: force
|
|
required: false
|
|
description: If true, delete poster even if it's currently in use by collections
|
|
schema:
|
|
type: boolean
|
|
default: false
|
|
responses:
|
|
'204':
|
|
description: Saved poster deleted successfully
|
|
'401':
|
|
description: Authentication required
|
|
'404':
|
|
description: Poster not found
|
|
'409':
|
|
description: Poster is currently in use by collections
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Poster is currently in use'
|
|
inUse:
|
|
type: boolean
|
|
example: true
|
|
usedBy:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
type:
|
|
type: string
|
|
enum: [collection, preExisting]
|
|
example: 'collection'
|
|
id:
|
|
type: string
|
|
example: 'col_123'
|
|
name:
|
|
type: string
|
|
example: 'Marvel Movies'
|
|
libraryName:
|
|
type: string
|
|
example: 'Movies'
|
|
'500':
|
|
description: Failed to delete saved poster
|
|
|
|
/posters/icons/upload:
|
|
post:
|
|
summary: Upload icon/asset
|
|
description: Uploads an icon or asset file for use in poster templates.
|
|
tags:
|
|
- poster-assets
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
multipart/form-data:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- icon
|
|
properties:
|
|
icon:
|
|
type: string
|
|
format: binary
|
|
description: 'Icon file (JPEG, PNG, WebP, SVG, max 10MB)'
|
|
name:
|
|
type: string
|
|
description: 'Name for the icon'
|
|
category:
|
|
type: string
|
|
description: 'Category for the icon'
|
|
tags:
|
|
type: string
|
|
description: 'Comma-separated tags'
|
|
description:
|
|
type: string
|
|
description: 'Description of the icon'
|
|
responses:
|
|
'201':
|
|
description: Icon uploaded successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
icon:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
name:
|
|
type: string
|
|
filename:
|
|
type: string
|
|
category:
|
|
type: string
|
|
tags:
|
|
type: array
|
|
items:
|
|
type: string
|
|
description:
|
|
type: string
|
|
'400':
|
|
description: No file uploaded or invalid file type
|
|
'500':
|
|
description: Failed to upload icon
|
|
|
|
/posters/icons/download:
|
|
post:
|
|
summary: Download icon from URL
|
|
description: Downloads an icon from a URL and saves it to the system.
|
|
tags:
|
|
- poster-assets
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- url
|
|
properties:
|
|
url:
|
|
type: string
|
|
format: uri
|
|
example: 'https://example.com/icon.png'
|
|
name:
|
|
type: string
|
|
category:
|
|
type: string
|
|
tags:
|
|
type: array
|
|
items:
|
|
type: string
|
|
description:
|
|
type: string
|
|
responses:
|
|
'201':
|
|
description: Icon downloaded successfully
|
|
'400':
|
|
description: URL is required or download failed
|
|
'500':
|
|
description: Failed to download icon
|
|
|
|
/posters/icons:
|
|
get:
|
|
summary: List available icons
|
|
description: Retrieves a list of available icons with optional filtering.
|
|
tags:
|
|
- poster-assets
|
|
parameters:
|
|
- name: type
|
|
in: query
|
|
schema:
|
|
type: string
|
|
enum: [user, system]
|
|
description: Filter by icon type
|
|
- name: category
|
|
in: query
|
|
schema:
|
|
type: string
|
|
description: Filter by category
|
|
- name: tags
|
|
in: query
|
|
schema:
|
|
type: array
|
|
items:
|
|
type: string
|
|
description: Filter by tags
|
|
- name: search
|
|
in: query
|
|
schema:
|
|
type: string
|
|
description: Search in name and description
|
|
responses:
|
|
'200':
|
|
description: Icons retrieved successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
icons:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
name:
|
|
type: string
|
|
filename:
|
|
type: string
|
|
category:
|
|
type: string
|
|
tags:
|
|
type: array
|
|
items:
|
|
type: string
|
|
description:
|
|
type: string
|
|
type:
|
|
type: string
|
|
enum: [user, system]
|
|
'500':
|
|
description: Failed to list icons
|
|
|
|
/fonts:
|
|
get:
|
|
summary: Get available system fonts
|
|
description: Retrieves all available font families from the system for use in poster templates.
|
|
tags:
|
|
- poster-assets
|
|
responses:
|
|
'200':
|
|
description: Fonts retrieved successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
fonts:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
family:
|
|
type: string
|
|
example: DejaVu Sans
|
|
availableWeights:
|
|
type: array
|
|
items:
|
|
type: string
|
|
example: ['Regular', 'Bold', 'Light', 'Medium']
|
|
cssValue:
|
|
type: string
|
|
example: "'DejaVu Sans'"
|
|
fontUrl:
|
|
type: string
|
|
description: URL to font file for web loading
|
|
example: '/fonts/truetype/dejavu/DejaVuSans.ttf'
|
|
count:
|
|
type: integer
|
|
example: 25
|
|
'500':
|
|
description: Failed to retrieve fonts
|
|
/posters/icons/categories:
|
|
get:
|
|
summary: List icon categories
|
|
description: Retrieves all available icon categories with statistics.
|
|
tags:
|
|
- poster-assets
|
|
responses:
|
|
'200':
|
|
description: Categories retrieved successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
categories:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
displayName:
|
|
type: string
|
|
description:
|
|
type: string
|
|
iconCount:
|
|
type: integer
|
|
'500':
|
|
description: Failed to list icon categories
|
|
|
|
/posters/icons/{id}:
|
|
delete:
|
|
summary: Delete icon
|
|
description: Deletes an icon by ID.
|
|
tags:
|
|
- poster-assets
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
description: Icon ID
|
|
responses:
|
|
'204':
|
|
description: Icon deleted successfully
|
|
'400':
|
|
description: Icon ID is required
|
|
'404':
|
|
description: Icon not found
|
|
'500':
|
|
description: Failed to delete icon
|
|
|
|
/posters/files/{filename}:
|
|
get:
|
|
summary: Serve poster files
|
|
description: Serves poster image files by filename.
|
|
tags:
|
|
- poster-assets
|
|
parameters:
|
|
- name: filename
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
description: Poster filename
|
|
- in: query
|
|
name: v
|
|
required: false
|
|
description: Cache-busting version parameter (typically file modification timestamp)
|
|
schema:
|
|
type: number
|
|
responses:
|
|
'200':
|
|
description: Poster image served successfully
|
|
content:
|
|
image/jpeg:
|
|
schema:
|
|
type: string
|
|
format: binary
|
|
'400':
|
|
description: Filename is required
|
|
'404':
|
|
description: Poster file not found
|
|
'500':
|
|
description: Failed to serve poster file
|
|
|
|
/posters/thumbnails/{filename}:
|
|
get:
|
|
summary: Serve thumbnail files
|
|
description: Serves poster thumbnail files by filename.
|
|
tags:
|
|
- poster-assets
|
|
parameters:
|
|
- name: filename
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
description: Thumbnail filename
|
|
- in: query
|
|
name: v
|
|
required: false
|
|
description: Cache-busting version parameter (typically file modification timestamp)
|
|
schema:
|
|
type: number
|
|
responses:
|
|
'200':
|
|
description: Thumbnail image served successfully
|
|
content:
|
|
image/jpeg:
|
|
schema:
|
|
type: string
|
|
format: binary
|
|
'400':
|
|
description: Filename is required
|
|
'404':
|
|
description: Thumbnail not found
|
|
'500':
|
|
description: Failed to serve thumbnail file
|
|
|
|
/posters/icons/{type}/{filename}:
|
|
get:
|
|
summary: Serve icon files
|
|
description: Serves icon files by type and filename.
|
|
tags:
|
|
- poster-assets
|
|
parameters:
|
|
- name: type
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
enum: [user, system]
|
|
description: Icon type
|
|
- name: filename
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
description: Icon filename
|
|
responses:
|
|
'200':
|
|
description: Icon file served successfully
|
|
content:
|
|
image/*:
|
|
schema:
|
|
type: string
|
|
format: binary
|
|
'400':
|
|
description: Invalid icon type or filename required
|
|
'404':
|
|
description: Icon file not found
|
|
'500':
|
|
description: Failed to serve icon file
|
|
|
|
/source-colors:
|
|
get:
|
|
summary: Get all source colors
|
|
description: Retrieves all source color mappings (database + defaults) for poster generation.
|
|
tags:
|
|
- source-colors
|
|
responses:
|
|
'200':
|
|
description: Source colors retrieved successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
additionalProperties:
|
|
type: object
|
|
properties:
|
|
primaryColor:
|
|
type: string
|
|
example: '#01b4e4'
|
|
secondaryColor:
|
|
type: string
|
|
example: '#0d253f'
|
|
textColor:
|
|
type: string
|
|
example: '#ffffff'
|
|
example:
|
|
tmdb:
|
|
primaryColor: '#01b4e4'
|
|
secondaryColor: '#0d253f'
|
|
textColor: '#ffffff'
|
|
trakt:
|
|
primaryColor: '#ed2224'
|
|
secondaryColor: '#1f1a1a'
|
|
textColor: '#ffffff'
|
|
mdblist:
|
|
primaryColor: '#4283c9'
|
|
secondaryColor: '#1a2e42'
|
|
textColor: '#ffffff'
|
|
'500':
|
|
description: Failed to get source colors
|
|
|
|
/source-colors/{sourceType}:
|
|
get:
|
|
summary: Get specific source color scheme
|
|
description: Retrieves color scheme for a specific source type.
|
|
tags:
|
|
- source-colors
|
|
parameters:
|
|
- name: sourceType
|
|
in: path
|
|
required: true
|
|
description: The type of source (e.g., 'trakt', 'imdb', 'letterboxd').
|
|
schema:
|
|
type: string
|
|
example: tmdb
|
|
responses:
|
|
'200':
|
|
description: Source color scheme retrieved successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
primaryColor:
|
|
type: string
|
|
example: '#01b4e4'
|
|
secondaryColor:
|
|
type: string
|
|
example: '#0d253f'
|
|
textColor:
|
|
type: string
|
|
example: '#ffffff'
|
|
'500':
|
|
description: Failed to get source colors
|
|
|
|
put:
|
|
summary: Update source colors
|
|
description: Updates color scheme for a specific source type. This affects all templates using source colors.
|
|
tags:
|
|
- source-colors
|
|
parameters:
|
|
- name: sourceType
|
|
in: path
|
|
required: true
|
|
description: The type of source (e.g., 'trakt', 'imdb', 'letterboxd').
|
|
schema:
|
|
type: string
|
|
example: tmdb
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- primaryColor
|
|
- secondaryColor
|
|
- textColor
|
|
properties:
|
|
primaryColor:
|
|
type: string
|
|
pattern: '^#[0-9a-fA-F]{6}$'
|
|
example: '#01b4e4'
|
|
secondaryColor:
|
|
type: string
|
|
pattern: '^#[0-9a-fA-F]{6}$'
|
|
example: '#0d253f'
|
|
textColor:
|
|
type: string
|
|
pattern: '^#[0-9a-fA-F]{6}$'
|
|
example: '#ffffff'
|
|
responses:
|
|
'200':
|
|
description: Source colors updated successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: 'Source colors updated for tmdb'
|
|
colors:
|
|
type: object
|
|
properties:
|
|
primaryColor:
|
|
type: string
|
|
example: '#01b4e4'
|
|
secondaryColor:
|
|
type: string
|
|
example: '#0d253f'
|
|
textColor:
|
|
type: string
|
|
example: '#ffffff'
|
|
'400':
|
|
description: Invalid input - missing fields or invalid hex colors
|
|
'500':
|
|
description: Failed to update source colors
|
|
|
|
delete:
|
|
summary: Reset source colors to defaults
|
|
description: Resets the specified source type colors to system defaults.
|
|
tags:
|
|
- source-colors
|
|
parameters:
|
|
- name: sourceType
|
|
in: path
|
|
required: true
|
|
description: The type of source (e.g., 'trakt', 'imdb', 'letterboxd').
|
|
schema:
|
|
type: string
|
|
example: tmdb
|
|
responses:
|
|
'200':
|
|
description: Source colors reset successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: 'Source colors reset to defaults for tmdb'
|
|
colors:
|
|
type: object
|
|
properties:
|
|
primaryColor:
|
|
type: string
|
|
example: '#01b4e4'
|
|
secondaryColor:
|
|
type: string
|
|
example: '#0d253f'
|
|
textColor:
|
|
type: string
|
|
example: '#ffffff'
|
|
'500':
|
|
description: Failed to reset source colors
|
|
|
|
/source-colors/reset:
|
|
post:
|
|
summary: Reset all source colors to defaults
|
|
description: Resets all source color customizations back to system defaults.
|
|
tags:
|
|
- source-colors
|
|
responses:
|
|
'200':
|
|
description: All source colors reset successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: 'All source colors reset to defaults'
|
|
colors:
|
|
type: object
|
|
additionalProperties:
|
|
type: object
|
|
properties:
|
|
primaryColor:
|
|
type: string
|
|
secondaryColor:
|
|
type: string
|
|
textColor:
|
|
type: string
|
|
'500':
|
|
description: Failed to reset source colors
|
|
|
|
/source-colors/export:
|
|
get:
|
|
summary: Export source colors as JSON
|
|
description: Exports all source color schemes as a downloadable JSON file for sharing.
|
|
tags:
|
|
- source-colors
|
|
responses:
|
|
'200':
|
|
description: Source colors exported successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
sourceColors:
|
|
type: object
|
|
additionalProperties:
|
|
type: object
|
|
properties:
|
|
primaryColor:
|
|
type: string
|
|
example: '#ed2224'
|
|
secondaryColor:
|
|
type: string
|
|
example: '#1f1a1a'
|
|
textColor:
|
|
type: string
|
|
example: '#ffffff'
|
|
exportedAt:
|
|
type: string
|
|
format: date-time
|
|
example: '2023-10-25T10:30:00.000Z'
|
|
version:
|
|
type: string
|
|
example: '1.0'
|
|
'500':
|
|
description: Failed to export source colors
|
|
|
|
/source-colors/import:
|
|
post:
|
|
summary: Import source colors from JSON
|
|
description: Imports source color schemes from a JSON file exported from Agregarr.
|
|
tags:
|
|
- source-colors
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- sourceColors
|
|
properties:
|
|
sourceColors:
|
|
type: object
|
|
additionalProperties:
|
|
type: object
|
|
properties:
|
|
primaryColor:
|
|
type: string
|
|
example: '#ed2224'
|
|
secondaryColor:
|
|
type: string
|
|
example: '#1f1a1a'
|
|
textColor:
|
|
type: string
|
|
example: '#ffffff'
|
|
version:
|
|
type: string
|
|
example: '1.0'
|
|
responses:
|
|
'200':
|
|
description: Source colors imported successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: 'Successfully imported 5 source color schemes'
|
|
importCount:
|
|
type: integer
|
|
example: 5
|
|
sourceColors:
|
|
type: object
|
|
additionalProperties:
|
|
type: object
|
|
properties:
|
|
primaryColor:
|
|
type: string
|
|
secondaryColor:
|
|
type: string
|
|
textColor:
|
|
type: string
|
|
'400':
|
|
description: Invalid source colors data or unsupported version
|
|
'401':
|
|
description: Authentication required
|
|
'500':
|
|
description: Failed to import source colors
|
|
|
|
/overlay-templates:
|
|
get:
|
|
summary: Get all overlay templates
|
|
description: Retrieves all active overlay templates including system presets and user-created templates.
|
|
tags:
|
|
- overlays
|
|
responses:
|
|
'200':
|
|
description: Overlay templates retrieved successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
templates:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/OverlayTemplate'
|
|
'401':
|
|
description: Authentication required
|
|
'500':
|
|
description: Failed to fetch overlay templates
|
|
|
|
post:
|
|
summary: Create overlay template
|
|
description: Creates a new overlay template with layered design elements.
|
|
tags:
|
|
- overlays
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
example: 'My Custom Badge'
|
|
description:
|
|
type: string
|
|
example: 'Custom rating badge'
|
|
type:
|
|
type: string
|
|
enum: ['rating', 'metadata', 'technical', 'status', 'generic']
|
|
example: 'rating'
|
|
templateData:
|
|
type: object
|
|
description: 'Template design data with states containing elements'
|
|
required:
|
|
- name
|
|
- type
|
|
- templateData
|
|
responses:
|
|
'201':
|
|
description: Template created successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/OverlayTemplate'
|
|
'400':
|
|
description: Invalid request body
|
|
'401':
|
|
description: Authentication required
|
|
'500':
|
|
description: Failed to create template
|
|
|
|
/overlay-templates/{id}:
|
|
put:
|
|
summary: Update overlay template
|
|
description: Updates an existing overlay template (cannot edit system presets).
|
|
tags:
|
|
- overlays
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
description: Template ID
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
description:
|
|
type: string
|
|
type:
|
|
type: string
|
|
enum: ['rating', 'metadata', 'technical', 'status', 'generic']
|
|
templateData:
|
|
type: object
|
|
responses:
|
|
'200':
|
|
description: Template updated successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/OverlayTemplate'
|
|
'400':
|
|
description: Invalid request body
|
|
'401':
|
|
description: Authentication required
|
|
'403':
|
|
description: Cannot edit system default templates
|
|
'404':
|
|
description: Template not found
|
|
'500':
|
|
description: Failed to update template
|
|
|
|
delete:
|
|
summary: Delete overlay template
|
|
description: Soft-deletes an overlay template (cannot delete system presets).
|
|
tags:
|
|
- overlays
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
description: Template ID
|
|
responses:
|
|
'200':
|
|
description: Template deleted successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: 'Template deleted successfully'
|
|
'401':
|
|
description: Authentication required
|
|
'403':
|
|
description: Cannot delete system default templates
|
|
'404':
|
|
description: Template not found
|
|
'500':
|
|
description: Failed to delete template
|
|
|
|
/overlay-templates/{id}/preview:
|
|
get:
|
|
summary: Generate template preview
|
|
description: Renders the overlay template on a random sample poster and returns the preview image.
|
|
tags:
|
|
- overlays
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
description: Template ID
|
|
responses:
|
|
'200':
|
|
description: Preview image generated successfully
|
|
content:
|
|
image/webp:
|
|
schema:
|
|
type: string
|
|
format: binary
|
|
'404':
|
|
description: Template not found
|
|
'500':
|
|
description: Failed to generate preview
|
|
|
|
/overlay-templates/combined-preview:
|
|
post:
|
|
summary: Generate combined preview with multiple overlays
|
|
description: Renders multiple overlay templates on a single poster in layer order and returns the combined preview image.
|
|
tags:
|
|
- overlays
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- templateIds
|
|
properties:
|
|
templateIds:
|
|
type: array
|
|
items:
|
|
type: integer
|
|
description: Array of template IDs to render in order
|
|
example: [1, 2, 3]
|
|
responses:
|
|
'200':
|
|
description: Combined preview image generated successfully
|
|
content:
|
|
image/webp:
|
|
schema:
|
|
type: string
|
|
format: binary
|
|
'400':
|
|
description: Invalid request - templateIds array required
|
|
'404':
|
|
description: No templates found
|
|
'500':
|
|
description: Failed to generate combined preview
|
|
|
|
/overlay-templates/presets/create:
|
|
post:
|
|
summary: Create preset templates
|
|
description: Manually trigger creation of system preset overlay templates (normally done on startup).
|
|
tags:
|
|
- overlays
|
|
responses:
|
|
'200':
|
|
description: Preset templates created successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: 'Preset templates created successfully'
|
|
'401':
|
|
description: Authentication required
|
|
'500':
|
|
description: Failed to create preset templates
|
|
|
|
/overlay-templates/copy:
|
|
post:
|
|
summary: Copy template design
|
|
description: Copy the visual design from one template to multiple target templates.
|
|
tags:
|
|
- overlays
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- sourceTemplateId
|
|
- targetTemplateIds
|
|
properties:
|
|
sourceTemplateId:
|
|
type: number
|
|
description: ID of the template to copy from
|
|
targetTemplateIds:
|
|
type: array
|
|
items:
|
|
type: number
|
|
description: Array of template IDs to copy to
|
|
responses:
|
|
'200':
|
|
description: Design copied successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
copiedCount:
|
|
type: number
|
|
'400':
|
|
description: Invalid request
|
|
'401':
|
|
description: Authentication required
|
|
'404':
|
|
description: Source template not found
|
|
'500':
|
|
description: Failed to copy template design
|
|
|
|
/overlay-templates/bulk-edit:
|
|
post:
|
|
summary: Bulk edit template properties
|
|
description: Apply property changes to multiple templates at once.
|
|
tags:
|
|
- overlays
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- templateIds
|
|
- properties
|
|
properties:
|
|
templateIds:
|
|
type: array
|
|
items:
|
|
type: number
|
|
description: Array of template IDs to update
|
|
properties:
|
|
type: object
|
|
description: Properties to apply to all templates
|
|
properties:
|
|
fontFamily:
|
|
type: string
|
|
fontSize:
|
|
type: number
|
|
fontWeight:
|
|
type: string
|
|
enum: [normal, bold]
|
|
fillColor:
|
|
type: string
|
|
textColor:
|
|
type: string
|
|
borderRadius:
|
|
type: number
|
|
opacity:
|
|
type: number
|
|
responses:
|
|
'200':
|
|
description: Templates updated successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
updatedCount:
|
|
type: number
|
|
'400':
|
|
description: Invalid request
|
|
'401':
|
|
description: Authentication required
|
|
'500':
|
|
description: Failed to bulk edit templates
|
|
|
|
/overlay-templates/preview-posters:
|
|
get:
|
|
summary: List available preview posters
|
|
description: Returns a list of all available preview posters for overlay template editing.
|
|
tags:
|
|
- overlays
|
|
responses:
|
|
'200':
|
|
description: Preview posters listed successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
posters:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
example: 'movie_550'
|
|
type:
|
|
type: string
|
|
enum: ['movie', 'tv']
|
|
example: 'movie'
|
|
tmdbId:
|
|
type: integer
|
|
example: 550
|
|
filename:
|
|
type: string
|
|
example: 'movie_550.jpg'
|
|
url:
|
|
type: string
|
|
example: '/preview-posters/movie_550.jpg'
|
|
count:
|
|
type: integer
|
|
example: 102
|
|
'401':
|
|
description: Authentication required
|
|
'500':
|
|
description: Failed to list preview posters
|
|
|
|
/overlay-templates/preview-metadata/{posterId}:
|
|
get:
|
|
summary: Get real metadata for preview poster
|
|
description: Fetches actual metadata (title, year, ratings, etc.) from TMDb/IMDb for a specific preview poster.
|
|
tags:
|
|
- overlays
|
|
parameters:
|
|
- name: posterId
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
description: Poster ID in format movie_123 or tv_456
|
|
example: 'movie_550'
|
|
responses:
|
|
'200':
|
|
description: Metadata retrieved successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
title:
|
|
type: string
|
|
example: 'Fight Club'
|
|
year:
|
|
type: integer
|
|
example: 1999
|
|
imdbRating:
|
|
type: number
|
|
example: 8.8
|
|
rtCriticsScore:
|
|
type: integer
|
|
example: 79
|
|
rtAudienceScore:
|
|
type: integer
|
|
example: 96
|
|
director:
|
|
type: string
|
|
example: 'David Fincher'
|
|
studio:
|
|
type: string
|
|
example: '20th Century Fox'
|
|
network:
|
|
type: string
|
|
example: 'AMC'
|
|
resolution:
|
|
type: string
|
|
example: '4K'
|
|
audioFormat:
|
|
type: string
|
|
example: 'Dolby Atmos'
|
|
videoCodec:
|
|
type: string
|
|
example: 'HEVC'
|
|
status:
|
|
type: string
|
|
example: 'Available'
|
|
releaseDate:
|
|
type: string
|
|
example: '1999-10-15'
|
|
runtime:
|
|
type: integer
|
|
example: 139
|
|
daysUntilAction:
|
|
type: integer
|
|
example: 5
|
|
description: 'Days until Maintainerr takes action on this item (negative = overdue)'
|
|
'400':
|
|
description: Invalid poster ID format
|
|
'401':
|
|
description: Authentication required
|
|
'500':
|
|
description: Failed to fetch preview poster metadata
|
|
|
|
/overlay-library-configs:
|
|
get:
|
|
summary: Get all library configurations
|
|
description: Retrieves overlay configurations for all libraries.
|
|
tags:
|
|
- overlays
|
|
responses:
|
|
'200':
|
|
description: Library configurations retrieved successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
configs:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/OverlayLibraryConfig'
|
|
'401':
|
|
description: Authentication required
|
|
'500':
|
|
description: Failed to fetch library configs
|
|
|
|
/overlay-library-configs/{libraryId}:
|
|
get:
|
|
summary: Get library configuration
|
|
description: Retrieves overlay configuration for a specific library.
|
|
tags:
|
|
- overlays
|
|
parameters:
|
|
- name: libraryId
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
description: Plex library ID
|
|
responses:
|
|
'200':
|
|
description: Library configuration retrieved successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/OverlayLibraryConfig'
|
|
'401':
|
|
description: Authentication required
|
|
'500':
|
|
description: Failed to fetch library config
|
|
|
|
post:
|
|
summary: Create or update library configuration
|
|
description: Configures which overlay templates are applied to a library.
|
|
tags:
|
|
- overlays
|
|
parameters:
|
|
- name: libraryId
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
description: Plex library ID
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
libraryName:
|
|
type: string
|
|
example: 'Movies'
|
|
mediaType:
|
|
type: string
|
|
enum: ['movie', 'show']
|
|
example: 'movie'
|
|
enabledOverlays:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
templateId:
|
|
type: integer
|
|
enabled:
|
|
type: boolean
|
|
layerOrder:
|
|
type: integer
|
|
config:
|
|
type: object
|
|
description: Optional per-overlay configuration
|
|
properties:
|
|
daysThreshold:
|
|
type: number
|
|
description: For Coming Soon overlays - show if days until release is less than this
|
|
timeWindowDays:
|
|
type: number
|
|
description: For New Release badge - show for X days after download
|
|
minimumRating:
|
|
type: number
|
|
description: For rating badges - minimum rating to display
|
|
tmdbLanguage:
|
|
type: string
|
|
nullable: true
|
|
description: ISO language code for TMDB poster metadata (e.g., en, fr, pt-BR). If not set, uses global setting.
|
|
example: 'en'
|
|
required:
|
|
- libraryName
|
|
- mediaType
|
|
- enabledOverlays
|
|
responses:
|
|
'200':
|
|
description: Library configuration saved successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/OverlayLibraryConfig'
|
|
'400':
|
|
description: Invalid request body
|
|
'401':
|
|
description: Authentication required
|
|
'500':
|
|
description: Failed to save library config
|
|
|
|
delete:
|
|
summary: Delete library configuration
|
|
description: Removes overlay configuration for a library.
|
|
tags:
|
|
- overlays
|
|
parameters:
|
|
- name: libraryId
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
description: Plex library ID
|
|
responses:
|
|
'200':
|
|
description: Configuration deleted successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: 'Configuration deleted successfully'
|
|
'401':
|
|
description: Authentication required
|
|
'404':
|
|
description: Configuration not found
|
|
'500':
|
|
description: Failed to delete configuration
|
|
|
|
/overlay-library-configs/{libraryId}/apply:
|
|
post:
|
|
summary: Apply overlays to library
|
|
description: Applies configured overlay templates to all posters in a library (runs asynchronously).
|
|
tags:
|
|
- overlays
|
|
parameters:
|
|
- name: libraryId
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
description: Plex library ID
|
|
responses:
|
|
'202':
|
|
description: Overlay application started (runs in background)
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: 'Overlay application started'
|
|
libraryId:
|
|
type: string
|
|
example: '1'
|
|
'401':
|
|
description: Authentication required
|
|
'409':
|
|
description: Conflict - another overlay operation is already running
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: 'Full overlay sync is currently running. Please wait for it to complete or cancel it before syncing individual libraries.'
|
|
conflictType:
|
|
type: string
|
|
enum: [full-sync-running, library-already-running]
|
|
example: 'full-sync-running'
|
|
'500':
|
|
description: Failed to start overlay application
|
|
|
|
/overlay-library-configs/{libraryId}/status:
|
|
get:
|
|
summary: Get overlay application status for library
|
|
description: Returns the current status of overlay application for a specific library.
|
|
tags:
|
|
- overlays
|
|
parameters:
|
|
- name: libraryId
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
description: Plex library ID
|
|
responses:
|
|
'200':
|
|
description: Status retrieved successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
running:
|
|
type: boolean
|
|
description: Whether overlay application is running for this library
|
|
example: true
|
|
libraryName:
|
|
type: string
|
|
description: Name of the library (only present if running)
|
|
example: 'Movies'
|
|
startTime:
|
|
type: number
|
|
description: Timestamp when the job started (only present if running)
|
|
example: 1640000000000
|
|
|
|
/overlay-library-configs/status/all:
|
|
get:
|
|
summary: Get all running library overlay operations
|
|
description: Returns a list of all libraries currently running overlay application.
|
|
tags:
|
|
- overlays
|
|
responses:
|
|
'200':
|
|
description: Running libraries retrieved successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
runningLibraries:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
libraryId:
|
|
type: string
|
|
example: '1'
|
|
libraryName:
|
|
type: string
|
|
example: 'Movies'
|
|
startTime:
|
|
type: number
|
|
example: 1640000000000
|
|
|
|
/overlay-settings:
|
|
get:
|
|
summary: Get overlay settings
|
|
description: Get global overlay system settings including poster source preference.
|
|
tags:
|
|
- overlays
|
|
responses:
|
|
'200':
|
|
description: Overlay settings retrieved
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
defaultPosterSource:
|
|
type: string
|
|
enum: [tmdb, plex, local]
|
|
description: Default poster source for overlays
|
|
example: 'tmdb'
|
|
initialSetupComplete:
|
|
type: boolean
|
|
description: Whether initial setup wizard has been completed
|
|
example: false
|
|
'401':
|
|
description: Authentication required
|
|
put:
|
|
summary: Update overlay settings
|
|
description: Update global overlay system settings.
|
|
tags:
|
|
- overlays
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- defaultPosterSource
|
|
properties:
|
|
defaultPosterSource:
|
|
type: string
|
|
enum: [tmdb, plex, local]
|
|
description: Default poster source for overlays
|
|
example: 'tmdb'
|
|
responses:
|
|
'200':
|
|
description: Settings updated successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
defaultPosterSource:
|
|
type: string
|
|
enum: [tmdb, plex, local]
|
|
initialSetupComplete:
|
|
type: boolean
|
|
'400':
|
|
description: Invalid poster source
|
|
'401':
|
|
description: Authentication required
|
|
|
|
/overlay-settings/download-base-posters:
|
|
post:
|
|
summary: Download base posters from Plex
|
|
description: Starts a background job to download all base posters from Plex libraries for overlay processing. Only used when poster source is set to 'plex'.
|
|
tags:
|
|
- overlays
|
|
responses:
|
|
'202':
|
|
description: Download job started
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: 'Base poster download started'
|
|
status:
|
|
type: object
|
|
properties:
|
|
running:
|
|
type: boolean
|
|
cancelled:
|
|
type: boolean
|
|
libraries:
|
|
type: object
|
|
overallProgress:
|
|
type: object
|
|
properties:
|
|
current:
|
|
type: number
|
|
total:
|
|
type: number
|
|
failed:
|
|
type: number
|
|
percentage:
|
|
type: number
|
|
'401':
|
|
description: Authentication required
|
|
'409':
|
|
description: Download job already running or overlay application is running
|
|
|
|
/overlay-settings/download-status:
|
|
get:
|
|
summary: Get download job status
|
|
description: Get the current status of the base poster download job including progress per library.
|
|
tags:
|
|
- overlays
|
|
responses:
|
|
'200':
|
|
description: Download status retrieved
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
running:
|
|
type: boolean
|
|
cancelled:
|
|
type: boolean
|
|
libraries:
|
|
type: object
|
|
additionalProperties:
|
|
type: object
|
|
properties:
|
|
libraryName:
|
|
type: string
|
|
current:
|
|
type: number
|
|
total:
|
|
type: number
|
|
failed:
|
|
type: number
|
|
overallProgress:
|
|
type: object
|
|
properties:
|
|
current:
|
|
type: number
|
|
total:
|
|
type: number
|
|
failed:
|
|
type: number
|
|
percentage:
|
|
type: number
|
|
'401':
|
|
description: Authentication required
|
|
|
|
/overlay-settings/cancel-download:
|
|
post:
|
|
summary: Cancel download job
|
|
description: Requests cancellation of the currently running base poster download job.
|
|
tags:
|
|
- overlays
|
|
responses:
|
|
'200':
|
|
description: Cancellation requested
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: 'Download job cancellation requested'
|
|
'400':
|
|
description: No download job running
|
|
'401':
|
|
description: Authentication required
|
|
|
|
/overlay-settings/reset-library-posters:
|
|
post:
|
|
summary: Reset all posters in a library
|
|
description: Starts a background job to reset all posters in a specified library to their base versions (without overlays). Respects the configured poster source setting.
|
|
tags:
|
|
- overlays
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- libraryId
|
|
properties:
|
|
libraryId:
|
|
type: string
|
|
description: The Plex library ID to reset posters for
|
|
example: '1'
|
|
responses:
|
|
'202':
|
|
description: Poster reset job started
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: 'Poster reset started'
|
|
status:
|
|
type: object
|
|
properties:
|
|
running:
|
|
type: boolean
|
|
cancelled:
|
|
type: boolean
|
|
currentLibrary:
|
|
type: string
|
|
currentLibraryName:
|
|
type: string
|
|
current:
|
|
type: number
|
|
total:
|
|
type: number
|
|
failed:
|
|
type: number
|
|
'400':
|
|
description: Library ID not provided
|
|
'401':
|
|
description: Authentication required
|
|
'409':
|
|
description: Reset job already running, or overlay application/download is running
|
|
|
|
/overlay-settings/reset-status:
|
|
get:
|
|
summary: Get poster reset job status
|
|
description: Get the current status of the poster reset job including progress.
|
|
tags:
|
|
- overlays
|
|
responses:
|
|
'200':
|
|
description: Reset status retrieved
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
running:
|
|
type: boolean
|
|
description: Whether the reset job is currently running
|
|
cancelled:
|
|
type: boolean
|
|
description: Whether the reset job was cancelled
|
|
currentLibrary:
|
|
type: string
|
|
description: Current library ID being processed
|
|
currentLibraryName:
|
|
type: string
|
|
description: Current library name being processed
|
|
current:
|
|
type: number
|
|
description: Number of items processed
|
|
total:
|
|
type: number
|
|
description: Total number of items to process
|
|
failed:
|
|
type: number
|
|
description: Number of items that failed to reset
|
|
'401':
|
|
description: Authentication required
|
|
|
|
/overlay-settings/cancel-reset:
|
|
post:
|
|
summary: Cancel poster reset job
|
|
description: Requests cancellation of the currently running poster reset job.
|
|
tags:
|
|
- overlays
|
|
responses:
|
|
'200':
|
|
description: Cancellation requested
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: 'Poster reset cancellation requested'
|
|
'400':
|
|
description: No reset job running
|
|
'401':
|
|
description: Authentication required
|
|
|
|
/overlay-settings/generate-local-folders:
|
|
post:
|
|
summary: Generate local poster folder structure
|
|
description: Creates empty folder structure for local posters. Creates folders for all library items in the format /config/plex-base-posters/{LibraryName}-{ID}/{Title} ({Year}) tmdb-{TMDBID}/. Note that folders are also created automatically when overlays are applied, so this is mainly useful for bulk folder creation upfront.
|
|
tags:
|
|
- overlays
|
|
responses:
|
|
'202':
|
|
description: Folder generation started
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: 'Folder generation started'
|
|
status:
|
|
type: object
|
|
properties:
|
|
running:
|
|
type: boolean
|
|
cancelled:
|
|
type: boolean
|
|
libraries:
|
|
type: object
|
|
overallProgress:
|
|
type: object
|
|
properties:
|
|
current:
|
|
type: number
|
|
total:
|
|
type: number
|
|
failed:
|
|
type: number
|
|
skipped:
|
|
type: number
|
|
description: Items skipped due to missing TMDB ID
|
|
percentage:
|
|
type: number
|
|
'409':
|
|
description: Folder generation already running or overlay application is running
|
|
'401':
|
|
description: Authentication required
|
|
|
|
/overlay-settings/generate-local-folders-status:
|
|
get:
|
|
summary: Get folder generation status
|
|
description: Returns the current status of the folder generation job.
|
|
tags:
|
|
- overlays
|
|
responses:
|
|
'200':
|
|
description: Folder generation status
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
running:
|
|
type: boolean
|
|
cancelled:
|
|
type: boolean
|
|
libraries:
|
|
type: object
|
|
additionalProperties:
|
|
type: object
|
|
properties:
|
|
libraryName:
|
|
type: string
|
|
current:
|
|
type: number
|
|
total:
|
|
type: number
|
|
failed:
|
|
type: number
|
|
skipped:
|
|
type: number
|
|
overallProgress:
|
|
type: object
|
|
properties:
|
|
current:
|
|
type: number
|
|
total:
|
|
type: number
|
|
failed:
|
|
type: number
|
|
skipped:
|
|
type: number
|
|
percentage:
|
|
type: number
|
|
'401':
|
|
description: Authentication required
|
|
|
|
/overlay-settings/cancel-generate-local-folders:
|
|
post:
|
|
summary: Cancel folder generation
|
|
description: Requests cancellation of the currently running folder generation job.
|
|
tags:
|
|
- overlays
|
|
responses:
|
|
'200':
|
|
description: Cancellation requested
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: 'Folder generation cancellation requested'
|
|
'400':
|
|
description: No folder generation running
|
|
'401':
|
|
description: Authentication required
|
|
|
|
/overlay-settings/populate-local-from-plex:
|
|
post:
|
|
summary: Populate local folders with Plex posters
|
|
description: Downloads all current Plex posters and saves them to the local poster folder structure. Great for migrating from Plex posters to local posters.
|
|
tags:
|
|
- overlays
|
|
responses:
|
|
'202':
|
|
description: Plex poster population started
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: 'Plex poster population started'
|
|
status:
|
|
type: object
|
|
properties:
|
|
running:
|
|
type: boolean
|
|
cancelled:
|
|
type: boolean
|
|
libraries:
|
|
type: object
|
|
overallProgress:
|
|
type: object
|
|
properties:
|
|
current:
|
|
type: number
|
|
total:
|
|
type: number
|
|
failed:
|
|
type: number
|
|
skipped:
|
|
type: number
|
|
description: Items skipped due to missing TMDB ID or poster URL
|
|
percentage:
|
|
type: number
|
|
'409':
|
|
description: Plex poster population already running or overlay application is running
|
|
'401':
|
|
description: Authentication required
|
|
|
|
/overlay-settings/populate-local-from-plex-status:
|
|
get:
|
|
summary: Get Plex poster population status
|
|
description: Returns the current status of the Plex poster population job.
|
|
tags:
|
|
- overlays
|
|
responses:
|
|
'200':
|
|
description: Plex poster population status
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
running:
|
|
type: boolean
|
|
cancelled:
|
|
type: boolean
|
|
libraries:
|
|
type: object
|
|
additionalProperties:
|
|
type: object
|
|
properties:
|
|
libraryName:
|
|
type: string
|
|
current:
|
|
type: number
|
|
total:
|
|
type: number
|
|
failed:
|
|
type: number
|
|
skipped:
|
|
type: number
|
|
overallProgress:
|
|
type: object
|
|
properties:
|
|
current:
|
|
type: number
|
|
total:
|
|
type: number
|
|
failed:
|
|
type: number
|
|
skipped:
|
|
type: number
|
|
percentage:
|
|
type: number
|
|
'401':
|
|
description: Authentication required
|
|
|
|
/overlay-settings/cancel-populate-local-from-plex:
|
|
post:
|
|
summary: Cancel Plex poster population
|
|
description: Requests cancellation of the currently running Plex poster population job.
|
|
tags:
|
|
- overlays
|
|
responses:
|
|
'200':
|
|
description: Cancellation requested
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
example: 'Plex poster population cancellation requested'
|
|
'400':
|
|
description: No Plex poster population running
|
|
'401':
|
|
description: Authentication required
|
|
|
|
/plex/search:
|
|
get:
|
|
summary: Search Plex libraries
|
|
description: Search across all Plex libraries for movies and TV shows.
|
|
tags:
|
|
- overlays
|
|
parameters:
|
|
- in: query
|
|
name: query
|
|
required: true
|
|
allowReserved: true
|
|
schema:
|
|
type: string
|
|
description: Search term
|
|
example: 'Inception'
|
|
- in: query
|
|
name: limit
|
|
required: false
|
|
schema:
|
|
type: integer
|
|
default: 20
|
|
description: Maximum number of results to return
|
|
example: 20
|
|
responses:
|
|
'200':
|
|
description: Search results
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
results:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
ratingKey:
|
|
type: string
|
|
example: '12345'
|
|
title:
|
|
type: string
|
|
example: 'Inception'
|
|
year:
|
|
type: integer
|
|
example: 2010
|
|
type:
|
|
type: string
|
|
enum: [movie, show]
|
|
example: 'movie'
|
|
thumb:
|
|
type: string
|
|
example: '/library/metadata/12345/thumb/1234567890'
|
|
libraryId:
|
|
type: string
|
|
example: '1'
|
|
libraryName:
|
|
type: string
|
|
example: 'Movies'
|
|
totalResults:
|
|
type: integer
|
|
example: 5
|
|
'400':
|
|
description: Query parameter is required
|
|
'401':
|
|
description: Authentication required
|
|
'500':
|
|
description: Failed to search Plex
|
|
|
|
/overlay-test:
|
|
post:
|
|
summary: Test overlay application on a single item
|
|
description: Test how overlays would be applied to a specific Plex item, returning the rendered poster with detailed debugging information including template matches, condition evaluation, and context variables.
|
|
tags:
|
|
- overlays
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- ratingKey
|
|
properties:
|
|
ratingKey:
|
|
type: string
|
|
description: Plex rating key of the item to test
|
|
example: '12345'
|
|
responses:
|
|
'200':
|
|
description: Overlay test completed successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
poster:
|
|
type: string
|
|
format: byte
|
|
description: Base64-encoded WebP image of the poster with overlays applied
|
|
item:
|
|
type: object
|
|
properties:
|
|
ratingKey:
|
|
type: string
|
|
example: '12345'
|
|
title:
|
|
type: string
|
|
example: 'Inception'
|
|
year:
|
|
type: integer
|
|
example: 2010
|
|
type:
|
|
type: string
|
|
enum: [movie, show]
|
|
example: 'movie'
|
|
libraryId:
|
|
type: string
|
|
example: '1'
|
|
libraryName:
|
|
type: string
|
|
example: 'Movies'
|
|
templates:
|
|
type: array
|
|
description: All enabled templates for the library with match results
|
|
items:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
example: 1
|
|
name:
|
|
type: string
|
|
example: 'IMDb Rating Badge'
|
|
matched:
|
|
type: boolean
|
|
description: Whether this template's conditions were met
|
|
example: true
|
|
conditionResults:
|
|
type: object
|
|
description: Detailed condition evaluation for debugging
|
|
properties:
|
|
sectionResults:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
sectionIndex:
|
|
type: integer
|
|
sectionOperator:
|
|
type: string
|
|
enum: [and, or]
|
|
matched:
|
|
type: boolean
|
|
ruleResults:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
ruleIndex:
|
|
type: integer
|
|
ruleOperator:
|
|
type: string
|
|
enum: [and, or]
|
|
field:
|
|
type: string
|
|
example: 'imdbRating'
|
|
operator:
|
|
type: string
|
|
example: 'gte'
|
|
value:
|
|
description: Expected value
|
|
actualValue:
|
|
description: Actual value from context
|
|
matched:
|
|
type: boolean
|
|
context:
|
|
type: object
|
|
description: Context variables grouped by source
|
|
properties:
|
|
plex:
|
|
type: object
|
|
description: Plex metadata
|
|
tmdb:
|
|
type: object
|
|
description: TMDB metadata
|
|
ratings:
|
|
type: object
|
|
description: IMDb and Rotten Tomatoes ratings
|
|
monitoring:
|
|
type: object
|
|
description: Radarr/Sonarr monitoring status
|
|
computed:
|
|
type: object
|
|
description: Computed fields
|
|
'400':
|
|
description: Invalid request (missing ratingKey, no library config, item is episode/season)
|
|
'401':
|
|
description: Authentication required
|
|
'404':
|
|
description: Item not found in Plex
|
|
'500':
|
|
description: Failed to test overlay
|
|
|
|
security:
|
|
- cookieAuth: []
|
|
- apiKey: []
|