mirror of
https://github.com/agregarr/agregarr.git
synced 2026-05-06 18:49:44 -05:00
a40b1d9477
corrects Overseerr test only validating connection and not API key. All sources now correctly throw API key invalid errors instead of generic errors
10692 lines
333 KiB
YAML
10692 lines
333 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.
|
|
tags:
|
|
- name: public
|
|
description: Public API endpoints requiring no authentication.
|
|
- name: settings
|
|
description: Endpoints related to Agregarr's settings and configuration.
|
|
- name: auth
|
|
description: Endpoints related to logging in or out, and the currently authenticated user.
|
|
- name: users
|
|
description: Endpoints related to user management.
|
|
- name: search
|
|
description: Endpoints related to search and discovery.
|
|
- name: request
|
|
description: Endpoints related to request management.
|
|
- 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: person
|
|
description: Endpoints related to retrieving person details.
|
|
- name: media
|
|
description: Endpoints related to media management.
|
|
- name: collection
|
|
description: Endpoints related to retrieving collection details.
|
|
- 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: posters
|
|
description: Endpoints related to poster template management, saved posters, and icon assets.
|
|
- name: source-colors
|
|
description: Endpoints related to managing global source color schemes for poster generation.
|
|
- name: exclusions
|
|
description: Endpoints related to managing global item exclusions for collections.
|
|
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
|
|
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', 'multi-source', 'anilist', 'myanimelist', 'radarrtag', 'sonarrtag']
|
|
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
|
|
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
|
|
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
|
|
minimumYear:
|
|
type: integer
|
|
description: "Only process movies/TV shows released on or after this year (0 = no limit)"
|
|
example: 2010
|
|
nullable: true
|
|
excludedGenres:
|
|
type: array
|
|
items:
|
|
type: integer
|
|
description: "TMDB genre IDs to exclude from missing items search"
|
|
example: [28, 53]
|
|
nullable: true
|
|
excludedCountries:
|
|
type: array
|
|
items:
|
|
type: string
|
|
description: "ISO 3166-1 country codes to exclude from missing items search"
|
|
example: ["JP", "KR"]
|
|
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
|
|
reverseOrder:
|
|
type: boolean
|
|
description: "Reverse the order of items from the source"
|
|
example: false
|
|
nullable: true
|
|
randomizeOrder:
|
|
type: boolean
|
|
description: "Randomize the order of items (mutually exclusive with reverseOrder)"
|
|
example: false
|
|
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', 'multi-source', 'anilist', 'myanimelist', 'radarrtag', 'sonarrtag']
|
|
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
|
|
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
|
|
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
|
|
minimumYear:
|
|
type: integer
|
|
description: "Only process movies/TV shows released on or after this year (0 = no limit)"
|
|
example: 2010
|
|
nullable: true
|
|
excludedGenres:
|
|
type: array
|
|
items:
|
|
type: integer
|
|
description: "TMDB genre IDs to exclude from missing items search"
|
|
example: [28, 53]
|
|
nullable: true
|
|
excludedCountries:
|
|
type: array
|
|
items:
|
|
type: string
|
|
description: "ISO 3166-1 country codes to exclude from missing items search"
|
|
example: ["JP", "KR"]
|
|
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
|
|
reverseOrder:
|
|
type: boolean
|
|
description: "Reverse the order of items from the source"
|
|
example: false
|
|
nullable: true
|
|
randomizeOrder:
|
|
type: boolean
|
|
description: "Randomize the order of items (mutually exclusive with reverseOrder)"
|
|
example: false
|
|
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
|
|
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
|
|
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', 'multi-source', 'anilist', 'myanimelist', 'radarrtag', 'sonarrtag']
|
|
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
|
|
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
|
|
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
|
|
minimumYear:
|
|
type: integer
|
|
description: "Only process movies/TV shows released on or after this year (0 = no limit)"
|
|
example: 2010
|
|
nullable: true
|
|
excludedGenres:
|
|
type: array
|
|
items:
|
|
type: integer
|
|
description: "TMDB genre IDs to exclude from missing items search"
|
|
example: [28, 53]
|
|
nullable: true
|
|
excludedCountries:
|
|
type: array
|
|
items:
|
|
type: string
|
|
description: "ISO 3166-1 country codes to exclude from missing items search"
|
|
example: ["JP", "KR"]
|
|
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
|
|
reverseOrder:
|
|
type: boolean
|
|
description: "Reverse the order of items from the source"
|
|
example: false
|
|
nullable: true
|
|
randomizeOrder:
|
|
type: boolean
|
|
description: "Randomize the order of items (mutually exclusive with reverseOrder)"
|
|
example: false
|
|
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
|
|
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
|
|
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', 'anilist', 'myanimelist', 'radarrtag', 'sonarrtag']
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
TraktSettings:
|
|
type: object
|
|
properties:
|
|
apiKey:
|
|
type: string
|
|
nullable: true
|
|
example: 'your-trakt-api-key-here'
|
|
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'
|
|
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
|
|
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
|
|
isDefault:
|
|
type: boolean
|
|
example: false
|
|
externalUrl:
|
|
type: string
|
|
example: http://radarr.example.com
|
|
syncEnabled:
|
|
type: boolean
|
|
example: false
|
|
preventSearch:
|
|
type: boolean
|
|
example: false
|
|
required:
|
|
- hostname
|
|
- port
|
|
- apiKey
|
|
- useSsl
|
|
- activeProfileId
|
|
- activeProfileName
|
|
- activeDirectory
|
|
- isDefault
|
|
ServarrTag:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: number
|
|
example: 1
|
|
label:
|
|
type: string
|
|
example: A Label
|
|
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: [short, long, fixed]
|
|
name:
|
|
type: string
|
|
example: A Job Name
|
|
nextExecutionTime:
|
|
type: string
|
|
example: '2020-09-02T05:02: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, mdblist, letterboxd, anilist, myanimelist]
|
|
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
|
|
|
|
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:
|
|
- genres
|
|
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:
|
|
- countries
|
|
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
|
|
/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
|
|
/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:
|
|
- collection
|
|
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:
|
|
- collection
|
|
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:
|
|
- collection
|
|
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"
|
|
'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:
|
|
- collection
|
|
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"
|
|
'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:
|
|
- collection
|
|
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:
|
|
- collection
|
|
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:
|
|
- collection
|
|
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:
|
|
- collection
|
|
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:
|
|
- collection
|
|
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:
|
|
- collection
|
|
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:
|
|
- collection
|
|
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:
|
|
- collection
|
|
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:
|
|
- collection
|
|
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:
|
|
- collection
|
|
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:
|
|
- collection
|
|
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:
|
|
- collection
|
|
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:
|
|
- collection
|
|
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:
|
|
- collection
|
|
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:
|
|
- collection
|
|
parameters:
|
|
- in: path
|
|
name: filename
|
|
required: true
|
|
schema:
|
|
type: string
|
|
example: "f47ac10b-58cc-4372-a567-0e02b2c3d479.jpg"
|
|
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. Authentication required.
|
|
tags:
|
|
- collection
|
|
parameters:
|
|
- in: path
|
|
name: filename
|
|
required: true
|
|
schema:
|
|
type: string
|
|
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"
|
|
'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:
|
|
- collection
|
|
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:
|
|
- collection
|
|
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:
|
|
- collection
|
|
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:
|
|
- collection
|
|
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:
|
|
- collection
|
|
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, 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]
|
|
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:
|
|
- collection
|
|
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:
|
|
- collection
|
|
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:
|
|
- collection
|
|
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:
|
|
- collection
|
|
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:
|
|
- collection
|
|
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:
|
|
- collection
|
|
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:
|
|
- collection
|
|
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:
|
|
- collection
|
|
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:
|
|
- collection
|
|
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:
|
|
- collection
|
|
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:
|
|
- collection
|
|
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:
|
|
- collection
|
|
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:
|
|
- collection
|
|
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:
|
|
- collection
|
|
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:
|
|
- collection
|
|
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:
|
|
title:
|
|
type: string
|
|
url:
|
|
type: string
|
|
criticsScore:
|
|
type: number
|
|
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 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)
|
|
responses:
|
|
'200':
|
|
description: TV show ratings
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
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:
|
|
- collection
|
|
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
|
|
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
|
|
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
|
|
responses:
|
|
'200':
|
|
description: OK
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/MainSettings'
|
|
/settings/plex:
|
|
get:
|
|
summary: Get Plex settings
|
|
description: Retrieves current Plex settings.
|
|
tags:
|
|
- settings
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
- 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 500x750 pixels (2:3 aspect ratio)
|
|
- All images are converted to JPEG format for consistency
|
|
- Quality optimization applied (85% quality)
|
|
tags:
|
|
- settings
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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/trakt:
|
|
get:
|
|
summary: Get Trakt settings
|
|
description: Retrieves current Trakt settings.
|
|
tags:
|
|
- settings
|
|
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
|
|
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 with the provided API key.
|
|
tags:
|
|
- settings
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
apiKey:
|
|
type: string
|
|
description: Trakt API key (Client ID)
|
|
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/mdblist:
|
|
get:
|
|
summary: Get MDBList settings
|
|
description: Retrieves current MDBList settings.
|
|
tags:
|
|
- settings
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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'
|
|
/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
|
|
example: '/overseerr'
|
|
required:
|
|
- hostname
|
|
- apiKey
|
|
responses:
|
|
'200':
|
|
description: 'Connection test successful'
|
|
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'
|
|
'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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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/{radarrId}:
|
|
put:
|
|
summary: Update Radarr instance
|
|
description: Updates an existing Radarr instance with the provided values.
|
|
tags:
|
|
- settings
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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'
|
|
/settings/sonarr:
|
|
get:
|
|
summary: Get Sonarr settings
|
|
description: Returns all Sonarr settings in a JSON array.
|
|
tags:
|
|
- settings
|
|
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
|
|
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
|
|
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/{sonarrId}:
|
|
put:
|
|
summary: Update Sonarr instance
|
|
description: Updates an existing Sonarr instance with the provided values.
|
|
tags:
|
|
- settings
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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'
|
|
/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
|
|
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
|
|
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
|
|
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
|
|
parameters:
|
|
- in: path
|
|
name: jobId
|
|
required: true
|
|
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
|
|
parameters:
|
|
- in: path
|
|
name: jobId
|
|
required: true
|
|
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
|
|
parameters:
|
|
- in: path
|
|
name: jobId
|
|
required: true
|
|
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
|
|
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
|
|
parameters:
|
|
- in: path
|
|
name: cacheId
|
|
required: true
|
|
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
|
|
parameters:
|
|
- in: query
|
|
name: take
|
|
schema:
|
|
type: number
|
|
nullable: true
|
|
example: 25
|
|
- in: query
|
|
name: skip
|
|
schema:
|
|
type: number
|
|
nullable: true
|
|
example: 0
|
|
- in: query
|
|
name: filter
|
|
schema:
|
|
type: string
|
|
nullable: true
|
|
enum: [debug, info, warn, error]
|
|
default: debug
|
|
- in: query
|
|
name: search
|
|
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/about:
|
|
get:
|
|
summary: Get server stats
|
|
description: Returns current server stats in a JSON object.
|
|
tags:
|
|
- settings
|
|
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
|
|
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
|
|
schema:
|
|
type: number
|
|
nullable: true
|
|
example: 20
|
|
- in: query
|
|
name: skip
|
|
schema:
|
|
type: number
|
|
nullable: true
|
|
example: 0
|
|
- in: query
|
|
name: sort
|
|
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
|
|
schema:
|
|
type: number
|
|
example: 337401
|
|
- in: query
|
|
name: language
|
|
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
|
|
schema:
|
|
type: number
|
|
example: 337401
|
|
- in: query
|
|
name: page
|
|
schema:
|
|
type: number
|
|
example: 1
|
|
default: 1
|
|
- in: query
|
|
name: language
|
|
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
|
|
schema:
|
|
type: number
|
|
example: 337401
|
|
- in: query
|
|
name: page
|
|
schema:
|
|
type: number
|
|
example: 1
|
|
default: 1
|
|
- in: query
|
|
name: language
|
|
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
|
|
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
|
|
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
|
|
schema:
|
|
type: number
|
|
example: 76479
|
|
- in: query
|
|
name: language
|
|
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
|
|
schema:
|
|
type: number
|
|
example: 76479
|
|
- in: path
|
|
name: seasonId
|
|
required: true
|
|
schema:
|
|
type: number
|
|
example: 1
|
|
- in: query
|
|
name: language
|
|
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
|
|
schema:
|
|
type: number
|
|
nullable: true
|
|
example: 20
|
|
- in: query
|
|
name: skip
|
|
schema:
|
|
type: number
|
|
nullable: true
|
|
example: 0
|
|
- in: query
|
|
name: filter
|
|
schema:
|
|
type: string
|
|
nullable: true
|
|
enum:
|
|
[
|
|
all,
|
|
available,
|
|
partial,
|
|
allavailable,
|
|
processing,
|
|
pending,
|
|
deleted,
|
|
]
|
|
- in: query
|
|
name: sort
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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, mdblist, letterboxd, anilist, myanimelist]
|
|
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
|
|
tags:
|
|
- settings
|
|
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
|
|
tags:
|
|
- settings
|
|
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
|
|
tags:
|
|
- settings
|
|
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
|
|
tags:
|
|
- settings
|
|
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
|
|
tags:
|
|
- settings
|
|
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
|
|
tags:
|
|
- settings
|
|
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
|
|
tags:
|
|
- search
|
|
responses:
|
|
'200':
|
|
description: Library hubs returned successfully
|
|
'500':
|
|
description: Failed to fetch library hubs
|
|
|
|
/discovery/hubs/libraries/{sectionId}:
|
|
get:
|
|
summary: Get 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
|
|
'500':
|
|
description: Failed to fetch library hubs
|
|
|
|
/discovery/hubs/libraries/{sectionId}/manage:
|
|
get:
|
|
summary: Get hub management interface for a 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
|
|
'500':
|
|
description: Failed to fetch hub management data
|
|
|
|
/discovery/hubs/scan:
|
|
get:
|
|
summary: Discover available Plex hubs and convert them to hub configurations
|
|
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
|
|
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:
|
|
- posters
|
|
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: 500
|
|
height:
|
|
type: number
|
|
example: 750
|
|
background:
|
|
type: object
|
|
properties:
|
|
type:
|
|
type: string
|
|
enum: [color, gradient]
|
|
example: "gradient"
|
|
color:
|
|
type: string
|
|
example: "#6366f1"
|
|
secondaryColor:
|
|
type: string
|
|
example: "#1e1b4b"
|
|
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:
|
|
- posters
|
|
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:
|
|
- posters
|
|
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:
|
|
- posters
|
|
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:
|
|
- posters
|
|
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:
|
|
- posters
|
|
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:
|
|
- posters
|
|
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:
|
|
- posters
|
|
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:
|
|
- posters
|
|
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:
|
|
- posters
|
|
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:
|
|
- posters
|
|
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:
|
|
- posters
|
|
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). Users can only delete their own posters.
|
|
tags:
|
|
- posters
|
|
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)
|
|
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"
|
|
message:
|
|
type: string
|
|
example: "This poster is being used by the following collections: Movie Collection, TV Collection"
|
|
collections:
|
|
type: array
|
|
items:
|
|
type: string
|
|
example: ["Movie Collection", "TV Collection"]
|
|
'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:
|
|
- posters
|
|
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:
|
|
- posters
|
|
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:
|
|
- posters
|
|
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:
|
|
- posters
|
|
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:
|
|
- posters
|
|
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:
|
|
- posters
|
|
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:
|
|
- posters
|
|
parameters:
|
|
- name: filename
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
description: Poster filename
|
|
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:
|
|
- posters
|
|
parameters:
|
|
- name: filename
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
description: Thumbnail filename
|
|
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:
|
|
- posters
|
|
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
|
|
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
|
|
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
|
|
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
|
|
|
|
security:
|
|
- cookieAuth: []
|
|
- apiKey: []
|