agregarr_agregarr/agregarr-api.yml
2026-01-06 19:21:46 +13:00

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: []