openapi: '3.0.2' info: title: 'Seerr API' version: '1.0.0' description: | This is the documentation for the Seerr 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 Seerr. tags: - name: public description: Public API endpoints requiring no authentication. - name: settings description: Endpoints related to Seerr's settings and configuration. - name: live-tv description: Live TV airings and recording requests through IPTV Tunerr. - name: soulseek description: Soulseek track requests, library-health fixes, and SongID through slskdN. - name: swipe description: Swipe discovery decks and swipe decisions. - 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: admin description: Administrator-managed instance-wide configuration and tools. - 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: watchlist description: Collection of media to watch later - name: blocklist description: Blocklisted media from discovery page. - name: association description: Cross-medium related media graph endpoints. - name: playlist description: Endpoints for importing Spotify and YouTube playlists as music requests. - name: game library description: Personal game progress, optional household sharing, and Steam library import. - name: native desktop description: Optional protocol-v1 Jellyfin playback for compatible native desktop clients. - name: indexer search description: Direct manual searches through an administrator-configured Prowlarr instance. servers: - url: '{server}/api/v1' variables: server: default: http://localhost:5055 components: schemas: SwipeCard: type: object properties: mediaType: type: string enum: [movie, tv, book] id: type: string title: type: string subtitle: type: string year: type: integer overview: type: string imageUrl: type: string rating: type: number authorId: type: string because: type: string description: Why the card is in the deck, for example a liked title. reason: type: string description: AI explanation when an AI provider ranked the deck. SwipeSettings: type: object properties: enabled: type: boolean aiProvider: type: string enum: [none, anthropic, openai] aiApiKey: type: string description: API key for the selected AI provider (optional for local OpenAI-compatible servers). Omit or send the redacted value to keep the saved key. clearAiApiKey: type: boolean aiModel: type: string maxLength: 100 aiBaseUrl: type: string maxLength: 2048 description: OpenAI-compatible base URL for the `openai` provider, for example https://api.openai.com/v1 or http://ollama:11434/v1. aiEffort: type: string enum: [low, medium, high] SwipeFavoriteSeed: type: object required: [mediaType, id, title] properties: mediaType: type: string enum: [movie, tv, book] id: type: string maxLength: 64 title: type: string maxLength: 512 BookHomeSectionPreference: type: object required: [key, enabled] properties: key: type: string maxLength: 64 enabled: type: boolean ReadMeABookSettings: type: object required: [enabled, hostname, port, useSsl, baseUrl, apiKey] properties: enabled: type: boolean hostname: type: string maxLength: 255 port: type: integer minimum: 1 maximum: 65535 useSsl: type: boolean baseUrl: type: string maxLength: 512 apiKey: type: string description: API token. The saved value is redacted in responses. apiKeyConfigured: type: boolean clearApiKey: type: boolean ReadMeABookRequest: type: object properties: id: type: integer asin: type: string title: type: string author: type: string narrator: type: string nullable: true description: type: string nullable: true coverArtUrl: type: string nullable: true durationMinutes: type: integer nullable: true status: type: string statusMessage: type: string nullable: true createdAt: type: string format: date-time updatedAt: type: string format: date-time TrackRequest: type: object properties: id: type: integer status: type: string enum: [pending, searching, completed, failed, declined, cancelled] artist: type: string title: type: string recordingMbid: type: string source: type: string enum: [manual, playlist, songid] searchCount: type: integer lastMatchCount: type: integer lastError: type: string createdAt: type: string format: date-time updatedAt: type: string format: date-time requestedBy: type: object properties: id: type: integer displayName: type: string SlskdnSettings: type: object properties: enabled: type: boolean hostname: type: string port: type: integer minimum: 1 maximum: 65535 useSsl: type: boolean baseUrl: type: string apiKey: type: string description: slskdN API key (read-write role; administrator for SongID). Omit or send the redacted value to keep the saved key. clearApiKey: type: boolean searchFilter: type: string maxLength: 512 SongIdResult: type: object properties: id: type: string status: type: string summary: type: string stage: type: string percentComplete: type: number queuePosition: type: integer albums: type: array items: type: object properties: releaseId: type: string releaseGroupId: type: string title: type: string artist: type: string isExact: type: boolean tracks: type: array items: type: object properties: recordingId: type: string title: type: string artist: type: string isExact: type: boolean RecordingRequest: type: object properties: id: type: integer kind: type: string enum: [airing, series] status: type: string enum: [ pending, scheduled, recording, completed, failed, declined, cancelled, ] title: type: string subTitle: type: string mediaType: type: string enum: [movie, tv] tmdbId: type: integer channel: type: string description: Tunerr guide number channelName: type: string startsAt: type: string format: date-time endsAt: type: string format: date-time completedCount: type: integer failedCount: type: integer lastError: type: string createdAt: type: string format: date-time updatedAt: type: string format: date-time requestedBy: type: object properties: id: type: integer displayName: type: string LiveTvAiring: type: object properties: channel: type: string channelName: type: string start: type: string format: date-time stop: type: string format: date-time title: type: string subTitle: type: string season: type: integer episode: type: integer categories: type: array items: type: string TunerrSettings: type: object properties: enabled: type: boolean hostname: type: string useSsl: type: boolean baseUrl: type: string deckPort: type: integer minimum: 1 maximum: 65535 tunerPort: type: integer minimum: 1 maximum: 65535 guideUrl: type: string sportarrBaseUrl: type: string description: Optional tuner base URL as reachable from Sportarr; empty derives it from hostname, HTTPS, and tunerPort. username: type: string password: type: string description: Tunerr deck password. Omit or send the redacted value to keep the saved password. clearPassword: type: boolean guideHours: type: integer minimum: 6 maximum: 336 TunerrSportarrIntegrationStatus: type: object required: [tunerr, sportarr] properties: tunerr: type: object required: [configured, sportsAutomation] properties: configured: type: boolean sportsAutomation: type: string enum: [unavailable, disabled, enabled] eventCount: type: integer minimum: 0 matchedEventCount: type: integer minimum: 0 sportarr: type: object required: [configured, reachable, feeds] properties: configured: type: boolean reachable: type: boolean nullable: true name: type: string feeds: type: object required: [linked] properties: linked: type: boolean source: type: object required: [id, name, active, channelCount, hasError] properties: id: type: integer name: type: string active: type: boolean channelCount: type: integer hasError: type: boolean guide: type: object required: [id, name, active, programCount, linkedToSource, hasError] properties: id: type: integer name: type: string active: type: boolean programCount: type: integer linkedToSource: type: boolean hasError: type: boolean TunerrSportarrIntegrationResult: type: object required: [success, sourceCreated, guideCreated, source, guide, sync] properties: success: type: boolean sourceCreated: type: boolean guideCreated: type: boolean source: type: object required: [id, name, active, channelCount, hasError] properties: id: type: integer name: type: string active: type: boolean channelCount: type: integer hasError: type: boolean guide: type: object required: [id, name, active, programCount, linkedToSource, hasError] properties: id: type: integer name: type: string active: type: boolean programCount: type: integer linkedToSource: type: boolean hasError: type: boolean sync: type: object required: [success, channelCount, programCount, mappedChannelCount] properties: success: type: boolean channelCount: type: integer programCount: type: integer mappedChannelCount: type: integer DownloadClientSettings: type: object required: [name, type, hostname] properties: id: type: integer name: type: string maxLength: 80 type: type: string enum: [qbittorrent, transmission, deluge, torrentng] enabled: type: boolean hostname: type: string port: type: integer minimum: 1 maximum: 65535 useSsl: type: boolean baseUrl: type: string username: type: string password: type: string description: Client password, Deluge Web UI password, or TorrentNG API token. Omit or send the redacted value to keep the saved secret. clearPassword: type: boolean LiveDownloadSettings: type: object properties: pollIntervalSeconds: type: integer minimum: 1 maximum: 60 clients: type: array maxItems: 8 items: $ref: '#/components/schemas/DownloadClientSettings' ReaderDeliverySettings: type: object required: [ grimmoryUrl, grimmoryUsername, grimmoryPassword, bookorbitUrl, bookorbitUsername, bookorbitPassword, preferredProvider, ] properties: grimmoryUrl: type: string maxLength: 2048 grimmoryUsername: type: string maxLength: 256 grimmoryPassword: type: string maxLength: 2048 description: Responses always redact configured passwords. Send the redacted marker to preserve a saved password. bookorbitUrl: type: string maxLength: 2048 bookorbitUsername: type: string maxLength: 256 bookorbitPassword: type: string maxLength: 2048 description: Responses always redact configured passwords. Send the redacted marker to preserve a saved password. preferredProvider: type: string enum: [grimmory, bookorbit] clearGrimmoryCredentials: type: boolean description: Set true to remove the saved Grimmory username and password. clearBookorbitCredentials: type: boolean description: Set true to remove the saved BookOrbit username and password. ReaderGroupingTarget: type: object additionalProperties: false required: [type, id, name] properties: type: type: string enum: [author, book-series, comic-series] id: type: string minLength: 1 maxLength: 255 name: type: string minLength: 1 maxLength: 255 ReaderGroupingRule: type: object required: [field, operator, value] properties: field: type: string operator: type: string value: oneOf: - type: string - type: array items: type: string ReaderGroupingFilter: type: object required: [type, join, rules] properties: type: type: string enum: [group] join: type: string enum: [and, AND] rules: type: array items: $ref: '#/components/schemas/ReaderGroupingRule' ReaderDeliveryGrouping: type: object required: [ id, provider, targetType, targetId, targetName, groupName, remoteGroupId, isPublic, syncToKobo, status, lastMatchCount, countVerified, lastError, lastSyncedAt, serviceUrl, ] properties: id: type: integer minimum: 1 provider: type: string enum: [grimmory, bookorbit] targetType: type: string enum: [author, book-series, comic-series] targetId: type: string targetName: type: string groupName: type: string remoteGroupId: type: string nullable: true isPublic: type: boolean syncToKobo: type: boolean status: type: string enum: [pending, ready, error] lastMatchCount: type: integer minimum: 0 countVerified: type: boolean lastError: type: string nullable: true lastSyncedAt: type: string format: date-time nullable: true serviceUrl: type: string format: uri nullable: true ReaderGroupingPreviewRequest: type: object additionalProperties: false required: [provider, target] properties: provider: type: string enum: [grimmory, bookorbit] target: $ref: '#/components/schemas/ReaderGroupingTarget' ReaderGroupingPreview: type: object required: [provider, target, rule, ruleSummary, matchedCount, sampleTitles] properties: provider: type: string enum: [grimmory, bookorbit] target: $ref: '#/components/schemas/ReaderGroupingTarget' rule: $ref: '#/components/schemas/ReaderGroupingFilter' ruleSummary: type: string matchedCount: type: integer minimum: 0 sampleTitles: type: array maxItems: 5 items: type: string ReaderGroupingSaveRequest: type: object additionalProperties: false required: [provider, target] properties: provider: type: string enum: [grimmory, bookorbit] target: $ref: '#/components/schemas/ReaderGroupingTarget' isPublic: type: boolean syncToKobo: type: boolean allowEmpty: type: boolean description: Must be true to create a rule when the current preview has no matches. ReaderGroupingSaveResponse: type: object required: [grouping, previewCount, sampleTitles, ruleSummary] properties: grouping: $ref: '#/components/schemas/ReaderDeliveryGrouping' previewCount: type: integer minimum: 0 sampleTitles: type: array maxItems: 5 items: type: string ruleSummary: type: string warning: type: string ReaderGroupingConnectionTest: type: object required: [connected, provider, existingGroupingCount] properties: connected: type: boolean provider: type: string enum: [grimmory, bookorbit] existingGroupingCount: type: integer minimum: 0 ReaderGroupingDeleteResponse: type: object required: [deleted] properties: deleted: type: boolean GameLibraryEntry: type: object required: [ id, externalKey, catalogId, category, title, status, isOwned, steamAppId, steamOwned, playtimeMinutes, storeName, platformName, shareWithHousehold, source, lastSyncedAt, ] properties: id: type: integer minimum: 1 externalKey: type: string catalogId: type: integer nullable: true category: type: string enum: [game, retro, modern] title: type: string summary: type: string coverUrl: type: string releaseDate: type: string status: type: string enum: [backlog, playing, played, completed, paused, dropped] isOwned: type: boolean steamAppId: type: integer nullable: true steamOwned: type: boolean playtimeMinutes: type: integer minimum: 0 storeName: type: string platformName: type: string shareWithHousehold: type: boolean source: type: string enum: [manual, steam] lastSyncedAt: type: string format: date-time nullable: true createdAt: type: string format: date-time updatedAt: type: string format: date-time request: type: object nullable: true properties: id: type: integer status: type: string GameLibraryPage: type: object required: [total, nextOffset, results] properties: total: type: integer nextOffset: type: integer nullable: true results: type: array items: $ref: '#/components/schemas/GameLibraryEntry' SharedGameLibraryPage: type: object required: [total, nextOffset, results] properties: total: type: integer nextOffset: type: integer nullable: true results: type: array items: type: object required: [ key, catalogId, category, title, owners, ownerCount, steamAppId, playtimeMinutes, ] properties: key: type: string catalogId: type: integer nullable: true category: type: string enum: [game, retro, modern] title: type: string summary: type: string coverUrl: type: string ownerCount: type: integer owners: type: array items: type: object required: [ id, displayName, status, storeName, platformName, playtimeMinutes, ] properties: id: type: integer displayName: type: string avatar: type: string status: type: string enum: [backlog, playing, played, completed, paused, dropped] storeName: type: string platformName: type: string playtimeMinutes: type: integer minimum: 0 steamAppId: type: integer nullable: true playtimeMinutes: type: integer minimum: 0 GameLibraryMutation: type: object additionalProperties: false required: [category, catalogId] properties: category: type: string enum: [game, retro, modern] catalogId: type: integer minimum: 1 maximum: 2147483647 status: type: string enum: [backlog, playing, played, completed, paused, dropped] isOwned: type: boolean storeName: type: string maxLength: 120 platformName: type: string maxLength: 120 shareWithHousehold: type: boolean GameLibraryManualMutation: type: object additionalProperties: false required: [title] properties: category: type: string enum: [game, retro, modern] default: game title: type: string minLength: 1 maxLength: 512 status: type: string enum: [backlog, playing, played, completed, paused, dropped] isOwned: type: boolean storeName: type: string maxLength: 120 platformName: type: string maxLength: 120 shareWithHousehold: type: boolean GameLibraryPatch: type: object additionalProperties: false minProperties: 1 properties: status: type: string enum: [backlog, playing, played, completed, paused, dropped] isOwned: type: boolean storeName: type: string maxLength: 120 platformName: type: string maxLength: 120 shareWithHousehold: type: boolean GameLibraryMutationResponse: type: object required: [entry] properties: entry: $ref: '#/components/schemas/GameLibraryEntry' GameLibraryErrorResponse: type: object additionalProperties: true properties: status: type: integer error: type: string message: type: string ExternalRequestList: type: object required: [id, provider, sourceUrl] properties: id: type: integer provider: type: string enum: [imdb, imdb-csv, goodreads, hardcover] sourceUrl: type: string format: uri lastSyncedAt: type: string format: date-time nullable: true lastSyncError: type: string nullable: true ExternalRequestListSyncResult: type: object required: - listId - provider - sourceItems - requested - alreadyRequested - unmatched - failed - lastSyncedAt properties: listId: type: integer provider: type: string enum: [imdb, imdb-csv, goodreads, hardcover] sourceItems: type: integer requested: type: integer alreadyRequested: type: integer unmatched: type: integer failed: type: integer lastSyncedAt: type: string format: date-time error: type: string SoftwareProviderSettingsInput: type: object properties: hostname: type: string maxLength: 255 port: type: integer minimum: 1 maximum: 65535 useSsl: type: boolean baseUrl: type: string maxLength: 512 apiKey: type: string maxLength: 2048 SoftwareProviderSettingsView: type: object properties: hostname: type: string port: type: integer useSsl: type: boolean baseUrl: type: string apiKey: type: string description: Always redacted when configured. apiKeyConfigured: type: boolean SoftwareRequestActions: type: object nullable: true required: [retry, cancel] properties: retry: type: boolean cancel: type: boolean cancelReason: type: string nullable: true MediaRatings: type: object properties: rt: type: object properties: title: type: string year: type: number url: type: string criticsScore: type: number criticsRating: type: string enum: ['Rotten', 'Fresh', 'Certified Fresh'] audienceScore: type: number audienceRating: type: string enum: ['Spilled', 'Upright'] imdb: type: object properties: title: type: string url: type: string criticsScore: type: number criticsScoreCount: type: integer mdblist: type: object properties: imdbId: type: string imdbRating: type: number imdbVotes: type: integer rtRating: type: number rtUserRating: type: number metacriticRating: type: number traktRating: type: number traktVotes: type: integer tmdbRating: type: number MdblistRatingBatchRequest: type: object additionalProperties: false required: - ids properties: ids: type: array minItems: 1 maxItems: 200 items: type: integer minimum: 1 maximum: 1000000000 MdblistRatings: type: object properties: imdbId: type: string imdbRating: type: number imdbVotes: type: integer rtRating: type: number rtUserRating: type: number metacriticRating: type: number traktRating: type: number traktVotes: type: integer tmdbRating: type: number MdblistRatingsBatchResponse: type: object additionalProperties: $ref: '#/components/schemas/MdblistRatings' QueueIntervention: type: object additionalProperties: false required: - id - serviceType - serviceId - serviceName - title - warnings - state - resolution - actorId - manualImportCapable - createdAt - lastSeenAt - actionAt - resolvedAt - actions properties: id: type: integer minimum: 1 serviceType: type: string enum: - radarr - sonarr - lidarr - readarr serviceId: type: integer serviceName: type: string title: type: string warnings: type: array items: type: string state: type: string enum: - active - failed - importing - rejecting - resolved resolution: type: string nullable: true actorId: type: integer nullable: true manualImportCapable: type: boolean createdAt: type: string format: date-time lastSeenAt: type: string format: date-time actionAt: type: string format: date-time nullable: true resolvedAt: type: string format: date-time nullable: true actions: type: array maxItems: 50 items: type: object additionalProperties: false required: - at - actorId - action - state - options properties: at: type: string format: date-time actorId: type: integer action: type: string enum: - import - reject state: type: string options: type: object additionalProperties: false properties: importMode: type: string enum: - copy - move fileCount: type: integer blocklist: type: boolean removeFromClient: type: boolean DiscoveryAccount: type: object additionalProperties: false required: - provider - username - providerUserId - allowWrites - linkedAt - expiresAt properties: provider: type: string enum: - trakt - anilist - simkl username: type: string providerUserId: type: string allowWrites: type: boolean linkedAt: type: string format: date-time expiresAt: type: integer nullable: true DiscoveryConfiguration: type: object additionalProperties: false required: - trakt - anilist - simkl - mdblist properties: trakt: type: object additionalProperties: false required: - configured - clientId properties: configured: type: boolean clientId: type: string anilist: type: object additionalProperties: false required: - configured - clientId properties: configured: type: boolean clientId: type: string simkl: type: object additionalProperties: false required: - configured - clientId properties: configured: type: boolean clientId: type: string mdblist: type: object additionalProperties: false required: - configured properties: configured: type: boolean DiscoveryAccounts: type: object additionalProperties: false required: [accounts, mediaServer] properties: accounts: type: array items: $ref: '#/components/schemas/DiscoveryAccount' mediaServer: type: object nullable: true additionalProperties: false required: [provider, connected] properties: provider: type: string enum: [plex, jellyfin, emby] connected: type: boolean DiscoveryFeedItem: type: object additionalProperties: false required: - id - source - sourceId - title properties: id: type: string source: type: string enum: - trakt - anilist - mdblist sourceId: type: string title: type: string mediaType: type: string enum: - movie - tv tmdbId: type: integer minimum: 1 year: type: integer imageUrl: type: string identityMapped: type: boolean identityResolution: type: string enum: [personal, curated, external-id] mappingAvailable: type: boolean DiscoveryFeedPage: type: object additionalProperties: false required: - page - hasMore - items - missingMappings properties: page: type: integer minimum: 1 maximum: 100 hasMore: type: boolean items: type: array items: $ref: '#/components/schemas/DiscoveryFeedItem' missingMappings: type: integer minimum: 0 DiscoveryProviderError: type: object additionalProperties: false required: - code - message properties: code: type: string enum: - PROVIDER_RATE_LIMITED - RECONNECT_REQUIRED - PROVIDER_SETUP_REQUIRED - PROVIDER_LIST_NOT_FOUND - PROVIDER_TEMPORARILY_UNAVAILABLE message: type: string PersonalLibraryItem: type: object additionalProperties: false required: [id, source, sourceId, title] properties: id: type: string source: type: string enum: [trakt, anilist, simkl, plex, jellyfin, emby] sourceId: type: string title: type: string mediaType: type: string enum: [movie, tv] tmdbId: type: integer minimum: 1 identityMapped: type: boolean identityResolution: type: string enum: [personal, curated, external-id] imageUrl: type: string year: type: integer status: type: string enum: [planning, watching, watched, completed, unwatched, paused, dropped] rating: type: number minimum: 0 maximum: 10 progress: type: integer minimum: 0 totalEpisodes: type: integer minimum: 0 PersonalLibraryPage: type: object additionalProperties: false required: [items, page, hasMore, allowWrites, missingMappings, truncated] properties: items: type: array items: $ref: '#/components/schemas/PersonalLibraryItem' page: type: integer minimum: 1 maximum: 500 nextCursor: type: integer minimum: 0 maximum: 100000 description: Resume a media-server in-progress shelf from this offset. total: type: integer minimum: 0 hasMore: type: boolean allowWrites: type: boolean missingMappings: type: integer minimum: 0 truncated: type: boolean libraries: type: array items: type: object additionalProperties: false required: [id, name, type] properties: id: type: string name: type: string type: type: string enum: [show, movie] ProviderLibraryRepairRequest: type: object additionalProperties: false required: [shelf, startPage, pageCount] properties: shelf: type: string enum: [all, watchlist, watched, in-progress, completed, rated] startPage: type: integer minimum: 1 maximum: 500 pageCount: type: integer minimum: 1 maximum: 5 mediaType: type: string enum: [movie, tv] ProviderLibraryRepairResult: type: object additionalProperties: false required: [ startPage, nextPage, pagesScanned, scanned, matched, saved, hasMore, truncated, limitReached, ] properties: startPage: type: integer minimum: 1 maximum: 500 nextPage: type: integer minimum: 1 maximum: 501 pagesScanned: type: integer minimum: 0 maximum: 5 scanned: type: integer minimum: 0 maximum: 200 matched: type: integer minimum: 0 maximum: 200 saved: type: integer minimum: 0 maximum: 200 hasMore: type: boolean truncated: type: boolean limitReached: type: boolean DiscoveryIdentityMappingRequest: type: object additionalProperties: false required: [identity, tmdbId, mediaType] properties: identity: type: string minLength: 3 maxLength: 256 tmdbId: type: integer minimum: 1 maximum: 1000000000 mediaType: type: string enum: [movie, tv] DiscoveryIdentityMapping: type: object additionalProperties: false required: [identity, tmdbId, mediaType, updatedAt] properties: identity: type: string maxLength: 256 tmdbId: type: integer minimum: 1 mediaType: type: string enum: [movie, tv] updatedAt: type: string format: date-time PersonalIdentityMappingPackEntry: type: object additionalProperties: false required: [identity, tmdbId, mediaType] properties: identity: type: string minLength: 3 maxLength: 256 tmdbId: type: integer minimum: 1 maximum: 1000000000 mediaType: type: string enum: [movie, tv] PersonalIdentityMappingPack: type: object additionalProperties: false required: [format, version, exportedAt, entries] properties: format: type: string enum: [seerrng.personal-title-matches] version: type: integer enum: [1] exportedAt: type: string format: date-time entries: type: array maxItems: 10000 items: $ref: '#/components/schemas/PersonalIdentityMappingPackEntry' PersonalIdentityMappingPackImportResult: type: object additionalProperties: false required: [imported, updated, unchanged, total] properties: imported: type: integer minimum: 0 updated: type: integer minimum: 0 unchanged: type: integer minimum: 0 total: type: integer minimum: 0 CuratedIdentityMappingPack: type: object additionalProperties: false required: [format, version, packId, name, exportedAt, entries] properties: format: type: string enum: [seerrng.curated-title-matches] version: type: integer enum: [1] packId: type: string minLength: 1 maxLength: 64 pattern: '^[a-z0-9](?:[a-z0-9-]{0,62}[a-z0-9])?$' name: type: string minLength: 1 maxLength: 128 exportedAt: type: string format: date-time entries: type: array maxItems: 10000 items: $ref: '#/components/schemas/PersonalIdentityMappingPackEntry' CuratedIdentityPackSummary: type: object additionalProperties: false required: [packId, name, version, count, updatedAt] properties: packId: type: string maxLength: 64 name: type: string maxLength: 128 version: type: integer enum: [1] count: type: integer minimum: 0 maximum: 10000 updatedAt: type: string format: date-time CuratedIdentityPackList: type: object additionalProperties: false required: [packs] properties: packs: type: array maxItems: 50 items: $ref: '#/components/schemas/CuratedIdentityPackSummary' CuratedIdentityPackImportResult: type: object additionalProperties: false required: [packId, name, imported, updated, unchanged, removed, total] properties: packId: type: string maxLength: 64 name: type: string maxLength: 128 imported: type: integer minimum: 0 updated: type: integer minimum: 0 unchanged: type: integer minimum: 0 removed: type: integer minimum: 0 total: type: integer minimum: 0 maximum: 10000 DiscoveryTrackingRequest: type: object additionalProperties: false required: [requestId, action, value] properties: requestId: type: string format: uuid action: type: string enum: [watched, rating, progress] value: anyOf: - type: boolean - type: number minimum: 0 maximum: 100000 mediaType: type: string enum: [movie, tv] tmdbId: type: integer minimum: 1 maximum: 2147483647 anilistId: type: integer minimum: 1 maximum: 2147483647 episode: type: object additionalProperties: false required: [season, episode] properties: season: type: integer minimum: 0 maximum: 10000 episode: type: integer minimum: 1 maximum: 2147483647 DiscoveryTrackingAction: type: object additionalProperties: false required: [requestId, provider, state, createdAt] properties: requestId: type: string format: uuid provider: type: string enum: [trakt, anilist, simkl] state: type: string enum: [pending, succeeded, unknown] createdAt: type: string format: date-time completedAt: type: string format: date-time nullable: true ProviderEpisodeWatchState: type: object additionalProperties: false required: [available, season, episodes] properties: available: type: boolean season: type: integer minimum: 0 maximum: 10000 episodes: type: array maxItems: 10000 items: type: object additionalProperties: false required: [episode, watched] properties: episode: type: integer minimum: 1 maximum: 2147483647 watched: type: boolean MusicSourceRating: type: object required: [score, votes, url, source] properties: score: type: number minimum: 0 maximum: 10 votes: type: integer minimum: 0 url: type: string source: type: string enum: [musicbrainz, lidarr, theaudiodb, discogs] scale: type: integer enum: [5, 10] edition: type: string Blocklist: type: object properties: tmdbId: type: number example: 1 title: type: string externalId: type: string description: Canonical external title ID, or normalized magazine title. externalProvider: type: string enum: [ musicbrainz, openlibrary, openlibrary_edition, isbn, comicvine, lazylibrarian, ] mediaType: type: string enum: [movie, tv, music, book, comic, magazine] media: $ref: '#/components/schemas/MediaInfo' userId: type: number example: 1 Watchlist: type: object properties: id: type: integer example: 1 readOnly: true tmdbId: type: number example: 1 mbId: type: string description: MusicBrainz release group ID. externalId: type: string description: Open Library work ID, ComicVine volume ID, or magazine title. mediaType: type: string enum: [movie, tv, music, book, comic, magazine] ratingKey: type: string type: type: string title: type: string media: $ref: '#/components/schemas/MediaInfo' createdAt: type: string example: '2020-09-12T10:00:27.000Z' readOnly: true updatedAt: type: string example: '2020-09-12T10:00:27.000Z' readOnly: true requestedBy: $ref: '#/components/schemas/User' User: type: object properties: id: type: integer example: 1 readOnly: true email: type: string example: 'hey@itsme.com' readOnly: true username: type: string plexUsername: type: string readOnly: true plexToken: type: string readOnly: true jellyfinAuthToken: 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: themePalette: type: string description: Account theme preference. SeerrNG is adopted once on installation or upgrade; subsequent user choices survive later upgrades. username: type: string nullable: true example: 'Mr User' email: type: string example: 'user@example.com' locale: type: string nullable: true example: 'en' discoverRegion: type: string nullable: true example: 'US' streamingRegion: type: string nullable: true example: 'US' originalLanguage: type: string nullable: true example: 'en' preferredLanguages: type: object description: 'Universal preferred acquisition language with optional per-media overrides' additionalProperties: false properties: all: type: string nullable: true description: Clear the universal preference when null. example: 'en' movie: type: string nullable: true description: Null means any language; omit to inherit all. example: 'en' tv: type: string nullable: true description: Null means any language; omit to inherit all. example: 'ja' music: type: string nullable: true description: Null means any language; omit to inherit all. example: 'fr' book: type: string nullable: true description: Null means any language; omit to inherit all. example: 'es' movieQuotaLimit: type: number nullable: true description: 'Maximum number of movie requests allowed' example: 10 movieQuotaDays: type: number nullable: true description: 'Time period in days for movie quota' example: 30 tvQuotaLimit: type: number nullable: true description: 'Maximum number of TV requests allowed' example: 5 tvQuotaDays: type: number nullable: true description: 'Time period in days for TV quota' example: 14 softwareQuotaLimit: type: number nullable: true description: 'Maximum number of software requests allowed' example: 5 softwareQuotaDays: type: number nullable: true description: 'Time period in days for software quota' example: 7 globalSoftwareQuotaLimit: type: number nullable: true description: 'Global software quota limit setting' example: 5 globalSoftwareQuotaDays: type: number nullable: true description: 'Global software quota days setting' example: 7 globalMovieQuotaDays: type: number nullable: true description: 'Global movie quota days setting' example: 30 globalMovieQuotaLimit: type: number nullable: true description: 'Global movie quota limit setting' example: 10 globalTvQuotaLimit: type: number nullable: true description: 'Global TV quota limit setting' example: 5 globalTvQuotaDays: type: number nullable: true description: 'Global TV quota days setting' example: 14 watchlistSyncMovies: type: boolean nullable: true description: 'Enable watchlist sync for movies' example: true watchlistSyncTv: type: boolean nullable: true description: 'Enable watchlist sync for TV' example: false watchlistSyncMusic: type: boolean nullable: true description: 'Enable watchlist sync for music' example: true watchlistSyncBooks: type: boolean nullable: true description: 'Enable watchlist sync for books' example: true watchlistSyncComics: type: boolean nullable: true description: 'Enable watchlist sync for comics' example: false watchlistSyncMagazines: type: boolean nullable: true description: 'Enable watchlist sync for magazines' example: false cardTextVisibility: $ref: '#/components/schemas/CardTextVisibilitySettings' requestRootFolders: type: object description: Per-user root-folder defaults keyed by service type and instance id, such as radarr:1. additionalProperties: type: string detailDisclosureCastPinned: type: boolean description: 'Keep Cast open by default on supported detail pages' example: false detailDisclosureCrewPinned: type: boolean description: 'Keep Crew open by default on supported detail pages' example: false detailDisclosureSubjectTagsPinned: type: boolean description: 'Keep Subject Tags open by default on supported detail pages' example: false detailDisclosureOrder: type: object additionalProperties: false description: Independent per-media disclosure order for this user. properties: tv: type: array uniqueItems: true maxItems: 6 items: type: string enum: [cast, crew, subjectTags, details, mediaServer, overview] CardTextVisibilitySettings: type: object properties: movie: type: string nullable: true enum: - always - hover example: hover tv: type: string nullable: true enum: - always - hover example: hover album: type: string nullable: true enum: - always - hover example: always book: type: string nullable: true enum: - always - hover example: always DetailDisclosurePinSettings: type: object properties: details: type: boolean description: Keeps the additional details card open for the selected media type. Supported by the media-scoped endpoint. example: false collection: type: boolean description: Keeps movie collection panels open. Supported by the movie-scoped detail-disclosures endpoint. example: false cast: type: boolean example: false crew: type: boolean example: false artists: type: boolean example: false subjectTags: type: boolean example: false MainSettings: type: object properties: apiKey: type: string readOnly: true appLanguage: type: string example: en applicationTitle: type: string example: Seerr applicationUrl: type: string example: https://os.example.com hideAvailable: type: boolean example: false hideRequested: type: boolean example: false partialRequestsEnabled: type: boolean example: false localLogin: type: boolean example: true mediaServerType: type: number example: 1 newPlexLogin: type: boolean example: true defaultPermissions: type: number example: 32 enableSpecialEpisodes: type: boolean example: false includeAdult: type: boolean example: false openIdProviders: type: array items: $ref: '#/components/schemas/PublicOidcProvider' versionCheck: type: boolean example: false PublicOidcProvider: type: object readOnly: true properties: slug: type: string name: type: string logo: type: string required: - slug - name LinkedAccount: type: object properties: id: type: number username: type: string provider: $ref: '#/components/schemas/PublicOidcProvider' NetworkSettings: type: object properties: csrfProtection: type: boolean example: false forceIpv4First: type: boolean example: false trustProxy: type: boolean example: false tls: $ref: '#/components/schemas/TlsSettings' proxy: type: object properties: enabled: type: boolean example: false hostname: type: string example: '' port: type: number example: 8080 useSsl: type: boolean example: false user: type: string example: '' password: type: string example: '' bypassFilter: type: string example: '' bypassLocalAddresses: type: boolean example: true dnsCache: type: object properties: enabled: type: boolean example: false forceMinTtl: type: number example: 0 forceMaxTtl: type: number example: -1 TlsSettings: type: object properties: mode: type: string enum: [disabled, self-signed, provided] example: disabled httpsPort: type: integer minimum: 1 maximum: 65535 example: 5056 hosts: type: string example: localhost,127.0.0.1,::1 certificateFile: type: string example: '' keyFile: type: string example: '' caFile: type: string example: '' redirectHttpToHttps: type: boolean example: false allowHttpAuth: type: boolean example: false httpAuthAcknowledged: type: boolean example: false PlexLibrary: type: object properties: id: type: string name: type: string example: Movies enabled: type: boolean example: false type: type: string enum: [show, movie, music, book] 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 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 JellyfinLibrary: type: object properties: id: type: string name: type: string example: Movies enabled: type: boolean example: false type: type: string enum: [show, movie, music, book] required: - id - name - enabled JellyfinSettings: type: object properties: name: type: string example: 'Main Server' readOnly: true hostname: type: string example: 'http://my.jellyfin.host' externalHostname: type: string example: 'http://my.jellyfin.host' jellyfinForgotPasswordUrl: type: string example: 'http://my.jellyfin.host/web/index.html#!/forgotpassword.html' adminUser: type: string example: 'admin' adminPass: type: string example: 'mypassword' libraries: type: array readOnly: true items: $ref: '#/components/schemas/JellyfinLibrary' serverID: type: string readOnly: true bridgeLoginEnabled: type: boolean readOnly: true description: Whether linked Jellyfin users may sign in through the optional SeerrNG Jellyfin plugin. bridgeLoginGeneration: type: integer minimum: 0 readOnly: true description: Changes when bridge sign-in is enabled or disabled, revoking sessions created before the change. MetadataSettings: type: object properties: settings: type: object properties: tv: type: string enum: [tvdb, tmdb] example: 'tvdb' anime: type: string enum: [tvdb, tmdb] example: 'tvdb' 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 apiKey: type: string nullable: true externalUrl: type: string nullable: true ServarrConnectionSettings: type: object properties: id: type: number hostname: type: string example: '127.0.0.1' port: type: number example: 8787 apiKey: type: string example: 'exampleapikey' useSsl: type: boolean example: false baseUrl: type: string required: - hostname - port - apiKey AudiobookshelfSettings: type: object description: Read-only Audiobookshelf book library connection used for audiobook availability. properties: id: type: integer minimum: 1 name: type: string maxLength: 128 hostname: type: string maxLength: 512 port: type: integer minimum: 1 maximum: 65535 useSsl: type: boolean apiKey: type: string description: User API token. Responses redact this value. baseUrl: type: string maxLength: 512 externalUrl: type: string maxLength: 512 libraryId: type: string maxLength: 256 libraryName: type: string maxLength: 256 syncEnabled: type: boolean required: - name - hostname - port - apiKey - libraryId - libraryName - syncEnabled AudiobookshelfLibrary: type: object properties: id: type: string name: type: string numBooks: type: integer minimum: 0 required: [id, name] 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' is4k: type: boolean example: false 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: - name - hostname - port - apiKey - useSsl - activeProfileId - activeProfileName - activeDirectory - is4k - isDefault MylarSettings: type: object properties: id: type: number example: 0 readOnly: true name: type: string example: 'Mylar' hostname: type: string example: '127.0.0.1' port: type: number example: 8090 apiKey: type: string example: 'exampleapikey' useSsl: type: boolean example: false baseUrl: type: string isDefault: type: boolean example: false externalUrl: type: string example: http://mylar.example.com tags: type: array items: type: number syncEnabled: type: boolean example: false preventSearch: type: boolean example: false rootFolder: type: string example: '/comics' required: - name - hostname - port - apiKey - useSsl - isDefault - syncEnabled KapowarrSettings: type: object properties: id: type: number example: 0 readOnly: true name: type: string example: 'Kapowarr' hostname: type: string example: '127.0.0.1' port: type: number example: 5656 apiKey: type: string example: 'exampleapikey' useSsl: type: boolean example: false baseUrl: type: string isDefault: type: boolean example: false externalUrl: type: string example: http://kapowarr.example.com tags: type: array items: type: number syncEnabled: type: boolean example: false preventSearch: type: boolean example: false rootFolder: type: string example: '/comics' required: - name - hostname - port - apiKey - useSsl - isDefault - syncEnabled - rootFolder BackIssueSettings: type: object properties: id: type: number example: 0 readOnly: true name: type: string example: 'BackIssue' hostname: type: string example: '127.0.0.1' port: type: number example: 8787 apiKey: type: string example: 'exampleapikey' useSsl: type: boolean example: false baseUrl: type: string isDefault: type: boolean example: false externalUrl: type: string example: http://backissue.example.com tags: type: array items: type: number syncEnabled: type: boolean example: false preventSearch: type: boolean example: false required: - name - hostname - port - apiKey - useSsl - isDefault - syncEnabled LazyLibrarianSettings: type: object properties: id: type: number readOnly: true name: type: string example: 'Magazine Library' hostname: type: string example: '127.0.0.1' port: type: number example: 5299 apiKey: type: string useSsl: type: boolean baseUrl: type: string isDefault: type: boolean externalUrl: type: string tags: type: array items: type: number syncEnabled: type: boolean preventSearch: type: boolean required: - name - hostname - port - apiKey - useSsl - isDefault - syncEnabled 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 is4k: type: boolean example: false 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: - name - hostname - port - apiKey - useSsl - activeProfileId - activeProfileName - activeDirectory - is4k - enableSeasonFolders - isDefault SportarrSettings: type: object description: Sportarr connection and quality-profile settings. API keys are redacted in responses. properties: id: type: integer minimum: 0 maximum: 1000000 readOnly: true name: type: string maxLength: 512 hostname: type: string maxLength: 512 port: type: integer minimum: 1 maximum: 65535 apiKey: type: string maxLength: 512 description: Sportarr API key. Responses redact the configured value. useSsl: type: boolean baseUrl: type: string maxLength: 512 description: Optional relative URL base. activeProfileId: type: integer minimum: 1 maximum: 1000000 activeProfileName: type: string maxLength: 512 isDefault: type: boolean externalUrl: type: string maxLength: 512 format: uri nullable: true required: - name - hostname - port - apiKey - useSsl - activeProfileId - activeProfileName - isDefault ServarrTag: type: object properties: id: type: number example: 1 label: type: string example: A Label QuotaStatus: type: object required: [used, restricted] properties: days: type: number example: 7 limit: type: number example: 10 used: type: number example: 6 remaining: type: number example: 4 restricted: type: boolean example: false ProwlarrSearchResult: type: object required: [ title, indexer, indexerId, size, seeders, leechers, grabs, protocol, publishDate, infoUrl, categories, ] properties: title: type: string indexer: type: string indexerId: type: integer nullable: true size: type: number nullable: true seeders: type: number nullable: true leechers: type: number nullable: true grabs: type: number nullable: true protocol: type: string publishDate: type: string format: date-time nullable: true infoUrl: type: string format: uri nullable: true categories: type: array items: type: object required: [id, name] properties: id: type: integer name: type: string ProwlarrCategoryIds: type: array minItems: 1 maxItems: 32 items: type: integer minimum: 1 maximum: 1000000 ProwlarrCategoryMappings: type: object required: [ movie, tv, music, ebook, audiobook, comic, magazine, retro, modern, game, ] properties: movie: $ref: '#/components/schemas/ProwlarrCategoryIds' tv: $ref: '#/components/schemas/ProwlarrCategoryIds' music: $ref: '#/components/schemas/ProwlarrCategoryIds' ebook: $ref: '#/components/schemas/ProwlarrCategoryIds' audiobook: $ref: '#/components/schemas/ProwlarrCategoryIds' comic: $ref: '#/components/schemas/ProwlarrCategoryIds' magazine: $ref: '#/components/schemas/ProwlarrCategoryIds' retro: $ref: '#/components/schemas/ProwlarrCategoryIds' modern: $ref: '#/components/schemas/ProwlarrCategoryIds' game: $ref: '#/components/schemas/ProwlarrCategoryIds' ProwlarrIndexerCategorySummary: type: object required: [id, name, indexerCount] properties: id: type: integer name: type: string indexerCount: type: integer ProwlarrInventory: type: object required: [ success, totalIndexers, enabledSearchableIndexers, categories, categoryCatalog, ] properties: success: type: boolean version: type: string totalIndexers: type: integer enabledSearchableIndexers: type: integer categories: type: object additionalProperties: type: integer categoryCatalog: type: array items: $ref: '#/components/schemas/ProwlarrIndexerCategorySummary' diagnostics: type: array description: Results of the explicit per-indexer connection test. items: $ref: '#/components/schemas/ProwlarrIndexerDiagnostic' ProwlarrIndexerDiagnostic: type: object required: [name, layer, success] properties: id: type: integer minimum: 1 name: type: string layer: type: string enum: [indexer-feed] success: type: boolean status: type: integer error: type: string disabledTill: type: string format: date-time nullable: true mostRecentFailure: type: string format: date-time nullable: true ProwlarrSearchResultsResponse: type: object required: [category, query, offset, limit, results, hasMore] properties: category: type: string enum: [ movie, tv, music, ebook, audiobook, comic, magazine, retro, modern, game, ] query: type: string offset: type: integer limit: type: integer hasMore: type: boolean results: type: array items: $ref: '#/components/schemas/ProwlarrSearchResult' SoftwareRequest: type: object required: [id, category, provider, status, title, attempt, createdAt, updatedAt] properties: id: type: integer requestedBy: type: object nullable: true properties: id: type: integer displayName: type: string avatar: type: string nullable: true approvedById: type: integer nullable: true category: type: string enum: [retro, modern, game] provider: type: string enum: [romarr, questarr] description: Acquisition provider. PC games use QuestarrNG; emulation requests use ROMarrNG. status: type: string enum: [ pending, approved, searching, downloading, importing, available, failed, declined, cancelled, ] title: type: string summary: type: string nullable: true coverUrl: type: string nullable: true catalogId: type: integer nullable: true actions: $ref: '#/components/schemas/SoftwareRequestActions' platform: type: object nullable: true properties: slug: type: string name: type: string nullable: true catalogId: type: integer nullable: true variant: type: object nullable: true properties: operatingSystem: type: string enum: [windows, linux, macos] architecture: type: string enum: [x64, arm64, x86, universal] attempt: type: integer percent: type: number nullable: true error: type: string nullable: true createdAt: type: string format: date-time updatedAt: type: string format: date-time SoftwareRequestAsset: type: object required: [id, name, size, url] properties: id: type: string name: type: string size: type: integer minimum: 0 url: type: string description: Same-origin authenticated SeerrNG download route. SoftwareRequestStatusEvent: type: object required: [id, requestId, requestedById, status, fingerprint, createdAt] properties: id: type: integer requestId: type: integer requestedById: type: integer status: type: string enum: [ pending, approved, searching, downloading, importing, available, failed, declined, cancelled, ] message: type: string nullable: true percent: type: number nullable: true fingerprint: type: string createdAt: type: string format: date-time SoftwareRequestStatusResult: type: object required: [request, status, message, assets] properties: request: $ref: '#/components/schemas/SoftwareRequest' status: type: string enum: [ pending, approved, searching, downloading, importing, available, failed, declined, cancelled, ] message: type: string nullable: true assets: type: array items: $ref: '#/components/schemas/SoftwareRequestAsset' SoftwareRequestPageInfo: type: object required: [page, pages, pageSize, results] properties: page: type: integer pages: type: integer pageSize: type: integer results: type: integer description: Number of requests on the current page. SoftwareRequestsResponse: type: object required: [results, pageInfo] properties: results: type: array items: $ref: '#/components/schemas/SoftwareRequestStatusResult' pageInfo: $ref: '#/components/schemas/SoftwareRequestPageInfo' SoftwareRequestDetailResponse: type: object required: [request, status, message, history, assets] properties: request: $ref: '#/components/schemas/SoftwareRequest' status: type: string enum: [ pending, approved, searching, downloading, importing, available, failed, declined, cancelled, ] message: type: string nullable: true history: type: array items: $ref: '#/components/schemas/SoftwareRequestStatusEvent' assets: type: array items: $ref: '#/components/schemas/SoftwareRequestAsset' SoftwareRequestMutationResponse: type: object required: [request] properties: request: $ref: '#/components/schemas/SoftwareRequest' status: type: string enum: [ pending, approved, searching, downloading, importing, available, failed, declined, cancelled, ] assets: type: array items: $ref: '#/components/schemas/SoftwareRequestAsset' KapowarrRootFolder: type: object required: [id, path] properties: id: type: integer path: type: string KapowarrRootFoldersResponse: type: object required: [defaultRootFolder, rootFolders] properties: defaultRootFolder: type: string nullable: true rootFolders: type: array items: $ref: '#/components/schemas/KapowarrRootFolder' PublicSettings: type: object required: - initialized - plexClientIdentifier properties: initialized: type: boolean example: false plexClientIdentifier: type: string format: uuid description: Instance Plex OAuth client identifier example: 6919275e-142a-48d8-be6b-93594cbd4626 magazinesEnabled: type: boolean description: Whether a LazyLibrarian instance is configured. example: true sportsEnabled: type: boolean description: Whether a Sportarr instance is configured. example: false ebookServiceEnabled: type: boolean description: Whether a Bookshelf-compatible ebook service is configured. example: true audiobookServiceEnabled: type: boolean description: Whether a Bookshelf-compatible audiobook service is configured. example: false romarrEnabled: type: boolean description: Whether a ROMarrNG instance is configured. example: true enabledMediaCategories: type: object description: Administrator-controlled visibility and request availability for each media category. additionalProperties: false properties: movie: type: boolean tv: type: boolean music: type: boolean ebook: type: boolean audiobook: type: boolean comic: type: boolean magazine: type: boolean sports: type: boolean retro: type: boolean modern: type: boolean game: type: boolean 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 mediaInfo: $ref: '#/components/schemas/MediaInfo' 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 mediaInfo: $ref: '#/components/schemas/MediaInfo' MusicResult: type: object required: - mbId - mediaType - title properties: mbId: type: string example: f5093c06-23e3-404f-aeaa-40f72885ee3a mediaType: type: string enum: [music] title: type: string example: Album Title artist: type: string example: Artist Name artistMbId: type: string example: b10bbbfc-cf9e-42e0-be17-e2c3e1d2600d posterPath: type: string releaseDate: type: string availableServices: type: array description: Available Lidarr destinations and their configured quality-profile labels. items: type: object required: - serverId - quality properties: serverId: type: number quality: type: string example: FLAC trackAvailability: type: object description: Recording MusicBrainz IDs with files in each configured Lidarr quality. properties: mp3: type: array items: type: string format: uuid flac: type: array items: type: string format: uuid mediaInfo: $ref: '#/components/schemas/MediaInfo' ArtistResult: type: object required: - id - mediaType - name properties: id: type: string example: b10bbbfc-cf9e-42e0-be17-e2c3e1d2600d mediaType: type: string enum: [artist] name: type: string example: Artist Name type: type: string example: Person artistThumb: type: string nullable: true artistBackdrop: type: string nullable: true BookResult: type: object required: - id - mediaType - title properties: id: type: string example: OL27448W mediaType: type: string enum: [book] title: type: string example: Book Title author: type: string example: Author Name authorId: type: string example: OL23919A firstPublishYear: type: number example: 1965 posterPath: type: string isbn13: type: string example: '9780441478125' editionId: type: string example: OL8934157M series: type: array items: $ref: '#/components/schemas/BookSeriesReference' audiobookDuration: type: number description: Audiobook duration in seconds, when Bookshelf provides it. narrators: type: array items: type: string mediaInfo: $ref: '#/components/schemas/MediaInfo' BookSeriesReference: type: object required: - id - title properties: id: type: string title: type: string position: type: string BookSeriesDetails: type: object required: - id - title - books properties: id: type: string title: type: string description: type: string books: type: array items: $ref: '#/components/schemas/BookResult' ComicResult: type: object required: - id - mediaType - title properties: id: type: string example: '1234' description: ComicVine volume ID. mediaType: type: string enum: [comic] title: type: string example: Batman onUserWatchlist: type: boolean aliases: type: array items: type: string publisher: type: string example: DC Comics startYear: type: string example: '1940' issueCount: type: number example: 904 posterPath: type: string deck: type: string siteDetailUrl: type: string mediaInfo: $ref: '#/components/schemas/MediaInfo' ComicServiceOption: type: object required: - id - name - isDefault - backendType properties: id: type: number example: 1 name: type: string example: Mylar3 isDefault: type: boolean backendType: type: string enum: [mylar, kapowarr, backissue] MagazineServiceOption: type: object required: - id - name - isDefault properties: id: type: number example: 1 name: type: string example: LazyLibrarian isDefault: type: boolean SportarrServiceOption: type: object required: [id, name, isDefault, profileName] properties: id: type: integer minimum: 0 maximum: 1000000 name: type: string isDefault: type: boolean profileName: type: string MagazineIssueReference: type: object required: - id - available properties: id: type: string date: type: string available: type: boolean MagazineResult: type: object required: - id - provider - mediaType - title properties: id: type: string provider: type: string enum: [lazylibrarian] mediaType: type: string enum: [magazine] title: type: string posterPath: type: string description: SeerrNG magazine cover URL when LazyLibrarian has a cached cover. status: type: string latestIssue: type: string issueCount: type: number mediaInfo: $ref: '#/components/schemas/MediaInfo' MagazineDetails: allOf: - $ref: '#/components/schemas/MagazineResult' - type: object required: - issues properties: onUserWatchlist: type: boolean issues: type: array items: $ref: '#/components/schemas/MagazineIssueReference' SportarrResult: type: object required: - id - provider - mediaType - title - overview - requestable - libraryState - eventsAvailable properties: id: type: string pattern: '^lg-[0-9]{1,20}$' description: Sportarr's canonical external league identity. provider: type: string enum: [sportarr] mediaType: type: string enum: [sports] title: type: string overview: type: string sport: type: string country: type: string year: type: integer posterPath: type: string description: Authenticated SeerrNG image-proxy path. requestable: type: boolean libraryState: type: string enum: [not-added, monitored, unmonitored, requested] status: type: integer description: SeerrNG media availability status when monitored or requested. sportarrId: type: integer description: Installation-local Sportarr library ID; not a portable league identity. eventsAvailable: type: boolean mediaInfo: $ref: '#/components/schemas/MediaInfo' SportarrEvent: type: object required: [id, title, monitored, hasFile, fileCount] properties: id: type: integer externalId: type: string title: type: string sport: type: string leagueId: type: integer leagueName: type: string season: type: string seasonNumber: type: integer episodeNumber: type: integer eventDate: type: string broadcastDate: type: string broadcastTimezone: type: string monitored: type: boolean hasFile: type: boolean fileCount: type: integer minimum: 0 fileSize: type: number minimum: 0 quality: type: string SportarrEventPage: type: object required: [eventsAvailable, page, pageSize, totalRecords, totalPages, results] properties: eventsAvailable: type: boolean page: type: integer pageSize: type: integer totalRecords: type: integer minimum: 0 totalPages: type: integer minimum: 0 results: type: array items: $ref: '#/components/schemas/SportarrEvent' AuthorResult: type: object properties: id: type: string example: OL23919A mediaType: type: string enum: [author] provider: type: string enum: [openlibrary, bookshelf] name: type: string example: Ursula K. Le Guin topWork: type: string workCount: type: number biography: type: string birthDate: type: string deathDate: type: string posterPath: type: string works: type: array items: $ref: '#/components/schemas/BookResult' pagination: type: object properties: limit: type: number offset: type: number totalItems: type: number AuthorWorksResponse: type: object properties: works: type: array items: $ref: '#/components/schemas/BookResult' pagination: type: object properties: limit: type: number offset: type: number totalItems: type: number BulkMediaRequestItem: type: object properties: mediaId: type: string example: OL27448W title: type: string isbn13: type: string example: '9780441478125' editionId: type: string example: OL8934157M authorId: type: string example: OL23919A required: - mediaId BulkMediaRequestBody: type: object properties: mediaType: type: string enum: [music, book] items: type: array items: $ref: '#/components/schemas/BulkMediaRequestItem' format: type: string enum: [ebook, audiobook, both] description: Book request format. serverId: type: number profileId: type: number metadataProfileId: type: number rootFolder: type: string userId: type: number nullable: true description: >- Optional requester ID for all created requests. Omit this field to use the authenticated user. When supplied, requests are attributed to that account. Supplying it requires both `MANAGE_USERS` and `MANAGE_REQUESTS`; otherwise the API returns HTTP 403. tags: type: array items: type: number required: - mediaType - items BulkMediaRequestResult: type: object properties: mediaId: type: string title: type: string reason: type: string required: - mediaId - reason BulkMediaRequestResponse: type: object properties: created: type: array items: $ref: '#/components/schemas/MediaRequest' skipped: type: array items: $ref: '#/components/schemas/BulkMediaRequestResult' failed: type: array items: $ref: '#/components/schemas/BulkMediaRequestResult' PersonMovieBulkRequestResult: type: object properties: movieId: type: integer minimum: 1 maximum: 1000000000 reason: type: string required: - movieId - reason PersonMovieBulkRequestBody: type: object properties: movieIds: type: array minItems: 1 maxItems: 100 description: Movie metadata IDs. Duplicate IDs are accepted and deduplicated before processing. items: type: integer minimum: 1 maximum: 1000000000 required: - movieIds PersonMovieBulkRequestResponse: type: object properties: created: type: array description: Movie IDs whose requests were created. items: type: integer minimum: 1 maximum: 1000000000 skipped: type: array description: Already-requested or blocklisted movies that were skipped. items: $ref: '#/components/schemas/PersonMovieBulkRequestResult' failed: type: array description: Movie requests that could not be processed. items: $ref: '#/components/schemas/PersonMovieBulkRequestResult' stoppedReason: type: string description: Present when a quota or service-configuration error stopped the remaining requests. required: - created - skipped - failed AssociationEdge: type: object properties: weight: type: number example: 0.85 type: type: string enum: [similar, recommended, shared-person, shared-genre] reason: type: string example: Recommended for fans node: oneOf: - $ref: '#/components/schemas/MovieResult' - $ref: '#/components/schemas/TvResult' - $ref: '#/components/schemas/MusicResult' - $ref: '#/components/schemas/ArtistResult' - $ref: '#/components/schemas/BookResult' - $ref: '#/components/schemas/PersonResult' required: - weight - type - reason - node AssociationGraph: type: object properties: root: type: object properties: mediaType: type: string enum: [movie, tv, album, artist, book] id: type: string title: type: string required: - mediaType - id - title edges: type: array items: $ref: '#/components/schemas/AssociationEdge' required: - root - edges 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' - $ref: '#/components/schemas/MusicResult' - $ref: '#/components/schemas/BookResult' 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 spokenLanguages: type: array items: $ref: '#/components/schemas/SpokenLanguage' status: type: string tagline: type: string title: type: string video: type: boolean voteAverage: type: number voteCount: type: number credits: type: object properties: cast: type: array items: $ref: '#/components/schemas/Cast' crew: type: array items: $ref: '#/components/schemas/Crew' 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' mediaInfo: $ref: '#/components/schemas/MediaInfo' 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 SeasonEpisodeSelection: type: object properties: seasonNumber: type: number minimum: 0 episodeNumbers: type: array description: Omit to select the entire season. items: type: number minimum: 1 required: - seasonNumber 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 spokenLanguages: type: array items: $ref: '#/components/schemas/SpokenLanguage' seasons: type: array items: $ref: '#/components/schemas/Season' status: type: string tagline: type: string type: type: string voteAverage: type: number voteCount: type: number credits: type: object properties: cast: type: array items: $ref: '#/components/schemas/Cast' crew: type: array items: $ref: '#/components/schemas/Crew' externalIds: $ref: '#/components/schemas/ExternalIds' keywords: type: array items: $ref: '#/components/schemas/Keyword' mediaInfo: $ref: '#/components/schemas/MediaInfo' watchProviders: type: array items: $ref: '#/components/schemas/WatchProviders' RequestStatusSnapshot: type: object properties: stage: type: string enum: [ requested, approved, searching, downloading, importing, library, available, unavailable, failed, declined, cancelled, ] attempt: type: integer minimum: 0 percent: type: number minimum: 0 maximum: 100 nullable: true description: Null when the connected download service does not provide complete usable size data. size: type: number nullable: true sizeLeft: type: number nullable: true estimatedCompletionTime: type: string format: date-time nullable: true downloadCount: type: integer minimum: 0 downloadId: type: string nullable: true description: Stable opaque identifier for grouping queue observations; it is not the downloader's raw queue ID. service: type: string nullable: true message: type: string observedAt: type: string format: date-time isTerminal: type: boolean needsAttention: type: boolean retryable: type: boolean required: - stage - attempt - percent - size - sizeLeft - estimatedCompletionTime - downloadCount - downloadId - service - message - observedAt - isTerminal - needsAttention - retryable RequestStatusHistoryItem: type: object properties: id: type: integer requestId: type: integer requestedById: type: integer mediaId: type: integer mediaType: type: string enum: [movie, tv, music, book, comic, magazine, sports] stage: type: string attempt: type: integer format: type: string nullable: true service: type: string nullable: true message: type: string nullable: true percent: type: number nullable: true size: type: number nullable: true sizeLeft: type: number nullable: true estimatedCompletionTime: type: string format: date-time nullable: true downloadCount: type: integer downloadId: type: string nullable: true createdAt: type: string format: date-time required: - id - requestId - requestedById - mediaId - mediaType - stage - attempt - downloadCount - createdAt RequestStatusHistoryPage: type: object properties: results: type: array items: $ref: '#/components/schemas/RequestStatusHistoryItem' total: type: integer required: - results - total RequestStatusPage: type: object properties: pageInfo: $ref: '#/components/schemas/PageInfo' results: type: array items: type: object properties: request: $ref: '#/components/schemas/MediaRequest' status: $ref: '#/components/schemas/RequestStatusSnapshot' required: - request - status counts: type: object properties: total: type: integer active: type: integer incomplete: type: integer attention: type: integer completed: type: integer unavailable: type: integer failed: type: integer required: - total - active - incomplete - attention - completed - unavailable - failed olderCount: type: integer description: Number of requests in the same scope that predate the selected rolling time window. required: - pageInfo - results - counts - olderCount RequestStatusDetail: type: object properties: request: $ref: '#/components/schemas/MediaRequest' current: $ref: '#/components/schemas/RequestStatusSnapshot' history: $ref: '#/components/schemas/RequestStatusHistoryPage' required: - request - current - history MediaRequest: type: object properties: id: type: number example: 123 readOnly: true status: type: number example: 0 description: Status of the request. 1 = PENDING APPROVAL, 2 = APPROVED, 3 = DECLINED readOnly: true media: $ref: '#/components/schemas/MediaInfo' createdAt: type: string example: '2020-09-12T10:00:27.000Z' readOnly: true updatedAt: type: string example: '2020-09-12T10:00:27.000Z' readOnly: true requestedBy: $ref: '#/components/schemas/User' modifiedBy: anyOf: - $ref: '#/components/schemas/User' - type: string nullable: true is4k: type: boolean example: false watchAheadEpisodeCount: type: integer minimum: 0 maximum: 5 description: Number of upcoming episodes to keep requested by the Plex, Jellyfin, or Emby Episode Queue. watchAheadParentRequestId: type: integer nullable: true description: Parent TV request ID when this request was generated by watch-ahead. serverId: type: number profileId: type: number rootFolder: type: string metadataProfileId: type: number tags: type: array items: type: number bookFormat: type: string enum: [ebook, audiobook, both] nullable: true ignoreQuota: type: boolean example: false description: If true, this request will not count against the user's quota. Requires MANAGE_REQUESTS permission. required: - id - status MediaInfo: type: object properties: id: type: number readOnly: true tmdbId: type: number readOnly: true nullable: true tvdbId: type: number readOnly: true nullable: true mbId: type: string readOnly: true nullable: true mediaType: type: string enum: [movie, tv, music, book, comic, magazine, sports] serviceId: type: number nullable: true externalServiceId: type: number nullable: true externalServiceSlug: type: string nullable: true audiobookServiceId: type: number nullable: true audiobookExternalServiceId: type: number nullable: true audiobookExternalServiceSlug: type: string nullable: true status: type: number example: 0 description: Availability of the media. 1 = `UNKNOWN`, 2 = `PENDING`, 3 = `PROCESSING`, 4 = `PARTIALLY_AVAILABLE`, 5 = `AVAILABLE`, 6 = `DELETED` requests: type: array readOnly: true items: $ref: '#/components/schemas/MediaRequest' createdAt: type: string example: '2020-09-12T10:00:27.000Z' readOnly: true updatedAt: type: string example: '2020-09-12T10:00:27.000Z' readOnly: true Cast: type: object properties: id: type: number example: 123 castId: type: number example: 1 character: type: string example: Some Character Name creditId: type: string gender: type: number name: type: string example: Some Persons Name order: type: number profilePath: type: string nullable: true Crew: type: object properties: id: type: number example: 123 creditId: type: string gender: type: number name: type: string example: Some Persons Name job: type: string department: type: string profilePath: type: string nullable: true 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 ServiceRootFolder: type: object properties: id: type: number example: 1 path: type: string example: /media/library freeSpace: type: number totalSpace: type: number ServiceTag: type: object properties: id: type: number example: 1 label: type: string example: requested LidarrSettings: allOf: - $ref: '#/components/schemas/RadarrSettings' - type: object properties: activeMetadataProfileId: type: number example: 1 activeMetadataProfileName: type: string example: Standard tags: type: array items: type: number ReadarrSettings: allOf: - $ref: '#/components/schemas/LidarrSettings' - type: object properties: serviceType: type: string enum: [ebook, audiobook] example: ebook provider: type: string enum: - hardcover - softcover - unknown legacyWarning: type: string metadataSource: type: string BookshelfMediaMoveAuthor: type: object required: [id, name, path, currentFormatPath, bookFileCount] properties: id: type: integer name: type: string path: type: string currentFormatPath: type: string bookFileCount: type: integer minimum: 0 BookshelfMediaMoveRootFolder: type: object required: [id, path, accessible] properties: id: type: integer path: type: string accessible: type: boolean BookshelfMediaMoveConfiguration: type: object required: - serviceId - serviceName - configuredFormat - format - truncated - authors - rootFolders properties: serviceId: type: integer serviceName: type: string configuredFormat: type: string enum: [ebook, audiobook] format: type: string enum: [ebook, audiobook] truncated: type: boolean description: True when more than 10,000 author records were found. authors: type: array items: $ref: '#/components/schemas/BookshelfMediaMoveAuthor' rootFolders: type: array items: $ref: '#/components/schemas/BookshelfMediaMoveRootFolder' BookshelfMediaMovePreviewRequest: type: object required: [authorIds, format, destinationRootPath] properties: authorIds: type: array minItems: 1 maxItems: 1000 uniqueItems: true items: type: integer minimum: 1 format: type: string enum: [ebook, audiobook] sourceRootPath: type: string maxLength: 4096 destinationRootPath: type: string maxLength: 4096 BookshelfMediaMoveStartRequest: allOf: - $ref: '#/components/schemas/BookshelfMediaMovePreviewRequest' - type: object required: [previewToken] properties: previewToken: type: string minLength: 1 maxLength: 512 BookshelfMediaMoveFile: type: object required: - fileType - sourcePath - destinationPath - status - sourceExists - destinationExists - size properties: fileType: type: string enum: [media, metadata, extra] sourcePath: type: string destinationPath: type: string status: type: string enum: [ready, missing, alreadyAtDestination, conflict] sourceExists: type: boolean destinationExists: type: boolean size: type: integer minimum: 0 BookshelfMediaMoveAuthorPreview: type: object required: - authorId - authorName - format - sourcePath - destinationPath - mediaFileCount - sidecarFileCount - missingFileCount - alreadyAtDestinationCount - totalSize - requiredCopyBytes - canMove - warnings - conflicts - files properties: authorId: type: integer authorName: type: string format: type: string enum: [ebook, audiobook] sourcePath: type: string destinationPath: type: string mediaFileCount: type: integer minimum: 0 sidecarFileCount: type: integer minimum: 0 missingFileCount: type: integer minimum: 0 alreadyAtDestinationCount: type: integer minimum: 0 totalSize: type: integer minimum: 0 requiredCopyBytes: type: integer minimum: 0 availableSpace: type: integer minimum: 0 canMove: type: boolean warnings: type: array items: type: string conflicts: type: array items: type: string files: type: array items: $ref: '#/components/schemas/BookshelfMediaMoveFile' BookshelfMediaMoveBatchPreview: type: object required: - format - destinationRootPath - previewToken - authorCount - mediaFileCount - sidecarFileCount - missingFileCount - totalSize - requiredCopyBytes - canMove - warnings - conflicts - authors properties: format: type: string enum: [ebook, audiobook] destinationRootPath: type: string previewToken: type: string authorCount: type: integer mediaFileCount: type: integer sidecarFileCount: type: integer missingFileCount: type: integer totalSize: type: integer requiredCopyBytes: type: integer availableSpace: type: integer canMove: type: boolean warnings: type: array items: type: string conflicts: type: array items: type: string authors: type: array items: $ref: '#/components/schemas/BookshelfMediaMoveAuthorPreview' BookshelfMediaMoveCommand: type: object required: [id, name, status] properties: id: type: integer name: type: string status: type: string enum: [queued, started, completed, failed, aborted, cancelled, orphaned] message: type: string progress: type: number minimum: 0 maximum: 100 queued: type: string started: type: string ended: type: string ServarrServiceDetails: type: object properties: server: oneOf: - $ref: '#/components/schemas/RadarrSettings' - $ref: '#/components/schemas/SonarrSettings' - $ref: '#/components/schemas/LidarrSettings' - $ref: '#/components/schemas/ReadarrSettings' profiles: type: array items: $ref: '#/components/schemas/ServiceProfile' metadataProfiles: type: array items: $ref: '#/components/schemas/ServiceProfile' rootFolders: type: array items: $ref: '#/components/schemas/ServiceRootFolder' languageProfiles: nullable: true type: array items: $ref: '#/components/schemas/ServiceProfile' tags: type: array items: $ref: '#/components/schemas/ServiceTag' provider: type: string enum: - hardcover - softcover - unknown legacyWarning: type: string metadataSource: type: string PageInfo: type: object properties: page: type: number example: 1 pages: type: number example: 10 pageSize: type: number example: 25 results: type: number example: 100 DiscordSettings: type: object properties: enabled: type: boolean example: false types: type: number example: 2 options: type: object properties: botUsername: type: string botAvatarUrl: type: string webhookUrl: type: string webhookRoleId: type: string enableMentions: type: boolean SlackSettings: type: object properties: enabled: type: boolean example: false types: type: number example: 2 options: type: object properties: webhookUrl: type: string WebPushSettings: type: object properties: enabled: type: boolean example: false types: type: number example: 2 WebhookSettings: type: object properties: enabled: type: boolean example: false types: type: number example: 2 options: type: object properties: webhookUrl: type: string authHeader: type: string jsonPayload: type: string supportVariables: type: boolean example: false TelegramSettings: type: object properties: enabled: type: boolean example: false types: type: number example: 2 options: type: object properties: botUsername: type: string botAPI: type: string chatId: type: string messageThreadId: type: string sendSilently: type: boolean PushbulletSettings: type: object properties: enabled: type: boolean example: false types: type: number example: 2 options: type: object properties: accessToken: type: string channelTag: type: string nullable: true PushoverSettings: type: object properties: enabled: type: boolean example: false types: type: number example: 2 options: type: object properties: accessToken: type: string userToken: type: string sound: type: string GotifySettings: type: object properties: enabled: type: boolean example: false types: type: number example: 2 options: type: object properties: url: type: string token: type: string NtfySettings: type: object properties: enabled: type: boolean example: false types: type: number example: 2 options: type: object properties: url: type: string topic: type: string tags: type: string authMethodUsernamePassword: type: boolean username: type: string password: type: string authMethodToken: type: boolean token: type: string priority: type: number locale: type: string NotificationEmailSettings: type: object properties: enabled: type: boolean example: false types: type: number example: 2 options: type: object properties: emailFrom: type: string example: no-reply@example.com senderName: type: string example: Seerr smtpHost: type: string example: 127.0.0.1 smtpPort: type: number example: 465 secure: type: boolean example: false ignoreTls: type: boolean example: false requireTls: type: boolean example: false authUser: type: string nullable: true authPass: type: string nullable: true allowSelfSigned: type: boolean example: false 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 PersonDetails: type: object properties: id: type: number example: 1 name: type: string deathday: type: string knownForDepartment: type: string alsoKnownAs: type: array items: type: string gender: type: string biography: type: string popularity: type: string placeOfBirth: type: string profilePath: type: string adult: type: boolean imdbId: type: string homepage: type: string CreditCast: type: object properties: id: type: number example: 1 originalLanguage: type: string episodeCount: type: number overview: type: string originCountry: type: array items: type: string originalName: type: string voteCount: type: number name: type: string mediaType: type: string popularity: type: number creditId: type: string backdropPath: type: string firstAirDate: type: string voteAverage: type: number genreIds: type: array items: type: number posterPath: type: string originalTitle: type: string video: type: boolean title: type: string adult: type: boolean releaseDate: type: string character: type: string mediaInfo: $ref: '#/components/schemas/MediaInfo' CreditCrew: type: object properties: id: type: number example: 1 originalLanguage: type: string episodeCount: type: number overview: type: string originCountry: type: array items: type: string originalName: type: string voteCount: type: number name: type: string mediaType: type: string popularity: type: number creditId: type: string backdropPath: type: string firstAirDate: type: string voteAverage: type: number genreIds: type: array items: type: number posterPath: type: string originalTitle: type: string video: type: boolean title: type: string adult: type: boolean releaseDate: type: string department: type: string job: type: string mediaInfo: $ref: '#/components/schemas/MediaInfo' Keyword: type: object properties: id: type: number example: 1 name: type: string example: 'anime' SpokenLanguage: type: object properties: englishName: type: string example: 'English' nullable: true iso_639_1: type: string example: 'en' name: type: string example: 'English' Collection: type: object properties: id: type: number example: 123 name: type: string example: A Movie Collection overview: type: string example: Overview of collection posterPath: type: string backdropPath: type: string parts: type: array items: $ref: '#/components/schemas/MovieResult' 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 UserSettingsNotifications: type: object properties: notificationTypes: $ref: '#/components/schemas/NotificationAgentTypes' emailEnabled: type: boolean pgpKey: type: string nullable: true discordEnabled: type: boolean discordEnabledTypes: type: number nullable: true discordIds: type: array items: type: string nullable: true pushbulletAccessToken: type: string nullable: true pushoverApplicationToken: type: string nullable: true pushoverUserKey: type: string nullable: true pushoverSound: type: string nullable: true telegramEnabled: type: boolean telegramBotUsername: type: string nullable: true telegramChatId: type: string nullable: true telegramMessageThreadId: type: string nullable: true telegramSendSilently: type: boolean nullable: true NotificationAgentTypes: type: object properties: discord: type: number email: type: number pushbullet: type: number pushover: type: number slack: type: number telegram: type: number webhook: type: number webpush: type: number 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 Issue: type: object properties: id: type: number example: 1 issueType: type: number example: 1 issueSubtype: type: string nullable: true example: missing_issue problemSeason: type: number example: 2 problemEpisode: type: number example: 4 problemEpisodes: type: array nullable: true items: type: number example: [4, 5, 6] problemEpisodeSelections: type: array nullable: true items: $ref: '#/components/schemas/SeasonEpisodeSelection' is4k: type: boolean example: false media: $ref: '#/components/schemas/MediaInfo' createdBy: $ref: '#/components/schemas/User' modifiedBy: $ref: '#/components/schemas/User' comments: type: array items: $ref: '#/components/schemas/IssueComment' IssueComment: type: object properties: id: type: number example: 1 user: $ref: '#/components/schemas/User' message: type: string example: A comment DiscoverSlider: type: object properties: id: type: number example: 1 type: type: number example: 1 title: type: string nullable: true isBuiltIn: type: boolean enabled: type: boolean data: type: string example: '1234' nullable: true required: - type - enabled - title - data DiscoverHomeManifest: type: object required: - version - layoutRevision - userStateRevision - generatedAt - freshness - rows properties: version: type: integer enum: [1] layoutRevision: type: string userStateRevision: type: string generatedAt: type: string format: date-time freshness: type: object required: - manifestMaxAgeSeconds - rowMaxAgeSeconds - stateMaxAgeSeconds properties: manifestMaxAgeSeconds: type: integer rowMaxAgeSeconds: type: integer stateMaxAgeSeconds: type: integer rows: type: array items: type: object required: - key - sliderId - type - descriptorRevision properties: key: type: string sliderId: type: integer type: type: integer title: type: string data: type: string endpoint: type: string descriptorRevision: type: string description: Tracks row configuration only; use the row response ETag and freshness policy for catalog content. DiscoverHomeState: type: object required: - revision - generatedAt - items properties: revision: type: string generatedAt: type: string format: date-time items: type: array items: type: object required: - key - mediaType - id - media - request - watchlisted properties: key: type: string mediaType: type: string enum: [movie, tv, music, book] id: oneOf: - type: integer - type: string media: type: object nullable: true additionalProperties: true request: type: object nullable: true additionalProperties: true watchlisted: type: boolean WatchProviderRegion: type: object properties: iso_3166_1: type: string english_name: type: string native_name: type: string OverrideRule: type: object additionalProperties: false required: - id - createdAt - updatedAt properties: id: type: integer minimum: 1 maximum: 1000000000 radarrServiceId: type: integer minimum: 0 maximum: 1000000000 nullable: true sonarrServiceId: type: integer minimum: 0 maximum: 1000000000 nullable: true lidarrServiceId: type: integer minimum: 0 maximum: 1000000000 nullable: true users: type: string maxLength: 500 pattern: '^\d+(,\d+)*$' nullable: true genre: type: string maxLength: 500 pattern: '^\d+(,\d+)*$' nullable: true language: type: string maxLength: 500 pattern: '^[a-z]{2}(\|[a-z]{2})*$' nullable: true keywords: type: string maxLength: 500 pattern: '^\d+(,\d+)*$' nullable: true profileId: type: integer minimum: 0 maximum: 1000000000 nullable: true rootFolder: type: string maxLength: 500 nullable: true tags: type: string maxLength: 500 pattern: '^\d+(,\d+)*$' nullable: true createdAt: type: string format: date-time updatedAt: type: string format: date-time OverrideRuleWrite: type: object additionalProperties: false description: Exactly one service, at least one condition, and at least one setting must be configured. Lidarr rules support only the users condition. properties: radarrServiceId: type: integer minimum: 0 maximum: 1000000000 nullable: true sonarrServiceId: type: integer minimum: 0 maximum: 1000000000 nullable: true lidarrServiceId: type: integer minimum: 0 maximum: 1000000000 nullable: true users: type: string maxLength: 500 pattern: '^\d+(,\d+)*$' nullable: true genre: type: string maxLength: 500 pattern: '^\d+(,\d+)*$' nullable: true language: type: string maxLength: 500 pattern: '^[a-z]{2}(\|[a-z]{2})*$' nullable: true keywords: type: string maxLength: 500 pattern: '^\d+(,\d+)*$' nullable: true profileId: type: integer minimum: 0 maximum: 1000000000 nullable: true rootFolder: type: string maxLength: 500 nullable: true tags: type: string maxLength: 500 pattern: '^\d+(,\d+)*$' nullable: true Certification: type: object properties: certification: type: string example: 'PG-13' meaning: type: string example: 'Some material may be inappropriate for children under 13.' nullable: true order: type: number example: 3 nullable: true required: - certification CertificationResponse: type: object properties: certifications: type: object additionalProperties: type: array items: $ref: '#/components/schemas/Certification' example: certifications: US: - certification: 'G' meaning: 'All ages admitted' order: 1 - certification: 'PG' meaning: 'Some material may not be suitable for children under 10.' order: 2 PlaylistResolutionItem: type: object properties: id: type: string description: MusicBrainz release-group ID for a matched item, or a synthetic placeholder ID for an unmatched item. example: 'f5093c06-23e3-404f-aeaa-40f72885ee3a' title: type: string artist: type: string year: type: string image: type: string nullable: true releaseType: type: string sourceTitle: type: string description: The track/video title as read from the source playlist. sourceArtist: type: string sourceUrl: type: string matchStatus: type: string enum: - matched - unmatched - ambiguous matchReason: type: string required: - id - title - sourceTitle - matchStatus PlaylistResolutionResponse: type: object properties: provider: type: string enum: - spotify - youtube name: type: string url: type: string totalItems: type: number matchedItems: type: number items: type: array items: $ref: '#/components/schemas/PlaylistResolutionItem' required: - provider - name - url - totalItems - matchedItems - items PlaybackDevice: type: object properties: id: type: string name: type: string client: type: string platform: type: string serverType: type: integer required: - id - name - client - serverType DesktopAuthTicketIssueRequest: type: object properties: challenge: type: string pattern: '^[a-f0-9]{64}$' description: SHA-256 challenge generated by the native client. protocolVersion: type: integer enum: [1] required: - challenge - protocolVersion DesktopAuthTicketIssueResponse: type: object properties: ticket: type: string pattern: '^[A-Za-z0-9_-]{43}$' description: Short-lived opaque ticket for the native client. expiresIn: type: integer description: Ticket lifetime in milliseconds. required: - ticket - expiresIn DesktopAuthTicketRedeemRequest: type: object properties: ticket: type: string pattern: '^[A-Za-z0-9_-]{43}$' verifier: type: string pattern: '^[A-Za-z0-9_-]{43}$' description: Native-only PKCE verifier matching the challenge. protocolVersion: type: integer enum: [1] required: - ticket - verifier - protocolVersion DesktopAuthBootstrapResponse: type: object description: Sensitive bootstrap payload returned only to the native HTTP client. properties: serverUrl: type: string format: uri fallbackServerUrl: type: string format: uri serverId: type: string userId: type: string deviceId: type: string description: Native-only Jellyfin device identifier. accessToken: type: string description: Native-only Jellyfin access token; never return this to browser JavaScript. bootstrapGeneration: type: string required: - serverUrl - serverId - userId - deviceId - accessToken - bootstrapGeneration PlaybackCatalogItem: type: object properties: id: type: string title: type: string index: type: integer parentIndex: type: integer kind: type: string enum: - movie - episode - track available: type: boolean enum: - true required: - id - title - index - kind - available PlaybackCatalogGroup: type: object properties: id: type: string title: type: string index: type: integer available: type: boolean items: type: array items: $ref: '#/components/schemas/PlaybackCatalogItem' required: - id - title - index - available - items PlaybackCatalogResponse: type: object properties: mediaId: type: integer serverType: type: integer is4k: type: boolean rootItem: $ref: '#/components/schemas/PlaybackCatalogItem' groups: type: array items: $ref: '#/components/schemas/PlaybackCatalogGroup' required: - mediaId - serverType - is4k - groups WatchEpisodeStatus: type: object properties: seasonNumber: type: integer minimum: 0 episodeNumber: type: integer minimum: 0 watched: type: boolean required: - seasonNumber - episodeNumber - watched WatchSeasonStatus: type: object properties: seasonNumber: type: integer minimum: 0 availableCount: type: integer minimum: 0 watchedCount: type: integer minimum: 0 episodes: type: array items: $ref: '#/components/schemas/WatchEpisodeStatus' required: - seasonNumber - availableCount - watchedCount - episodes WatchStatusResponse: type: object properties: serverType: type: integer availableCount: type: integer minimum: 0 watchedCount: type: integer minimum: 0 unwatchedCount: type: integer minimum: 0 seasons: type: array items: $ref: '#/components/schemas/WatchSeasonStatus' required: - serverType - availableCount - watchedCount - unwatchedCount PlaybackCommand: type: object properties: deviceId: type: string maxLength: 512 itemIds: type: array minItems: 0 items: type: string is4k: type: boolean required: - deviceId - itemIds PlaybackPlaylistCommand: type: object properties: itemIds: type: array minItems: 0 maxItems: 1000 items: type: string maxLength: 128 is4k: type: boolean required: - itemIds PlaybackPlaylistResponse: type: object properties: url: type: string format: uri required: - url CollectionPlaybackCommand: type: object properties: is4k: type: boolean default: false description: Use only the selected quality (false for HD, true for 4K). Unavailable titles are skipped, never substituted with another quality. deviceId: type: string maxLength: 512 mediaIds: type: array minItems: 1 items: type: integer required: - deviceId - mediaIds CollectionPlaylistCommand: type: object properties: is4k: type: boolean default: false description: Use only the selected quality (false for HD, true for 4K). Unavailable titles are skipped, never substituted with another quality. mediaIds: type: array minItems: 1 maxItems: 1000 items: type: integer minimum: 1 required: - mediaIds securitySchemes: cookieAuth: type: apiKey name: connect.sid in: cookie apiKey: type: apiKey in: header name: X-Api-Key paths: /desktop/auth-tickets: post: summary: Issue a one-time native desktop authentication ticket description: Creates a 60-second, single-use ticket bound to the signed-in session and linked Jellyfin identity. This operation requires a browser session cookie; API keys are not accepted. tags: - native desktop security: - cookieAuth: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/DesktopAuthTicketIssueRequest' responses: '201': description: Native ticket issued. content: application/json: schema: $ref: '#/components/schemas/DesktopAuthTicketIssueResponse' '400': description: Invalid protocol challenge. '403': description: A current browser session and HTTPS transport are required. '409': description: A linked Jellyfin account or protocol-compatible credentials are required. '429': description: Ticket issue rate limit reached. /desktop/auth-tickets/redeem: post: summary: Redeem a native desktop ticket for a Jellyfin session description: Redeems the single-use ticket and PKCE verifier from a native HTTP client. Browser-origin requests are rejected. The response contains sensitive Jellyfin credentials and must never be exposed to browser JavaScript. tags: - native desktop security: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/DesktopAuthTicketRedeemRequest' responses: '200': description: Native-only Jellyfin playback bootstrap. content: application/json: schema: $ref: '#/components/schemas/DesktopAuthBootstrapResponse' '400': description: Invalid ticket redemption request. '401': description: Ticket, verifier, session, or Jellyfin identity is invalid or expired. '403': description: HTTPS is required and browser-origin redemption is not allowed. '409': description: Ticket has already been consumed or the configured media server is unsupported. '429': description: Ticket redemption rate limit reached. '503': description: Jellyfin could not be reached to validate the linked account. /association/{mediaType}/{id}: get: summary: Get cross-medium associations description: Returns a ranked graph of similar, recommended, and shared-person associations for movies, series, albums, artists, and books. tags: - association parameters: - in: path name: mediaType required: true schema: type: string enum: [movie, tv, album, artist, book] - in: path name: id required: true schema: type: string description: TMDB ID for movie/TV, MusicBrainz release group ID for album, MusicBrainz artist ID for artist, or Open Library work ID for book. - in: query name: includeWeak schema: type: boolean default: false description: Include lower-confidence shared-genre associations. - in: query name: limit schema: type: integer minimum: 1 maximum: 60 description: Maximum number of association edges to return. responses: '200': description: Ranked association graph content: application/json: schema: $ref: '#/components/schemas/AssociationGraph' '400': description: Invalid association media type. /imageproxy/warm: post: summary: Warm the image cache for visible media description: Queues a bounded set of image URLs for authenticated, background cache warming. The response confirms the URLs were accepted, not that upstream downloads have completed. tags: - other requestBody: required: true content: application/json: schema: type: object required: - urls properties: urls: type: array maxItems: 100 items: type: string maxLength: 2048 responses: '202': description: Image URLs were accepted for background cache warming. content: application/json: schema: type: object required: - accepted properties: accepted: type: boolean enum: [true] '400': description: The image URL list is invalid or exceeds the request limits. '403': description: Authentication is required. '429': description: The cache warming request rate limit was exceeded. /status: get: summary: Get Seerr status description: Returns the current Seerr status in a JSON object. updateAvailable and commitsBehind are omitted when checkUpdateAvailable is false. security: [] tags: - public parameters: - in: query name: checkUpdateAvailable description: If false, updateAvailable and commitsBehind will be omitted from the response. Defaults to the versionCheck setting. required: false example: false schema: type: boolean 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/ready: get: summary: Check Seerr readiness description: Returns success only when the application database is reachable. security: [] tags: - public responses: '204': description: Application is ready to receive traffic '503': description: Application database is unavailable /status/tls: get: summary: Get active browser transport configuration description: Returns the configured HTTP/TLS mode, listener ports, allowed TLS hosts, and certificate fingerprint. This endpoint is public so the first-run UI can explain how browser authentication must be performed. security: [] tags: - public responses: '200': description: Active transport configuration content: application/json: schema: type: object required: - mode - httpPort - httpsPort - httpAuthAllowed - redirectsHttpToHttps - hosts - caDownloadAvailable - configuredMode - configuredHttpsPort - configuredHttpAuthAllowed - configuredRedirectsHttpToHttps - environmentOverrides - pendingRestart - setupRequired properties: mode: type: string enum: [disabled, self-signed, provided] httpPort: type: integer httpsPort: type: integer nullable: true httpAuthAllowed: type: boolean redirectsHttpToHttps: type: boolean hosts: type: array items: type: string fingerprint: type: string caDownloadAvailable: type: boolean configuredMode: type: string enum: [disabled, self-signed, provided] configuredHttpsPort: type: integer nullable: true configuredHttpAuthAllowed: type: boolean configuredRedirectsHttpToHttps: type: boolean environmentOverrides: type: array items: type: string pendingRestart: type: boolean setupRequired: type: boolean /status/tls/bootstrap: post: summary: Configure transport security before first-user setup description: Saves the initial TLS or explicit HTTP-auth choice. This endpoint is available during incomplete first-run setup, or to an authenticated administrator before setup is finalized, and always requires a server restart before the selected listener configuration becomes active. security: [] tags: - public requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/TlsSettings' responses: '200': description: Transport configuration saved; restart is required content: application/json: schema: type: object required: - mode - pendingRestart properties: mode: type: string enum: [disabled, self-signed, provided] pendingRestart: type: boolean '400': description: Invalid transport configuration '403': description: Bootstrap configuration is no longer available to this caller /status/tls/ca: get: summary: Download the generated local CA certificate description: Returns the public CA certificate for self-signed built-in TLS. The private CA and server keys are never exposed. security: [] tags: - public responses: '200': description: PEM-encoded local CA certificate content: application/x-pem-file: schema: type: string '404': description: Built-in self-signed TLS is not active /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. tags: - settings 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 appDataPermissions: type: boolean example: true /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/network: get: summary: Get network settings description: Retrieves all network settings in a JSON object. tags: - settings responses: '200': description: OK content: application/json: schema: $ref: '#/components/schemas/NetworkSettings' post: summary: Update network settings description: Updates network settings with the provided values. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/NetworkSettings' responses: '200': description: 'Values were sucessfully updated' content: application/json: schema: $ref: '#/components/schemas/NetworkSettings' /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/jellyfin: get: summary: Get Jellyfin settings description: Retrieves current Jellyfin settings. tags: - settings responses: '200': description: OK content: application/json: schema: $ref: '#/components/schemas/JellyfinSettings' post: summary: Update Jellyfin settings description: Updates Jellyfin settings with the provided values. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/JellyfinSettings' responses: '200': description: 'Values were successfully updated' content: application/json: schema: $ref: '#/components/schemas/JellyfinSettings' /settings/jellyfin/bridge-login: post: summary: Enable or disable Jellyfin bridge sign-in description: Changes the optional SeerrNG Jellyfin plugin sign-in setting without contacting Jellyfin, so administrators can revoke bridge sessions during a server outage. tags: - settings requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: [enabled] properties: enabled: type: boolean responses: '200': description: Bridge login setting updated. content: application/json: schema: type: object required: [bridgeLoginEnabled] properties: bridgeLoginEnabled: type: boolean '400': description: Invalid setting value, or Jellyfin is not connected and active with media-server sign-in enabled. '403': description: An administrator account is required. /settings/jellyfin/library: get: summary: Get Jellyfin libraries description: Returns a list of Jellyfin libraries in a JSON array. tags: - settings responses: '200': description: 'Jellyfin libraries returned' content: application/json: schema: type: array items: $ref: '#/components/schemas/JellyfinLibrary' post: summary: Update Jellyfin libraries description: Optionally synchronizes libraries and updates which libraries are enabled. tags: - settings requestBody: required: true content: application/json: schema: type: object properties: sync: type: boolean enable: type: string description: Comma-separated library IDs. Omitted or empty disables all libraries. responses: '200': description: 'Jellyfin libraries updated' content: application/json: schema: type: array items: $ref: '#/components/schemas/JellyfinLibrary' /settings/jellyfin/users: get: summary: Get Jellyfin Users description: Returns a list of Jellyfin Users in a JSON array. tags: - settings - users responses: '200': description: Jellyfin users returned content: application/json: schema: type: array items: type: object properties: username: type: string id: type: string thumb: type: string email: type: string /settings/jellyfin/sync: get: summary: Get status of full Jellyfin library sync description: Returns sync progress in a JSON array. tags: - settings responses: '200': description: Status of Jellyfin sync 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/JellyfinLibrary' libraries: type: array items: $ref: '#/components/schemas/JellyfinLibrary' post: summary: Start full Jellyfin library sync description: Runs a full Jellyfin library sync 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 Jellyfin sync 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/JellyfinLibrary' libraries: type: array items: $ref: '#/components/schemas/JellyfinLibrary' /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/library: get: summary: Get Plex libraries description: Returns a list of Plex libraries in a JSON array. tags: - settings responses: '200': description: 'Plex libraries returned' content: application/json: schema: type: array items: $ref: '#/components/schemas/PlexLibrary' post: summary: Update Plex libraries description: Optionally synchronizes libraries and updates which libraries are enabled. tags: - settings requestBody: required: true content: application/json: schema: type: object properties: sync: type: boolean enable: type: string description: Comma-separated library IDs. Omitted or empty disables all libraries. responses: '200': description: 'Plex libraries updated' content: application/json: schema: type: array items: $ref: '#/components/schemas/PlexLibrary' /settings/plex/library/{libraryId}/type: put: summary: Reclassify a Plex artist library description: Changes a Plex artist library between Music and Audiobooks. tags: - settings parameters: - name: libraryId in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object required: - type properties: type: type: string enum: - music - book responses: '200': description: 'Plex libraries returned after reclassification' 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/metadatas: get: summary: Get Metadata settings description: Retrieves current Metadata settings. tags: - settings responses: '200': description: OK content: application/json: schema: $ref: '#/components/schemas/MetadataSettings' put: summary: Update Metadata settings description: Updates Metadata settings with the provided values. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/MetadataSettings' responses: '200': description: 'Values were successfully updated' content: application/json: schema: $ref: '#/components/schemas/MetadataSettings' /settings/metadatas/test: post: summary: Test Provider configuration description: Tests if the TVDB configuration is valid. Returns a list of available languages on success. tags: - settings requestBody: required: true content: application/json: schema: type: object properties: tmdb: type: boolean example: true tvdb: type: boolean example: true responses: '200': description: Succesfully connected to TVDB content: application/json: schema: type: object properties: message: type: string example: 'Successfully connected to TVDB' /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/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: $ref: '#/components/schemas/ServarrConnectionSettings' 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/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: $ref: '#/components/schemas/ServarrConnectionSettings' 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/sportarr: get: summary: Get Sportarr settings description: Returns configured Sportarr services with API keys redacted. tags: - settings responses: '200': description: Sportarr settings returned content: application/json: schema: type: array items: $ref: '#/components/schemas/SportarrSettings' post: summary: Add a Sportarr service description: Adds a Sportarr connection and selected quality profile. Requires administrator permission. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/SportarrSettings' responses: '201': description: Sportarr service added content: application/json: schema: $ref: '#/components/schemas/SportarrSettings' '400': description: Invalid Sportarr settings '403': description: Administrator permission required '409': description: Maximum configured Sportarr services reached /settings/sportarr/test: post: summary: Test a Sportarr connection description: Validates the native Sportarr API key and returns quality profiles. Requires administrator permission. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ServarrConnectionSettings' responses: '200': description: Sportarr connection verified content: application/json: schema: type: object required: [profiles] properties: profiles: type: array items: $ref: '#/components/schemas/ServiceProfile' urlBase: type: string nullable: true '400': description: Invalid connection settings '403': description: Administrator permission required '422': description: The connection is not a Sportarr server '502': description: Sportarr connection failed /settings/sportarr/{id}: put: summary: Update Sportarr settings description: Updates a configured Sportarr service. Requires administrator permission. tags: - settings parameters: - in: path name: id required: true schema: type: integer minimum: 0 maximum: 1000000 requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/SportarrSettings' responses: '200': description: Sportarr settings updated content: application/json: schema: $ref: '#/components/schemas/SportarrSettings' '400': description: Invalid Sportarr settings '403': description: Administrator permission required '404': description: Sportarr service not found delete: summary: Remove Sportarr settings description: Removes a configured Sportarr service when no saved requests depend on it. Requires administrator permission. tags: - settings parameters: - in: path name: id required: true schema: type: integer minimum: 0 maximum: 1000000 responses: '200': description: Sportarr settings removed content: application/json: schema: $ref: '#/components/schemas/SportarrSettings' '403': description: Administrator permission required '404': description: Sportarr service not found '409': description: Existing request data depends on this service /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/software-acquisition: get: summary: Get software acquisition provider settings description: Returns ROMarrNG, QuestarrNG, and Steam connection state with API keys redacted, the selected QuestarrNG, ROMarrNG IGDB, or ROMarrNG DAT emulation catalog, administrator-assigned Retro and Modern system groups, and per-system IGDB platform overrides. tags: - settings responses: '200': description: Software acquisition settings returned content: application/json: schema: type: object properties: romarr: $ref: '#/components/schemas/SoftwareProviderSettingsView' questarr: $ref: '#/components/schemas/SoftwareProviderSettingsView' emulationCatalogProvider: type: string enum: [questarr, romarr, romarr-dat] emulationSystemGroups: type: object additionalProperties: type: string enum: [retro, modern] emulationPlatformMappings: type: object additionalProperties: type: integer minimum: 1 steamApiKey: type: string description: Always empty or redacted; never returns the configured secret. steamApiKeyConfigured: type: boolean put: summary: Update software acquisition settings description: Updates provider connections, the selected emulation catalog, per-system emulation groups and IGDB platform overrides, and the Steam Web API key. API keys stay server-side and are redacted in responses; omit an unchanged secret to keep it. tags: - settings requestBody: required: true content: application/json: schema: type: object properties: romarr: $ref: '#/components/schemas/SoftwareProviderSettingsInput' questarr: $ref: '#/components/schemas/SoftwareProviderSettingsInput' emulationCatalogProvider: type: string enum: [questarr, romarr, romarr-dat] emulationSystemGroups: type: object additionalProperties: type: string enum: [retro, modern] emulationPlatformMappings: type: object additionalProperties: type: integer minimum: 1 steamApiKey: type: string maxLength: 2048 responses: '200': description: Software acquisition settings updated content: application/json: schema: type: object properties: romarr: $ref: '#/components/schemas/SoftwareProviderSettingsView' questarr: $ref: '#/components/schemas/SoftwareProviderSettingsView' emulationCatalogProvider: type: string enum: [questarr, romarr, romarr-dat] emulationSystemGroups: type: object additionalProperties: type: string enum: [retro, modern] emulationPlatformMappings: type: object additionalProperties: type: integer minimum: 1 steamApiKey: type: string steamApiKeyConfigured: type: boolean '400': description: Invalid provider or system-group settings /settings/software-acquisition/platform-mapping/preview: get: summary: Preview ROMarrNG system to IGDB platform matches description: Returns ROMarrNG systems, automatic matches, saved overrides, and unmatched IGDB platforms without changing settings. tags: - settings responses: '200': description: Platform mapping preview returned content: application/json: schema: type: object required: [ systems, catalogPlatforms, unmatchedSystems, unmatchedCatalogPlatforms, ] properties: systems: type: array items: type: object required: [ slug, name, aliases, automaticMatch, selectedMatch, status, ] properties: slug: type: string name: type: string aliases: type: array items: type: string automaticMatch: type: object nullable: true properties: id: type: integer name: type: string selectedMatch: type: object nullable: true properties: id: type: integer name: type: string status: type: string enum: [automatic, manual, unmatched] catalogPlatforms: type: array items: type: object required: [id, name] properties: id: type: integer name: type: string unmatchedSystems: type: array items: type: object required: [slug, name] properties: slug: type: string name: type: string unmatchedCatalogPlatforms: type: array items: type: object required: [id, name] properties: id: type: integer name: type: string '502': description: ROMarrNG platform data could not be retrieved '503': description: ROMarrNG is not connected /settings/software-acquisition/test/{provider}: post: summary: Test a software acquisition provider connection description: Checks the selected NG provider's authenticated integration contract without saving the submitted settings. tags: - settings parameters: - in: path name: provider required: true schema: type: string enum: [romarr, questarr] requestBody: required: true content: application/json: schema: type: object required: [hostname, port, useSsl] properties: hostname: type: string port: type: integer useSsl: type: boolean baseUrl: type: string apiKey: type: string responses: '200': description: Provider connection and integration contract verified '400': description: Invalid provider settings '502': description: Provider did not return a supported integration contract /settings/reader-delivery: get: summary: Get reader app connection and shelf-management settings description: Returns administrator-configured service addresses and usernames. Passwords are redacted and can be preserved by sending the redacted marker back unchanged. tags: - settings responses: '200': description: Reader app settings returned content: application/json: schema: $ref: '#/components/schemas/ReaderDeliverySettings' put: summary: Update reader app connection and shelf-management settings description: Stores administrator credentials in protected application settings for live shelf management. OPDS reader credentials remain configured in the reader service. Passwords are redacted on reads; clear flags remove the saved account credentials. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ReaderDeliverySettings' responses: '200': description: Reader app settings updated with secrets redacted content: application/json: schema: $ref: '#/components/schemas/ReaderDeliverySettings' '400': description: Invalid service URL, provider, or credentials '403': description: Administrator permission required /settings/reader-delivery/connection-test: post: summary: Test reader service account access description: Logs in with saved administrator credentials and verifies that SeerrNG can list the service's existing managed grouping collection. tags: - settings requestBody: required: true content: application/json: schema: type: object required: [provider] properties: provider: type: string enum: [grimmory, bookorbit] responses: '200': description: Reader service login and grouping access verified content: application/json: schema: $ref: '#/components/schemas/ReaderGroupingConnectionTest' '400': description: Provider is invalid or required account settings are missing '403': description: Administrator permission required '502': description: Reader service could not be reached or rejected the account /settings/reader-delivery/groupings: get: summary: List SeerrNG-managed reader shelves description: Returns only the reader grouping mappings created and managed by SeerrNG. It does not import unmanaged service groupings. tags: - settings responses: '200': description: Managed reader shelves returned content: application/json: schema: type: array items: $ref: '#/components/schemas/ReaderDeliveryGrouping' post: summary: Create or update a rule-based reader shelf description: Previews the rule, requires explicit allowEmpty consent for zero current matches, and then creates or updates the SeerrNG-managed shelf in the selected reader service. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ReaderGroupingSaveRequest' responses: '200': description: Reader shelf saved; countVerified indicates whether the provider confirmed its final item count content: application/json: schema: $ref: '#/components/schemas/ReaderGroupingSaveResponse' '400': description: Invalid provider, target, or option '403': description: Administrator permission required '409': description: Empty match requires opt-in, a concurrent update is in progress, or provider visibility is immutable '502': description: Reader service could not complete the grouping operation /settings/reader-delivery/groupings/preview: post: summary: Preview a reader shelf rule description: Checks current matches and returns a provider-specific live grouping filter with a bounded title sample. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ReaderGroupingPreviewRequest' responses: '200': description: Rule preview returned content: application/json: schema: $ref: '#/components/schemas/ReaderGroupingPreview' '400': description: Invalid provider, target, or missing service credentials '403': description: Administrator permission required '502': description: Reader service could not return a rule preview /settings/reader-delivery/groupings/{id}: delete: summary: Remove a SeerrNG-managed reader shelf description: Deletes the mapped shelf in the reader service and removes its SeerrNG mapping. It does not delete library books or files. tags: - settings parameters: - in: path name: id required: true schema: type: integer minimum: 1 responses: '200': description: Managed shelf and mapping removed content: application/json: schema: $ref: '#/components/schemas/ReaderGroupingDeleteResponse' '400': description: Invalid grouping ID or missing service credentials '403': description: Administrator permission required '404': description: Managed shelf not found '502': description: Reader service could not delete the managed shelf /live/downloads: get: summary: Stream live torrent download progress description: >- Server-sent events (`event: downloads`) with live progress for the authorized torrents, read from the configured download clients. Pass the opaque `liveDownloadToken` values returned with visible media download items. Administrators may pass raw torrent info hashes. Non-torrent or unauthorized IDs are ignored. Events identify the item with the submitted ID and never return the raw hash. When a client stops reporting a previously visible torrent, an `unavailable` event clears the browser's stale progress. Returns 204 when no download client is configured. tags: - request parameters: - in: query name: ids required: true description: Comma-separated opaque liveDownloadToken values for this user; administrators may use 40- or 64-character hexadecimal info hashes. At most 100 IDs are used. schema: type: string maxLength: 16384 responses: '200': description: Event stream content: text/event-stream: schema: type: string '204': description: No download client is configured '400': description: No valid authorized live download IDs were given '429': description: Too many concurrent streams /settings/download-clients: get: summary: Get live download progress settings description: Returns the torrent clients SeerrNG reads for live download progress. Passwords and tokens are always redacted. tags: - settings responses: '200': description: Live download settings content: application/json: schema: $ref: '#/components/schemas/LiveDownloadSettings' put: summary: Update live download progress settings description: Replaces the list of torrent clients and the refresh interval. SeerrNG only reads these clients; it never adds, changes, or removes torrents. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/LiveDownloadSettings' responses: '200': description: Settings saved content: application/json: schema: $ref: '#/components/schemas/LiveDownloadSettings' '400': description: Invalid settings /settings/download-clients/test: post: summary: Test a download client connection description: Signs in to the client and reads its version. The submitted settings are not saved. Omit the password to use the saved one for the same client ID. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/DownloadClientSettings' responses: '200': description: Connected content: application/json: schema: type: object properties: success: type: boolean version: type: string '400': description: Invalid settings '502': description: The client could not be reached or rejected the credentials /settings/download-clients/status: get: summary: Get live download client health description: Reports the result of the most recent poll of each enabled client. Clients are polled only while a browser is viewing a download. tags: - settings responses: '200': description: Client health content: application/json: schema: type: object properties: subscribers: type: integer clients: type: array items: type: object properties: clientId: type: integer ok: type: boolean checkedAt: type: string error: type: string /live-tv/status: get: summary: Get Live TV availability description: Reports whether IPTV Tunerr is configured and its guide is loaded. Administrators also receive guide statistics. tags: - live-tv responses: '200': description: Live TV status content: application/json: schema: type: object properties: configured: type: boolean guideReady: type: boolean canRequest: type: boolean /live-tv/airings: get: summary: Find upcoming Live TV airings of a title description: Searches the indexed Tunerr guide for upcoming programmes whose title matches one of the given titles. Matching ignores case, accents, punctuation, a leading "The", and a trailing year. tags: - live-tv parameters: - in: query name: title required: true description: Title to match. Repeat for alternate titles (up to 4 are used). style: form explode: true schema: type: array maxItems: 8 items: type: string maxLength: 300 - in: query name: limit schema: type: integer minimum: 1 maximum: 50 responses: '200': description: Upcoming airings content: application/json: schema: type: object properties: configured: type: boolean guideReady: type: boolean airings: type: array items: $ref: '#/components/schemas/LiveTvAiring' '400': description: No title given /live-tv/recordings: get: summary: List Live TV recording requests description: Returns the caller's recording requests. Users who can manage or view all requests may pass `scope=all`. tags: - live-tv parameters: - in: query name: scope schema: type: string enum: [mine, all] - in: query name: filter schema: type: string enum: [all, active] - in: query name: take schema: type: integer minimum: 1 maximum: 100 - in: query name: skip schema: type: integer minimum: 0 responses: '200': description: Recording requests content: application/json: schema: type: object properties: pageInfo: type: object properties: total: type: integer take: type: integer skip: type: integer results: type: array items: $ref: '#/components/schemas/RecordingRequest' post: summary: Request a Live TV recording description: >- Requests one airing (`kind: airing`, with the airing's `channel` and `start` from `/live-tv/airings`) or every airing of a title (`kind: series`, optionally limited to one `channel`). Requests by users who can manage or auto-approve requests are scheduled in Tunerr immediately; others wait for approval. tags: - live-tv requestBody: required: true content: application/json: schema: type: object required: [kind, title] properties: kind: type: string enum: [airing, series] title: type: string maxLength: 300 channel: type: string maxLength: 255 start: type: string format: date-time mediaType: type: string enum: [movie, tv] tmdbId: type: integer responses: '201': description: Recording requested content: application/json: schema: $ref: '#/components/schemas/RecordingRequest' '400': description: Invalid request '403': description: The user cannot request recordings '404': description: Live TV is not set up, or the airing or title is not in the guide '409': description: Duplicate request or too many active recordings '502': description: Tunerr could not be reached '503': description: The guide is not loaded, or Tunerr does not support rule-based recording /live-tv/recordings/{id}/approve: post: summary: Approve a recording request description: Creates the Tunerr recording rule for a pending request. Requires the Manage Requests permission. tags: - live-tv parameters: - in: path name: id required: true schema: type: integer responses: '200': description: Recording scheduled content: application/json: schema: $ref: '#/components/schemas/RecordingRequest' '403': description: Access denied '404': description: Recording not found '409': description: Not pending, or the airing already ended '502': description: Tunerr could not be reached '503': description: Tunerr does not support rule-based recording /live-tv/recordings/{id}/decline: post: summary: Decline a recording request tags: - live-tv parameters: - in: path name: id required: true schema: type: integer responses: '200': description: Recording declined content: application/json: schema: $ref: '#/components/schemas/RecordingRequest' '403': description: Access denied '404': description: Recording not found '409': description: Not pending /live-tv/recordings/{id}: delete: summary: Cancel a recording request description: Cancels an active recording request and removes its Tunerr rule. The requester or a user with Manage Requests can cancel. tags: - live-tv parameters: - in: path name: id required: true schema: type: integer responses: '200': description: Recording cancelled content: application/json: schema: $ref: '#/components/schemas/RecordingRequest' '403': description: Access denied '404': description: Recording not found '409': description: The recording is no longer active '502': description: Tunerr could not be reached /settings/tunerr: get: summary: Get IPTV Tunerr settings description: The deck password is always redacted. tags: - settings responses: '200': description: Tunerr settings content: application/json: schema: $ref: '#/components/schemas/TunerrSettings' put: summary: Update IPTV Tunerr settings tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/TunerrSettings' responses: '200': description: Settings saved content: application/json: schema: $ref: '#/components/schemas/TunerrSettings' '400': description: Invalid settings /settings/tunerr/test: post: summary: Test the IPTV Tunerr connection description: Reads recording rules through the deck and opens the guide. Reports Tunerr recording features SeerrNG needs that are missing. Settings are not saved. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/TunerrSettings' responses: '200': description: Deck and guide reachable '400': description: Invalid settings '502': description: The deck or guide could not be reached /settings/tunerr/sportarr: get: summary: Get the optional Tunerr-to-Sportarr sports DVR link status description: Returns sanitized service and feed status without API credentials or feed URLs. tags: - settings responses: '200': description: Optional integration status content: application/json: schema: $ref: '#/components/schemas/TunerrSportarrIntegrationStatus' '403': description: Admin access required /settings/tunerr/sportarr/connect: post: summary: Connect Tunerr sports feeds to Sportarr description: Tests the generated M3U from Sportarr, adds or reuses the playlist and linked XMLTV source, then syncs the guide. This operation is idempotent and does not delete existing feeds. tags: - settings responses: '200': description: Playlist and guide connected and synced content: application/json: schema: $ref: '#/components/schemas/TunerrSportarrIntegrationResult' '403': description: Admin access required '400': description: Invalid Tunerr URL reachable from Sportarr '409': description: A required service or feed setup is disabled or conflicts with an existing source '502': description: A feed could not be tested or synced; a partial setup may remain and can be retried '503': description: Tunerr sports automation could not be reached /soulseek/status: get: summary: Get Soulseek request availability tags: - soulseek responses: '200': description: Whether slskdN is configured and the user can request tracks content: application/json: schema: type: object properties: configured: type: boolean canRequest: type: boolean /soulseek/track-requests: get: summary: List Soulseek track requests description: Returns the caller's track requests. Users who can manage or view all requests may pass `scope=all`. tags: - soulseek parameters: - in: query name: scope schema: type: string enum: [mine, all] - in: query name: filter schema: type: string enum: [all, active] - in: query name: take schema: type: integer minimum: 1 maximum: 100 - in: query name: skip schema: type: integer minimum: 0 responses: '200': description: Track requests content: application/json: schema: type: object properties: pageInfo: type: object results: type: array items: $ref: '#/components/schemas/TrackRequest' post: summary: Request tracks from Soulseek description: >- Requests individual tracks through the slskdN wishlist, for example singles or playlist tracks without an album match. Requests by users who can manage requests or auto-approve music start searching immediately; others wait for approval. An identical active request is returned instead of a duplicate. tags: - soulseek requestBody: required: true content: application/json: schema: type: object required: [tracks] properties: tracks: type: array minItems: 1 maxItems: 50 items: type: object required: [artist, title] properties: artist: type: string maxLength: 255 title: type: string maxLength: 255 recordingMbid: type: string source: type: string enum: [manual, playlist, songid] responses: '201': description: Track requests created or reused content: application/json: schema: type: object properties: results: type: array items: $ref: '#/components/schemas/TrackRequest' '400': description: Invalid tracks '403': description: The user cannot request music '404': description: slskdN is not set up '409': description: Too many active track requests '502': description: slskdN could not be reached /soulseek/track-requests/{id}/approve: post: summary: Approve a track request tags: - soulseek parameters: - in: path name: id required: true schema: type: integer responses: '200': description: Search started content: application/json: schema: $ref: '#/components/schemas/TrackRequest' '403': description: Access denied '404': description: Request not found '409': description: Not pending '502': description: slskdN could not be reached /soulseek/track-requests/{id}/decline: post: summary: Decline a track request tags: - soulseek parameters: - in: path name: id required: true schema: type: integer responses: '200': description: Declined content: application/json: schema: $ref: '#/components/schemas/TrackRequest' '403': description: Access denied '404': description: Request not found '409': description: Not pending /soulseek/track-requests/{id}: delete: summary: Cancel a track request description: Removes the slskdN wishlist entry. The requester or a manager can cancel. tags: - soulseek parameters: - in: path name: id required: true schema: type: integer responses: '200': description: Cancelled content: application/json: schema: $ref: '#/components/schemas/TrackRequest' '403': description: Access denied '404': description: Request not found '409': description: No longer active '502': description: slskdN could not be reached /soulseek/albums/{releaseGroupId}/issues: get: summary: List slskdN library-health issues for an album description: Looks up open slskdN issues (transcodes, missing tracks, and similar) for each release of the MusicBrainz release group. Requires Manage Requests. tags: - soulseek parameters: - in: path name: releaseGroupId required: true schema: type: string pattern: '^[0-9a-fA-F-]{36}$' responses: '200': description: Album issues content: application/json: schema: type: object properties: configured: type: boolean issues: type: array items: type: object properties: issueId: type: string type: type: string severity: type: string status: type: string title: type: string reason: type: string canAutoFix: type: boolean remediationJobId: type: string '400': description: Invalid album ID '403': description: Access denied '502': description: slskdN could not be reached /soulseek/albums/{releaseGroupId}/remediate: post: summary: Fix album issues with slskdN description: Starts slskdN remediation for the given issues. Only issues that belong to this album and that slskdN can fix automatically are sent. Requires Manage Requests. tags: - soulseek parameters: - in: path name: releaseGroupId required: true schema: type: string pattern: '^[0-9a-fA-F-]{36}$' requestBody: required: true content: application/json: schema: type: object required: [issueIds] properties: issueIds: type: array minItems: 1 maxItems: 200 items: type: string maxLength: 128 responses: '202': description: Remediation started content: application/json: schema: type: object properties: jobId: type: string issueCount: type: integer '400': description: Invalid request '403': description: Access denied '409': description: None of the issues can be fixed automatically '502': description: slskdN could not be reached /soulseek/songid: post: summary: Identify a song with slskdN SongID description: Starts a SongID analysis of a link or text. Poll the result with GET `/soulseek/songid/{id}`; only the requester (or a manager) can read it. The slskdN API key needs the administrator role. tags: - soulseek requestBody: required: true content: application/json: schema: type: object required: [source] properties: source: type: string maxLength: 2048 responses: '202': description: Analysis started content: application/json: schema: $ref: '#/components/schemas/SongIdResult' '400': description: No source given '403': description: Access denied '404': description: slskdN is not set up '502': description: slskdN could not run SongID '503': description: This slskdN does not support SongID /soulseek/songid/{id}: get: summary: Get a SongID result tags: - soulseek parameters: - in: path name: id required: true schema: type: string maxLength: 64 responses: '200': description: SongID result content: application/json: schema: $ref: '#/components/schemas/SongIdResult' '404': description: Not found /settings/slskdn: get: summary: Get slskdN settings description: The API key is always redacted. tags: - settings responses: '200': description: slskdN settings content: application/json: schema: $ref: '#/components/schemas/SlskdnSettings' put: summary: Update slskdN settings tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/SlskdnSettings' responses: '200': description: Settings saved content: application/json: schema: $ref: '#/components/schemas/SlskdnSettings' '400': description: Invalid settings /settings/slskdn/test: post: summary: Test the slskdN connection description: Reads the slskdN version and reports which optional features (wishlist, library health, SongID) the API key can use. Settings are not saved. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/SlskdnSettings' responses: '200': description: Connected '400': description: Invalid settings '502': description: slskdN could not be reached /live-tv/sports/teams: get: summary: List teams in Tunerr's sports schedule description: Teams from IPTV Tunerr's API-Sports schedules, for following. Requires Tunerr sports automation. tags: - live-tv responses: '200': description: Teams content: application/json: schema: type: object properties: configured: type: boolean enabled: type: boolean teams: type: array items: type: object properties: dataset: type: string league: type: string team: type: string '502': description: Tunerr could not be reached /live-tv/sports/follows: get: summary: List the teams the user follows tags: - live-tv responses: '200': description: Followed teams post: summary: Follow a team description: Live TV Sync requests a recording of each upcoming game Tunerr matches to a guide airing, using the usual approval rules. Up to 20 teams per user. tags: - live-tv requestBody: required: true content: application/json: schema: type: object required: [dataset, team] properties: dataset: type: string maxLength: 32 team: type: string maxLength: 128 responses: '200': description: Already following '201': description: Following '400': description: Invalid team '403': description: The user cannot request recordings '409': description: Too many followed teams /live-tv/sports/follows/{id}: delete: summary: Stop following a team tags: - live-tv parameters: - in: path name: id required: true schema: type: integer responses: '204': description: Unfollowed '404': description: Not following /swipe/status: get: summary: Get swipe availability description: Requires the Request permission. Returns 404 when an administrator has turned swipe off. tags: - swipe responses: '200': description: Swipe is available content: application/json: schema: type: object properties: enabled: type: boolean aiRanking: type: boolean '403': description: The user cannot make requests '404': description: Swipe is turned off /swipe/deck: get: summary: Get the user's swipe deck description: >- Returns up to 20 recommendations from SeerrNG's catalogs (TMDB recommendations and trending titles, Open Library subjects and trending books). Titles the user owns, requested, or already swiped are left out. When an AI provider is configured it reorders the deck and adds a reason to each pick. tags: - swipe parameters: - in: query name: mediaType required: true schema: type: string enum: [movie, tv, book] - in: query name: refresh schema: type: string enum: ['true', 'false'] responses: '200': description: Deck content: application/json: schema: type: object properties: mediaType: type: string ranked: type: boolean remaining: type: integer cards: type: array items: $ref: '#/components/schemas/SwipeCard' '400': description: Invalid media type '502': description: The catalogs could not be reached /swipe/decisions: post: summary: Record a swipe description: >- `want` (swipe right) records interest; the client then submits the request through `POST /request`. `pass` hides the title for good. `seen` marks it as already watched or read and counts as a taste signal. tags: - swipe requestBody: required: true content: application/json: schema: type: object required: [mediaType, id, decision] properties: mediaType: type: string enum: [movie, tv, book] id: type: string maxLength: 64 decision: type: string enum: [want, pass, seen] responses: '200': description: Recorded '400': description: Invalid swipe '404': description: The card is not in the user's deck /swipe/undo: post: summary: Undo the last pass or seen swipe tags: - swipe requestBody: required: true content: application/json: schema: type: object required: [mediaType] properties: mediaType: type: string enum: [movie, tv, book] responses: '200': description: The restored card content: application/json: schema: type: object properties: card: $ref: '#/components/schemas/SwipeCard' '404': description: Nothing to undo '409': description: The last swipe was a request; cancel it from Requests instead /swipe/profile: get: summary: Get the user's swipe preferences tags: - swipe responses: '200': description: Preferences put: summary: Update the user's swipe preferences tags: - swipe requestBody: required: true content: application/json: schema: type: object properties: tasteNotes: type: string maxLength: 1000 seriesRequest: type: string enum: [first-season, all-seasons] bookFormat: type: string enum: [ebook, audiobook] seedScope: type: string enum: [full, rated, favorites] favoriteSeeds: type: array maxItems: 25 items: $ref: '#/components/schemas/SwipeFavoriteSeed' responses: '200': description: Saved '400': description: Invalid preferences /swipe/favorites: get: summary: List the user's favorite seed options description: Returns the user's prior likes, requests, and linked personal library items for the selected media type. tags: [swipe] parameters: - in: query name: mediaType required: true schema: type: string enum: [movie, tv, book] responses: '200': description: Favorite seeds content: application/json: schema: type: array items: $ref: '#/components/schemas/SwipeFavoriteSeed' '400': description: Invalid media type /settings/swipe: get: summary: Get swipe settings description: The AI API key is always redacted. tags: - settings responses: '200': description: Swipe settings content: application/json: schema: $ref: '#/components/schemas/SwipeSettings' put: summary: Update swipe settings tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/SwipeSettings' responses: '200': description: Saved '400': description: Invalid settings /settings/swipe/test: post: summary: Test the swipe AI provider description: Sends one small ranking request to the selected AI provider with the submitted or saved key and model. Settings are not saved. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/SwipeSettings' responses: '200': description: The provider answered '400': description: Invalid settings '502': description: The provider rejected or failed the request /settings/readmeabook: get: summary: Get ReadMeABook connection settings tags: [settings] responses: '200': description: Connection settings with the API token redacted content: application/json: schema: $ref: '#/components/schemas/ReadMeABookSettings' put: summary: Save ReadMeABook connection settings tags: [settings] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ReadMeABookSettings' responses: '200': description: Saved settings with the API token redacted '400': description: Invalid settings /settings/readmeabook/test: post: summary: Test ReadMeABook connection settings tags: [settings] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ReadMeABookSettings' responses: '200': description: ReadMeABook accepted the configured token '400': description: Invalid settings '502': description: ReadMeABook could not be reached /settings/login-links: get: summary: List sign-in link metadata for a user tags: [settings] parameters: - in: query name: userId required: true schema: type: integer minimum: 1 responses: '200': description: Sign-in link metadata; raw tokens are never returned post: summary: Create an expiring, single-use sign-in link tags: [settings] requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: [userId] properties: userId: type: integer minimum: 1 responses: '201': description: Created; the raw token is returned once '400': description: Invalid target user /settings/login-links/{id}/revoke: post: summary: Revoke an active sign-in link tags: [settings] parameters: - in: path name: id required: true schema: type: integer minimum: 1 responses: '200': description: Link revoked '404': description: Link not found '409': description: Link is no longer active /settings/prowlarr: get: summary: Get Prowlarr connection settings description: Returns the Prowlarr connection and category mapping. The API key is always redacted. tags: - settings responses: '200': description: Prowlarr settings returned content: application/json: schema: type: object properties: hostname: type: string port: type: integer useSsl: type: boolean baseUrl: type: string apiKey: type: string description: Redacted when a key is saved. apiKeyConfigured: type: boolean categoryMappings: $ref: '#/components/schemas/ProwlarrCategoryMappings' put: summary: Update Prowlarr connection settings description: Saves the Prowlarr address, API key, and per-medium category filters. The API key remains server-side. tags: - settings requestBody: required: true content: application/json: schema: type: object required: [hostname, port, useSsl, baseUrl, categoryMappings] properties: hostname: type: string port: type: integer minimum: 1 maximum: 65535 useSsl: type: boolean baseUrl: type: string apiKey: type: string clearApiKey: type: boolean categoryMappings: $ref: '#/components/schemas/ProwlarrCategoryMappings' responses: '200': description: Prowlarr settings updated '400': description: Invalid Prowlarr settings /settings/prowlarr/test: post: summary: Test a Prowlarr connection description: Checks Prowlarr connectivity and category coverage, then tests each enabled searchable indexer with bounded concurrency. Tests contact the indexer but do not grab or download releases. The submitted connection settings are not saved. Omit apiKey to use the saved key. Requires administrator permission. tags: - settings requestBody: required: true content: application/json: schema: type: object required: [hostname, port, useSsl] properties: hostname: type: string port: type: integer useSsl: type: boolean baseUrl: type: string apiKey: type: string categoryMappings: $ref: '#/components/schemas/ProwlarrCategoryMappings' responses: '200': description: Prowlarr management connection, indexer coverage, and per-indexer test results content: application/json: schema: $ref: '#/components/schemas/ProwlarrInventory' '400': description: Invalid Prowlarr settings '502': description: Prowlarr management API unavailable content: application/json: schema: type: object properties: error: type: string diagnostics: type: array items: $ref: '#/components/schemas/ProwlarrIndexerDiagnostic' /settings/prowlarr/coverage: get: summary: Get Prowlarr indexer coverage description: Returns enabled searchable indexers and the categories they advertise. This does not confirm grabs or imports. tags: - settings responses: '200': description: Prowlarr coverage returned, or not configured content: application/json: schema: oneOf: - type: object required: [configured] properties: configured: type: boolean enum: [false] - allOf: - type: object required: [configured] properties: configured: type: boolean enum: [true] - $ref: '#/components/schemas/ProwlarrInventory' '502': description: Prowlarr inventory unavailable /indexer-search/configuration: get: summary: Get direct indexer search availability description: Returns whether Prowlarr is configured and the selected category IDs. Requires Manage Requests permission. tags: - indexer search responses: '200': description: Prowlarr search configuration returned content: application/json: schema: type: object required: [configured, categories] properties: configured: type: boolean categories: type: array items: type: object required: [category, categoryIds] properties: category: type: string enum: [ movie, tv, music, ebook, audiobook, comic, magazine, retro, modern, game, sports, ] categoryIds: $ref: '#/components/schemas/ProwlarrCategoryIds' /indexer-search/search: post: summary: Search Prowlarr indexers description: Runs a bounded manual release search in Prowlarr for a SeerrNG medium. Results are informational and are not grabbed or imported. tags: - indexer search requestBody: required: true content: application/json: schema: type: object required: [category, query] properties: category: type: string enum: [ movie, tv, music, ebook, audiobook, comic, magazine, retro, modern, game, sports, ] query: type: string minLength: 2 maxLength: 256 offset: type: integer minimum: 0 maximum: 2000 multipleOf: 50 responses: '200': description: Prowlarr results returned content: application/json: schema: $ref: '#/components/schemas/ProwlarrSearchResultsResponse' '400': description: Invalid search input '409': description: Prowlarr is not configured for this category '429': description: Search rate limit reached '502': description: Prowlarr search failed /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 avatar: type: object properties: size: type: number example: 123456 imageCount: type: number example: 123 dnsCache: type: object properties: stats: type: object properties: size: type: number example: 1 maxSize: type: number example: 500 hits: type: number example: 19 misses: type: number example: 1 failures: type: number example: 0 ipv4Fallbacks: type: number example: 0 hitRate: type: number example: 0.95 entries: type: array additionalProperties: type: object properties: addresses: type: object properties: ipv4: type: number example: 1 ipv6: type: number example: 1 activeAddress: type: string example: 127.0.0.1 family: type: number example: 4 age: type: number example: 10 ttl: type: number example: 10 networkErrors: type: number example: 0 hits: type: number example: 1 misses: type: number example: 1 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/cache/dns/{dnsEntry}/flush: post: summary: Flush a specific DNS cache entry description: Flushes a specific DNS cache entry tags: - settings parameters: - in: path name: dnsEntry required: true schema: type: string responses: '204': description: 'Flushed dns 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/notifications/email: get: summary: Get email notification settings description: Returns current email notification settings in a JSON object. tags: - settings responses: '200': description: Returned email settings content: application/json: schema: $ref: '#/components/schemas/NotificationEmailSettings' post: summary: Update email notification settings description: Updates email notification settings with provided values tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/NotificationEmailSettings' responses: '200': description: 'Values were sucessfully updated' content: application/json: schema: $ref: '#/components/schemas/NotificationEmailSettings' /settings/notifications/email/test: post: summary: Test email settings description: Sends a test notification to the email agent. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/NotificationEmailSettings' responses: '204': description: Test notification attempted /settings/notifications/discord: get: summary: Get Discord notification settings description: Returns current Discord notification settings in a JSON object. tags: - settings responses: '200': description: Returned Discord settings content: application/json: schema: $ref: '#/components/schemas/DiscordSettings' post: summary: Update Discord notification settings description: Updates Discord notification settings with the provided values. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/DiscordSettings' responses: '200': description: 'Values were sucessfully updated' content: application/json: schema: $ref: '#/components/schemas/DiscordSettings' /settings/notifications/discord/test: post: summary: Test Discord settings description: Sends a test notification to the Discord agent. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/DiscordSettings' responses: '204': description: Test notification attempted /settings/notifications/pushbullet: get: summary: Get Pushbullet notification settings description: Returns current Pushbullet notification settings in a JSON object. tags: - settings responses: '200': description: Returned Pushbullet settings content: application/json: schema: $ref: '#/components/schemas/PushbulletSettings' post: summary: Update Pushbullet notification settings description: Update Pushbullet notification settings with the provided values. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/PushbulletSettings' responses: '200': description: 'Values were sucessfully updated' content: application/json: schema: $ref: '#/components/schemas/PushbulletSettings' /settings/notifications/pushbullet/test: post: summary: Test Pushbullet settings description: Sends a test notification to the Pushbullet agent. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/PushbulletSettings' responses: '204': description: Test notification attempted /settings/notifications/pushover: get: summary: Get Pushover notification settings description: Returns current Pushover notification settings in a JSON object. tags: - settings responses: '200': description: Returned Pushover settings content: application/json: schema: $ref: '#/components/schemas/PushoverSettings' post: summary: Update Pushover notification settings description: Update Pushover notification settings with the provided values. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/PushoverSettings' responses: '200': description: 'Values were sucessfully updated' content: application/json: schema: $ref: '#/components/schemas/PushoverSettings' /settings/notifications/pushover/test: post: summary: Test Pushover settings description: Sends a test notification to the Pushover agent. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/PushoverSettings' responses: '204': description: Test notification attempted /settings/notifications/pushover/sounds: get: summary: Get Pushover sounds description: Returns valid Pushover sound options in a JSON array. tags: - settings parameters: - in: query name: token required: true schema: type: string nullable: false responses: '200': description: Returned Pushover settings content: application/json: schema: type: array items: type: object properties: name: type: string description: type: string /settings/notifications/gotify: get: summary: Get Gotify notification settings description: Returns current Gotify notification settings in a JSON object. tags: - settings responses: '200': description: Returned Gotify settings content: application/json: schema: $ref: '#/components/schemas/GotifySettings' post: summary: Update Gotify notification settings description: Update Gotify notification settings with the provided values. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/GotifySettings' responses: '200': description: 'Values were sucessfully updated' content: application/json: schema: $ref: '#/components/schemas/GotifySettings' /settings/notifications/gotify/test: post: summary: Test Gotify settings description: Sends a test notification to the Gotify agent. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/GotifySettings' responses: '204': description: Test notification attempted /settings/notifications/ntfy: get: summary: Get ntfy.sh notification settings description: Returns current ntfy.sh notification settings in a JSON object. tags: - settings responses: '200': description: Returned ntfy.sh settings content: application/json: schema: $ref: '#/components/schemas/NtfySettings' post: summary: Update ntfy.sh notification settings description: Update ntfy.sh notification settings with the provided values. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/NtfySettings' responses: '200': description: 'Values were sucessfully updated' content: application/json: schema: $ref: '#/components/schemas/NtfySettings' /settings/notifications/ntfy/test: post: summary: Test ntfy.sh settings description: Sends a test notification to the ntfy.sh agent. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/NtfySettings' responses: '204': description: Test notification attempted /settings/notifications/slack: get: summary: Get Slack notification settings description: Returns current Slack notification settings in a JSON object. tags: - settings responses: '200': description: Returned slack settings content: application/json: schema: $ref: '#/components/schemas/SlackSettings' post: summary: Update Slack notification settings description: Updates Slack notification settings with the provided values. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/SlackSettings' responses: '200': description: 'Values were sucessfully updated' content: application/json: schema: $ref: '#/components/schemas/SlackSettings' /settings/notifications/slack/test: post: summary: Test Slack settings description: Sends a test notification to the Slack agent. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/SlackSettings' responses: '204': description: Test notification attempted /settings/notifications/telegram: get: summary: Get Telegram notification settings description: Returns current Telegram notification settings in a JSON object. tags: - settings responses: '200': description: Returned Telegram settings content: application/json: schema: $ref: '#/components/schemas/TelegramSettings' post: summary: Update Telegram notification settings description: Update Telegram notification settings with the provided values. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/TelegramSettings' responses: '200': description: 'Values were sucessfully updated' content: application/json: schema: $ref: '#/components/schemas/TelegramSettings' /settings/notifications/telegram/test: post: summary: Test Telegram settings description: Sends a test notification to the Telegram agent. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/TelegramSettings' responses: '204': description: Test notification attempted /settings/notifications/webpush: get: summary: Get Web Push notification settings description: Returns current Web Push notification settings in a JSON object. tags: - settings responses: '200': description: Returned web push settings content: application/json: schema: $ref: '#/components/schemas/WebPushSettings' post: summary: Update Web Push notification settings description: Updates Web Push notification settings with the provided values. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/WebPushSettings' responses: '200': description: 'Values were sucessfully updated' content: application/json: schema: $ref: '#/components/schemas/WebPushSettings' /settings/notifications/webpush/test: post: summary: Test Web Push settings description: Sends a test notification to the Web Push agent. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/WebPushSettings' responses: '204': description: Test notification attempted /settings/notifications/webhook: get: summary: Get webhook notification settings description: Returns current webhook notification settings in a JSON object. tags: - settings responses: '200': description: Returned webhook settings content: application/json: schema: $ref: '#/components/schemas/WebhookSettings' post: summary: Update webhook notification settings description: Updates webhook notification settings with the provided values. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/WebhookSettings' responses: '200': description: 'Values were sucessfully updated' content: application/json: schema: $ref: '#/components/schemas/WebhookSettings' /settings/notifications/webhook/test: post: summary: Test webhook settings description: Sends a test notification to the webhook agent. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/WebhookSettings' responses: '204': description: Test notification attempted /settings/discover: get: summary: Get all discover sliders description: Returns all discovery sliders. Built-in and custom made. tags: - settings responses: '200': description: Returned all discovery sliders content: application/json: schema: type: array items: $ref: '#/components/schemas/DiscoverSlider' post: summary: Batch update all sliders. description: | Batch update all sliders at once. Should also be used for creation. Will only update sliders provided and will not delete any sliders not present in the request. If a slider is missing a required field, it will be ignored. Requires the `ADMIN` permission. tags: - settings requestBody: required: true content: application/json: schema: type: array items: $ref: '#/components/schemas/DiscoverSlider' responses: '200': description: Returned all newly updated discovery sliders content: application/json: schema: type: array items: $ref: '#/components/schemas/DiscoverSlider' /settings/discover/{sliderId}: put: summary: Update a single slider description: | Updates a single slider and return the newly updated slider. Requires the `ADMIN` permission. tags: - settings parameters: - in: path name: sliderId required: true schema: type: number requestBody: required: true content: application/json: schema: type: object properties: title: type: string example: 'Slider Title' type: type: number example: 1 data: type: string example: '1' responses: '200': description: Returns newly added discovery slider content: application/json: schema: $ref: '#/components/schemas/DiscoverSlider' delete: summary: Delete slider by ID description: Deletes the slider with the provided sliderId. Requires the `ADMIN` permission. tags: - settings parameters: - in: path name: sliderId required: true schema: type: number responses: '200': description: Slider successfully deleted content: application/json: schema: $ref: '#/components/schemas/DiscoverSlider' /settings/discover/add: post: summary: Add a new slider description: | Add a single slider and return the newly created slider. Requires the `ADMIN` permission. tags: - settings requestBody: required: true content: application/json: schema: type: object properties: title: type: string example: 'New Slider' type: type: number example: 1 data: type: string example: '1' responses: '200': description: Returns newly added discovery slider content: application/json: schema: $ref: '#/components/schemas/DiscoverSlider' /settings/discover/reset: post: summary: Reset all discover sliders description: Resets all discovery sliders to the default values. Requires the `ADMIN` permission. tags: - settings responses: '204': description: All sliders reset to defaults /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/plex/pin: post: summary: Create a Plex OAuth PIN description: Creates a short-lived Plex OAuth PIN through the server-side Plex API proxy. security: [] tags: - auth responses: '200': description: Plex OAuth PIN details content: application/json: schema: type: object required: - id - code properties: id: type: integer code: type: string expiresAt: type: string nullable: true /auth/plex/pin/{id}: get: summary: Poll a Plex OAuth PIN description: Polls a server-side Plex OAuth PIN until Plex claims it. security: [] tags: - auth parameters: - in: path name: id required: true schema: type: integer minimum: 1 - in: query name: code required: true schema: type: string responses: '200': description: Current Plex OAuth PIN state content: application/json: schema: type: object required: - authToken properties: authToken: type: string nullable: true expiresAt: type: string nullable: true /auth/jellyfin: post: summary: Sign in using a Jellyfin username and password description: Takes the user's username and password 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 Jellyfin 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: username: type: string password: type: string hostname: type: string email: type: string serverType: type: number required: - username - password /auth/jellyfin/bridge: post: summary: Sign in to SeerrNG from a Jellyfin session description: Validates the current Jellyfin user's access token against the configured server and creates a SeerrNG session only for an already-linked account. The token is accepted in a form body and is never stored. security: [] tags: - auth requestBody: required: true content: application/x-www-form-urlencoded: schema: type: object additionalProperties: false required: [token] properties: token: type: string maxLength: 4096 responses: '303': description: SeerrNG session created; redirects to the configured application URL. '400': description: The form body or Jellyfin token is invalid. '403': description: Bridge login is disabled, the Jellyfin token is invalid, or the account is not linked. '409': description: Jellyfin settings changed during authentication. '502': description: SeerrNG could not validate the session with Jellyfin. /auth/jellyfin/quickconnect/initiate: post: summary: Initiate Jellyfin Quick Connect description: Initiates a Quick Connect session and returns a code for the user to authorize on their Jellyfin server. security: [] tags: - auth responses: '200': description: Quick Connect session initiated content: application/json: schema: type: object properties: code: type: string example: '123456' secret: type: string example: 'abc123def456' '500': description: Failed to initiate Quick Connect /auth/jellyfin/quickconnect/check: get: summary: Check Quick Connect authorization status description: Checks if the Quick Connect code has been authorized by the user. security: [] tags: - auth parameters: - in: query name: secret required: true schema: type: string description: The secret returned from the initiate endpoint responses: '200': description: Authorization status returned content: application/json: schema: type: object properties: authenticated: type: boolean example: false '404': description: Quick Connect session not found or expired /auth/jellyfin/quickconnect/authenticate: post: summary: Authenticate with Quick Connect description: Completes the Quick Connect authentication flow and creates a user session. security: [] tags: - auth requestBody: required: true content: application/json: schema: type: object properties: secret: type: string required: - secret responses: '200': description: Successfully authenticated content: application/json: schema: $ref: '#/components/schemas/User' '403': description: Quick Connect not authorized or access denied '500': description: Authentication failed /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/login-link: post: summary: Sign in with an admin-generated one-time link description: The token is accepted only in the request body. A successful sign-in consumes it atomically. security: [] tags: [auth] requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: [token] properties: token: type: string pattern: '^[A-Za-z0-9_-]{43}$' responses: '200': description: Signed in content: application/json: schema: $ref: '#/components/schemas/User' '403': description: The link is invalid, expired, revoked, or already used '409': description: Sign out before using a sign-in link /auth/oidc/login/{slug}: get: summary: Initiate OpenID Connect login description: Initiates the OpenID Connect authorization code flow with PKCE for the specified provider. Returns a redirect URL to the provider's authorization endpoint. security: [] tags: - auth parameters: - in: path name: slug required: true schema: type: string description: Provider slug - in: query name: returnUrl required: false allowReserved: true schema: type: string format: uri-reference description: URL to redirect to after login. Defaults to /login if not specified. responses: '200': description: OK content: application/json: schema: type: object properties: redirectUrl: type: string '403': description: OpenID Connect sign-in is disabled or provider not found content: application/json: schema: type: object properties: error: type: string example: 'UNAUTHORIZED' '500': description: An error occurred while creating the authorization redirect content: application/json: schema: type: object properties: error: type: string example: 'OIDC_AUTHORIZATION_FAILED' /auth/oidc/callback/{slug}: post: summary: Handle OpenID Connect callback description: Handles the authorization code callback from the OpenID Connect provider. Exchanges the code for tokens, validates claims, and either logs in an existing user, links the account to the currently logged-in user, or creates a new user if allowed. security: [] tags: - auth parameters: - in: path name: slug required: true schema: type: string description: Provider slug requestBody: required: true content: application/json: schema: type: object required: - callbackUrl properties: callbackUrl: type: string format: uri description: The full callback URL including the authorization code and any other parameters returned by the OIDC provider (e.g. https://example.com/login?code=xxx). example: 'https://example.com/login?code=xxx' responses: '204': description: Authentication successful. No response body. '400': description: Unable to create account (e.g. missing email address) content: application/json: schema: type: object properties: error: type: string example: 'OIDC_MISSING_EMAIL' '403': description: OpenID Connect sign-in is disabled, provider not found, or user does not meet required claims content: application/json: schema: type: object properties: error: type: string example: 'UNAUTHORIZED' '409': description: The OIDC account is already linked to a different user content: application/json: schema: type: object properties: error: type: string example: 'OIDC_ACCOUNT_ALREADY_LINKED' '500': description: An error occurred (e.g. provider discovery failed, authorization failed) content: application/json: schema: type: object properties: error: type: string example: 'OIDC_AUTHORIZATION_FAILED' /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, usertype, role] default: created - in: query name: sortDirection description: | Sort direction. When omitted, the server chooses the direction per sort field (e.g. displayname defaults to asc, requests/updated to desc). schema: type: string enum: [asc, desc] - in: query name: q required: false schema: type: string - in: query name: includeIds required: false schema: type: string 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 permissions and supported per-user Auto-Request settings for users with the given IDs. Omitted settings are left unchanged. 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 settings: type: object additionalProperties: false properties: watchlistSyncMovies: type: boolean watchlistSyncTv: type: boolean watchlistSyncMusic: type: boolean watchlistSyncBooks: type: boolean watchlistSyncComics: type: boolean watchlistSyncMagazines: type: boolean 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' /user/import-from-jellyfin: post: summary: Import all users from Jellyfin description: | Fetches and imports users from the Jellyfin server. Requires the `MANAGE_USERS` permission. tags: - users requestBody: required: false content: application/json: schema: type: object properties: jellyfinUserIds: 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' /user/registerPushSubscription: post: summary: Register a web push /user/registerPushSubscription description: Registers a web push subscription for the logged-in user tags: - users requestBody: required: true content: application/json: schema: type: object properties: endpoint: type: string auth: type: string p256dh: type: string userAgent: type: string required: - endpoint - auth - p256dh responses: '204': description: Successfully registered push subscription /user/{userId}/pushSubscriptions: get: summary: Get all web push notification settings for a user description: | Returns all web push notification settings for a user in a JSON object. tags: - users parameters: - in: path name: userId required: true schema: type: number responses: '200': description: User web push notification settings in JSON content: application/json: schema: type: object properties: endpoint: type: string p256dh: type: string auth: type: string userAgent: type: string /user/{userId}/pushSubscription/{endpoint}: get: summary: Get web push notification settings for a user description: | Returns web push notification settings for a user in a JSON object. tags: - users parameters: - in: path name: userId required: true schema: type: number - in: path name: endpoint required: true schema: type: string responses: '200': description: User web push notification settings in JSON content: application/json: schema: type: object properties: endpoint: type: string p256dh: type: string auth: type: string userAgent: type: string delete: summary: Delete user push subscription by key description: Deletes the user push subscription with the provided key. tags: - users parameters: - in: path name: userId required: true schema: type: number - in: path name: endpoint required: true schema: type: string responses: '204': description: Successfully removed user push subscription /user/{userId}: get: summary: Get user by ID description: | Retrieves user details in a JSON object. Requires the `MANAGE_USERS` permission. tags: - users parameters: - in: path name: userId required: true schema: type: number responses: '200': description: Users details in JSON content: application/json: schema: $ref: '#/components/schemas/User' put: summary: Update a user by user ID description: | Update a user with the provided values. You cannot update a user's Plex token through this request. Requires the `MANAGE_USERS` permission. tags: - users parameters: - in: path name: userId required: true schema: type: number requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/User' responses: '200': description: Successfully updated user details content: application/json: schema: $ref: '#/components/schemas/User' delete: summary: Delete user by ID description: Deletes the user with the provided userId. Requires the `MANAGE_USERS` permission. tags: - users parameters: - in: path name: userId required: true schema: type: number responses: '200': description: User successfully deleted content: application/json: schema: $ref: '#/components/schemas/User' /user/{userId}/avatar: put: summary: Upload a local user's profile picture description: | Replaces the signed-in local user's profile picture. Profile pictures for Plex, Jellyfin, and Emby accounts remain managed by their provider. tags: - users parameters: - in: path name: userId required: true schema: type: number requestBody: required: true content: image/jpeg: schema: type: string format: binary image/png: schema: type: string format: binary image/webp: schema: type: string format: binary responses: '200': description: Profile picture updated successfully content: application/json: schema: $ref: '#/components/schemas/User' '400': description: Invalid profile picture '403': description: Access denied '409': description: Profile picture is managed by a linked provider '413': description: Profile picture exceeds the upload limit /user/jellyfin/{jellyfinUserId}: get: summary: Get user by Jellyfin user ID description: | Retrieves user details by Jellyfin user ID in a JSON object. Returns filtered data based on the caller's permissions. tags: - users parameters: - in: path name: jellyfinUserId required: true schema: type: string description: The Jellyfin user ID (32-character hexadecimal string) responses: '200': description: User details in JSON content: application/json: schema: $ref: '#/components/schemas/User' '404': description: User not found /user/{userId}/requests: get: summary: Get requests for a specific user description: | Retrieves a user's requests in a JSON object. tags: - users parameters: - in: path name: userId required: true schema: type: number - in: query name: take schema: type: number nullable: true example: 20 - in: query name: skip schema: type: number nullable: true example: 0 responses: '200': description: User's requests returned content: application/json: schema: type: object properties: pageInfo: $ref: '#/components/schemas/PageInfo' results: type: array items: $ref: '#/components/schemas/MediaRequest' /user/{userId}/quota: get: summary: Get quotas for a specific user description: | Returns quota details for a user in a JSON object. Requires `MANAGE_USERS` permission if viewing other users. tags: - users parameters: - in: path name: userId required: true schema: type: number responses: '200': description: User quota details in JSON content: application/json: schema: type: object properties: movie: $ref: '#/components/schemas/QuotaStatus' tv: $ref: '#/components/schemas/QuotaStatus' music: $ref: '#/components/schemas/QuotaStatus' book: $ref: '#/components/schemas/QuotaStatus' comic: $ref: '#/components/schemas/QuotaStatus' magazine: $ref: '#/components/schemas/QuotaStatus' software: $ref: '#/components/schemas/QuotaStatus' /blocklist: get: summary: Returns blocklisted items description: Returns list of all blocklisted media tags: - blocklist 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: search schema: type: string nullable: true example: dune - in: query name: filter schema: type: string enum: [all, manual, blocklistedTags] default: all - in: query name: timeFrame schema: type: string enum: [all, 7d, 14d, 30d, 6m] default: all - in: query name: mediaType schema: type: string enum: [all, movie, tv, music, book, comic, magazine] default: all - in: query name: sort schema: type: string enum: [date, title, mediaType] default: date - in: query name: sortDirection schema: type: string enum: [asc, desc] default: desc responses: '200': description: Blocklisted items returned content: application/json: schema: type: object properties: pageInfo: $ref: '#/components/schemas/PageInfo' counts: type: object required: [all, manual, blocklistedTags] properties: all: type: integer manual: type: integer blocklistedTags: type: integer results: type: array items: type: object properties: user: $ref: '#/components/schemas/User' createdAt: type: string example: 2024-04-21T01:55:44.000Z id: type: number example: 1 mediaType: type: string example: movie title: type: string example: Dune tmdbId: type: number example: 438631 post: summary: Add media to blocklist tags: - blocklist requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/Blocklist' responses: '201': description: Item succesfully blocklisted '412': description: Item has already been blocklisted /blocklist/{tmdbId}: get: summary: Get media from blocklist tags: - blocklist parameters: - in: path name: tmdbId description: tmdbId ID required: true example: '1' schema: type: string - in: query name: mediaType required: true schema: type: string enum: - movie - tv - music - book - comic - magazine responses: '200': description: Blocklist details in JSON delete: summary: Remove media from blocklist tags: - blocklist parameters: - in: path name: tmdbId description: tmdbId ID required: true example: '1' schema: type: string - in: query name: mediaType required: true schema: type: string enum: - movie - tv - music - book - comic - magazine responses: '204': description: Succesfully removed media item /blacklist: get: summary: Returns blocklisted items description: | **DEPRECATED**: Use `/blocklist` instead. This endpoint will be deprecated soon. deprecated: true tags: - blocklist 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: search schema: type: string nullable: true example: dune - in: query name: filter schema: type: string enum: [all, manual, blocklistedTags] default: manual responses: '200': description: Blocklisted items returned content: application/json: schema: type: object properties: pageInfo: $ref: '#/components/schemas/PageInfo' results: type: array items: type: object properties: user: $ref: '#/components/schemas/User' createdAt: type: string example: 2024-04-21T01:55:44.000Z id: type: number example: 1 mediaType: type: string example: movie title: type: string example: Dune tmdbId: type: number example: 438631 post: summary: Add media to blocklist description: | **DEPRECATED**: Use `/blocklist` instead. This endpoint will be deprecated soon. deprecated: true tags: - blocklist requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/Blocklist' responses: '201': description: Item succesfully blocklisted '412': description: Item has already been blocklisted /blacklist/{tmdbId}: get: summary: Get media from blocklist description: | **DEPRECATED**: Use `/blocklist/{tmdbId}` instead. This endpoint will be deprecated soon. deprecated: true tags: - blocklist parameters: - in: path name: tmdbId description: tmdbId ID required: true example: '1' schema: type: string - in: query name: mediaType required: true schema: type: string enum: - movie - tv - music - book - comic - magazine responses: '200': description: Blocklist details in JSON delete: summary: Remove media from blocklist description: | **DEPRECATED**: Use `/blocklist/{tmdbId}` instead. This endpoint will be deprecated soon. deprecated: true tags: - blocklist parameters: - in: path name: tmdbId description: tmdbId ID required: true example: '1' schema: type: string - in: query name: mediaType required: true schema: type: string enum: - movie - tv - music - book responses: '204': description: Succesfully removed media item /blocklist/collection/{collectionId}: post: summary: Add collection to blocklist description: Adds all movies in a collection to the blocklist tags: - blocklist parameters: - in: path name: collectionId description: Collection ID required: true example: '1424991' schema: type: string requestBody: required: false content: application/json: schema: type: object responses: '201': description: Successfully added collection to blocklist '500': description: Error adding collection to blocklist delete: summary: Remove collection from blocklist description: Removes all movies in a collection from the blocklist tags: - blocklist parameters: - in: path name: collectionId description: Collection ID required: true example: '1424991' schema: type: string responses: '204': description: Successfully removed collection from blocklist '500': description: Error removing collection from blocklist /watchlist: post: summary: Add media to watchlist tags: - watchlist requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/Watchlist' responses: '200': description: Watchlist data returned content: application/json: schema: $ref: '#/components/schemas/Watchlist' /watchlist/{mediaId}: delete: summary: Delete watchlist item description: Removes a watchlist item. tags: - watchlist parameters: - in: path name: mediaId description: TMDB ID, external media ID, or magazine title required: true example: '1' schema: type: string - in: query name: mediaType required: true schema: type: string enum: - movie - tv - music - book - comic - magazine responses: '204': description: Succesfully removed watchlist item /user/{userId}/watchlist: get: summary: Get the Plex watchlist for a specific user description: | Retrieves a user's Plex Watchlist in a JSON object. tags: - users - watchlist parameters: - in: path name: userId required: true schema: type: number - in: query name: page schema: type: number example: 1 default: 1 responses: '200': description: Watchlist data returned content: application/json: schema: type: object properties: page: type: number totalPages: type: number totalResults: type: number results: type: array items: type: object properties: tmdbId: type: number example: 1 ratingKey: type: string type: type: string title: type: string /user/{userId}/settings/main: get: summary: Get general settings for a user description: Returns general settings for a specific user. Requires `MANAGE_USERS` permission if viewing other users. tags: - users parameters: - in: path name: userId required: true schema: type: number responses: '200': description: User general settings returned content: application/json: schema: $ref: '#/components/schemas/UserSettings' post: summary: Update general settings for a user description: Updates and returns general settings for a specific user. Requires `MANAGE_USERS` permission if editing other users. tags: - users parameters: - in: path name: userId required: true schema: type: number requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UserSettings' responses: '200': description: Updated user general settings returned content: application/json: schema: $ref: '#/components/schemas/UserSettings' /user/{userId}/settings/request-root-folders: get: summary: Get a user's default request folders description: Returns root-folder preferences for that user. Other users' preferences are visible to request managers and user managers. tags: - users parameters: - in: path name: userId required: true schema: type: number responses: '200': description: Request-folder preferences returned content: application/json: schema: type: object additionalProperties: type: string '403': description: Caller may not view this user's preferences '404': description: User not found /user/{userId}/settings/preferred-languages: get: summary: Get preferred languages for a user description: Returns only the user's preferred language settings. Other users' preferences are visible to request managers and user managers. tags: - users parameters: - in: path name: userId required: true schema: type: number responses: '200': description: Preferred language settings returned content: application/json: schema: type: object additionalProperties: false properties: all: type: string movie: type: string nullable: true tv: type: string nullable: true music: type: string nullable: true book: type: string nullable: true /user/{userId}/settings/card-text: get: summary: Get card text visibility settings for a user description: Returns per-media card title visibility preferences for a specific user. Requires `MANAGE_USERS` permission if viewing other users. tags: - users parameters: - in: path name: userId required: true schema: type: number responses: '200': description: Card text visibility settings returned content: application/json: schema: $ref: '#/components/schemas/CardTextVisibilitySettings' post: summary: Update card text visibility settings for a user description: Updates and returns per-media card title visibility preferences for a specific user. Requires `MANAGE_USERS` permission if editing other users. tags: - users parameters: - in: path name: userId required: true schema: type: number requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CardTextVisibilitySettings' responses: '200': description: Updated card text visibility settings returned content: application/json: schema: $ref: '#/components/schemas/CardTextVisibilitySettings' /user/{userId}/settings/detail-disclosures: get: summary: Get pinned detail disclosure settings for a user description: Returns persistent Cast, Crew, Artists, and Subject Tags pin preferences for a specific user. Requires `MANAGE_USERS` permission if viewing another user. tags: - users parameters: - in: path name: userId required: true schema: type: number responses: '200': description: Pinned detail disclosure settings returned content: application/json: schema: $ref: '#/components/schemas/DetailDisclosurePinSettings' post: summary: Update pinned detail disclosure settings for a user description: Updates and returns persistent Cast, Crew, and Subject Tags pin preferences for a specific user. Requires `MANAGE_USERS` permission if editing another user. tags: - users parameters: - in: path name: userId required: true schema: type: number requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/DetailDisclosurePinSettings' responses: '200': description: Updated pinned detail disclosure settings returned content: application/json: schema: $ref: '#/components/schemas/DetailDisclosurePinSettings' /user/{userId}/settings/detail-disclosures/{mediaType}: get: summary: Get pinned detail disclosure settings for one media category description: Returns persistent disclosure pins scoped independently to Movie, Series, Music, or Book details. Requires `MANAGE_USERS` permission if viewing another user. tags: - users parameters: - in: path name: userId required: true schema: type: number - in: path name: mediaType required: true schema: type: string enum: [movie, tv, music, book, comic] responses: '200': description: Category-scoped detail disclosure settings returned content: application/json: schema: $ref: '#/components/schemas/DetailDisclosurePinSettings' post: summary: Update pinned detail disclosure settings for one media category description: Updates persistent disclosure pins without changing the pin state of another media category. Requires `MANAGE_USERS` permission if editing another user. tags: - users parameters: - in: path name: userId required: true schema: type: number - in: path name: mediaType required: true schema: type: string enum: [movie, tv, music, book, comic] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/DetailDisclosurePinSettings' responses: '200': description: Updated category-scoped detail disclosure settings returned content: application/json: schema: $ref: '#/components/schemas/DetailDisclosurePinSettings' /user/{id}/settings/discover-book-sections: get: summary: Get the current user's ordered book and audiobook home sections tags: [users] parameters: - in: path name: id required: true schema: type: integer minimum: 1 responses: '200': description: Section order and visibility post: summary: Save the current user's ordered book and audiobook home sections tags: [users] parameters: - in: path name: id required: true schema: type: integer minimum: 1 requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: [sections] properties: sections: type: array maxItems: 20 items: $ref: '#/components/schemas/BookHomeSectionPreference' responses: '200': description: Saved section order and visibility '400': description: Invalid section selection '403': description: The profile does not belong to the signed-in user /user/{id}/settings/detail-disclosure-order/{mediaType}: parameters: - in: path name: id required: true schema: type: integer minimum: 1 - in: path name: mediaType required: true schema: type: string enum: [tv] get: summary: Get the current user's Series detail disclosure order description: Self-only, including administrators. Returns all six roles in normalized order. Overview defaults first when absent; explicitly saved placement is preserved. tags: [users] responses: '200': description: Normalized disclosure order content: application/json: schema: &detailDisclosureOrder type: array minItems: 6 maxItems: 6 uniqueItems: true items: type: string enum: [cast, crew, subjectTags, details, mediaServer, overview] '400': description: Invalid media category '403': description: Not the current authenticated user '404': description: Invalid or nonexistent user post: summary: Save the current user's Series detail disclosure order description: Self-only authenticated operation, protected by the application's cookie and CSRF middleware. Overview defaults first when absent; other missing roles are appended in their default order. Explicitly saved placements and the relative order of existing roles are preserved. tags: [users] requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: [order] properties: order: type: array maxItems: 6 uniqueItems: true items: type: string enum: [cast, crew, subjectTags, details, mediaServer, overview] responses: '200': description: Saved normalized disclosure order content: application/json: schema: *detailDisclosureOrder '400': description: Invalid media category or order '403': description: Not the current authenticated user '404': description: Invalid or nonexistent user '500': description: Disclosure order could not be saved /user/{userId}/settings/media-filter-pins/{scope}: post: summary: Remember or unpin a media filter selection for one page tags: [users] parameters: - in: path name: userId required: true schema: type: number - in: path name: scope required: true schema: type: string enum: [books, trending, search, blocklist, issues, requests] requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: [value] properties: value: type: string nullable: true enum: [ all, movie, tv, music, book, ebook, audiobook, comic, magazine, author, software, retro, modern, game, null, ] responses: '200': description: Updated account media filter pins content: application/json: schema: type: object additionalProperties: type: string /user/{userId}/settings/theme: post: summary: Save the signed-in user's theme preference tags: [users] parameters: - in: path name: userId required: true schema: type: number requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: [palette] properties: palette: type: string maxLength: 32 responses: '200': description: Confirmed account theme preference content: application/json: schema: type: object additionalProperties: false required: [themePalette] properties: themePalette: type: string '400': description: Invalid theme palette '403': description: Only the signed-in user can change their theme /user/{userId}/settings/advanced-theme: post: summary: Save or clear a user's advanced theme overrides description: Stores supported visual theme token overrides for the signed-in user. Send null to clear the overrides. tags: [users] parameters: - in: path name: userId required: true schema: type: number requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: [overrides] properties: overrides: nullable: true type: object additionalProperties: oneOf: - type: string - type: number responses: '200': description: Saved theme overrides returned content: application/json: schema: type: object additionalProperties: false required: [advancedThemeOverrides] properties: advancedThemeOverrides: nullable: true type: object additionalProperties: oneOf: - type: string - type: number /user/{userId}/settings/password: get: summary: Get password page informatiom description: Returns important data for the password page to function correctly. Requires `MANAGE_USERS` permission if viewing other users. tags: - users parameters: - in: path name: userId required: true schema: type: number responses: '200': description: User password page information returned content: application/json: schema: type: object properties: hasPassword: type: boolean example: true post: summary: Update password for a user description: Updates a user's password. Requires `MANAGE_USERS` permission if editing other users. tags: - users parameters: - in: path name: userId required: true schema: type: number requestBody: required: true content: application/json: schema: type: object properties: currentPassword: type: string nullable: true newPassword: type: string required: - newPassword responses: '204': description: User password updated /user/{userId}/settings/linked-accounts: get: summary: Lists the user's linked OpenID Connect accounts description: Lists the user's linked OpenID Connect accounts tags: - users parameters: - in: path name: userId required: true schema: type: number responses: '200': description: List of linked accounts content: application/json: schema: type: array items: $ref: '#/components/schemas/LinkedAccount' '403': description: Insufficient permissions /user/{userId}/settings/linked-accounts/plex: post: summary: Link the provided Plex account to the current user description: Logs in to Plex with the provided auth token, then links the associated Plex account with the user's account. Users can only link external accounts to their own account. tags: - users parameters: - in: path name: userId required: true schema: type: number requestBody: required: true content: application/json: schema: type: object properties: authToken: type: string required: - authToken responses: '204': description: Linking account succeeded '403': description: Invalid credentials '422': description: Account already linked to a user delete: summary: Remove the linked Plex account for a user description: Removes the linked Plex account for a specific user. Requires `MANAGE_USERS` permission if editing other users. tags: - users parameters: - in: path name: userId required: true schema: type: number responses: '204': description: Unlinking account succeeded '400': description: Unlink request invalid '404': description: User does not exist /user/{userId}/settings/linked-accounts/jellyfin: post: summary: Link the provided Jellyfin account to the current user description: Logs in to Jellyfin with the provided credentials, then links the associated Jellyfin account with the user's account. Users can only link external accounts to their own account. tags: - users parameters: - in: path name: userId required: true schema: type: number requestBody: required: true content: application/json: schema: type: object properties: username: type: string example: 'Mr User' password: type: string example: 'supersecret' responses: '204': description: Linking account succeeded '403': description: Invalid credentials '422': description: Account already linked to a user delete: summary: Remove the linked Jellyfin account for a user description: Removes the linked Jellyfin account for a specific user. Requires `MANAGE_USERS` permission if editing other users. tags: - users parameters: - in: path name: userId required: true schema: type: number responses: '204': description: Unlinking account succeeded '400': description: Unlink request invalid '404': description: User does not exist /user/{userId}/settings/linked-accounts/jellyfin/quickconnect: post: summary: Link Jellyfin/Emby account with Quick Connect description: Links a Jellyfin/Emby account to the user's profile using Quick Connect authentication tags: - users parameters: - in: path name: userId required: true schema: type: number requestBody: required: true content: application/json: schema: type: object properties: secret: type: string required: - secret responses: '400': description: Invalid Quick Connect secret '204': description: Account successfully linked '401': description: Unauthorized '422': description: Account already linked '500': description: Server error /user/{userId}/settings/linked-accounts/{acctId}: delete: summary: Remove a linked account for a user description: Removes the linked account with the given ID for a specific user. Requires `MANAGE_USERS` permission if editing other users. tags: - users parameters: - in: path name: userId required: true schema: type: number - in: path name: acctId required: true schema: type: number responses: '204': description: Unlinking account succeeded '400': description: Unlink request invalid '403': description: Insufficient permissions '404': description: User or linked account does not exist /user/{userId}/settings/notifications: get: summary: Get notification settings for a user description: Returns notification settings for a specific user. Requires `MANAGE_USERS` permission if viewing other users. tags: - users parameters: - in: path name: userId required: true schema: type: number responses: '200': description: User notification settings returned content: application/json: schema: $ref: '#/components/schemas/UserSettingsNotifications' post: summary: Update notification settings for a user description: Updates and returns notification settings for a specific user. Requires `MANAGE_USERS` permission if editing other users. tags: - users parameters: - in: path name: userId required: true schema: type: number requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UserSettingsNotifications' responses: '200': description: Updated user notification settings returned content: application/json: schema: $ref: '#/components/schemas/UserSettingsNotifications' /user/{userId}/settings/permissions: get: summary: Get permission settings for a user description: Returns permission settings for a specific user. Requires `MANAGE_USERS` permission if viewing other users. tags: - users parameters: - in: path name: userId required: true schema: type: number responses: '200': description: User permission settings returned content: application/json: schema: type: object properties: permissions: type: number example: 2 post: summary: Update permission settings for a user description: Updates and returns permission settings for a specific user. Requires `MANAGE_USERS` permission if editing other users. tags: - users parameters: - in: path name: userId required: true schema: type: number requestBody: required: true content: application/json: schema: type: object properties: permissions: type: number required: - permissions responses: '200': description: Updated user general settings returned content: application/json: schema: type: object properties: permissions: type: number example: 2 /user/{userId}/watch_data: get: summary: Get watch data description: | Returns play count, play duration, and recently watched media. Requires the `ADMIN` permission to fetch results for other users. tags: - users parameters: - in: path name: userId required: true schema: type: number responses: '200': description: Users content: application/json: schema: type: object properties: recentlyWatched: type: array items: $ref: '#/components/schemas/MediaInfo' playCount: type: number /search: get: summary: Search for movies, TV shows, people, music, books, authors, comics, and magazines description: Returns movies, TV shows, people, music albums, artists, books, authors, and comics from TMDB, MusicBrainz, ListenBrainz, Open Library, configured Bookshelf services, and ComicVine, plus magazine titles from configured LazyLibrarian catalogs. tags: - search parameters: - in: query name: query required: true schema: type: string example: 'Mulan' - in: query name: page schema: type: number example: 1 default: 1 - in: query name: language schema: type: string example: en - in: query name: type schema: type: string enum: - movie - tv - person - album - artist - book - author - music - comic - magazine description: Filter results by media type. When omitted, all types are returned. - in: query name: format schema: type: string enum: - ebook - audiobook description: Select the configured book service format. Valid only when type is book. - in: query name: resultFilter schema: type: string description: Refine music search results by album title while preserving the main search query. - in: query name: artist schema: { type: string, maxLength: 256 } description: Restrict Music results to the credited artist before pagination. - in: query name: artistId schema: { type: string, maxLength: 36 } description: Exact MusicBrainz artist identifier selected from autocomplete. - in: query name: genre schema: { type: string, maxLength: 256 } - in: query name: releaseType schema: { type: string, maxLength: 256 } - in: query name: primaryReleaseDateGte schema: { type: string, maxLength: 10 } - in: query name: primaryReleaseDateLte schema: { type: string, maxLength: 10 } responses: '200': description: Results 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: anyOf: - $ref: '#/components/schemas/MovieResult' - $ref: '#/components/schemas/TvResult' - $ref: '#/components/schemas/PersonResult' - $ref: '#/components/schemas/MusicResult' - $ref: '#/components/schemas/ArtistResult' - $ref: '#/components/schemas/BookResult' - $ref: '#/components/schemas/AuthorResult' - $ref: '#/components/schemas/ComicResult' - $ref: '#/components/schemas/MagazineResult' /search/keyword: get: summary: Search for keywords description: Returns a list of TMDB keywords matching the search query tags: - search parameters: - in: query name: query required: true schema: type: string example: 'christmas' - in: query name: page schema: type: number example: 1 default: 1 responses: '200': description: Results 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/Keyword' /search/company: get: summary: Search for companies description: Returns a list of TMDB companies matching the search query. (Will not return origin country) tags: - search parameters: - in: query name: query required: true schema: type: string example: 'Disney' - in: query name: page schema: type: number example: 1 default: 1 responses: '200': description: Results 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/Company' /discover/home/manifest: get: summary: Get the Discover homepage synchronization manifest description: Returns stable layout and personalized-state revisions. Row descriptor revisions do not track upstream catalog content. tags: - discover responses: '200': description: Discover homepage manifest content: application/json: schema: $ref: '#/components/schemas/DiscoverHomeManifest' '304': description: Manifest revisions are unchanged /discover/home/state: post: summary: Get personalized state for a bounded set of Discover items tags: - discover requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: - items properties: items: type: array minItems: 1 maxItems: 100 items: oneOf: - type: object additionalProperties: false required: [mediaType, id] properties: mediaType: type: string enum: [movie, tv] id: type: integer minimum: 1 maximum: 1000000000 - type: object additionalProperties: false required: [mediaType, id] properties: mediaType: type: string enum: [music, book] id: type: string minLength: 1 maxLength: 128 responses: '200': description: Personalized media, request, and watchlist state content: application/json: schema: $ref: '#/components/schemas/DiscoverHomeState' '400': description: Invalid item list /discover/movies: get: summary: Discover movies description: Returns a list of movies in a JSON object. tags: - search parameters: - in: query name: page schema: type: number example: 1 default: 1 - in: query name: language schema: type: string example: en - in: query name: search description: Searches movie titles instead of using structured discovery filters schema: type: string maxLength: 256 example: Star Trek - in: query name: availability description: Selects the client-side scanned library quality view schema: type: string enum: [hd, 4k] - in: query name: genre schema: type: string example: 18 - in: query name: studio schema: type: number example: 1 - in: query name: keywords schema: type: string example: 1,2 - in: query name: excludeKeywords schema: type: string example: 3,4 description: Comma-separated list of keyword IDs to exclude from results - in: query name: sortBy schema: type: string example: popularity.desc - in: query name: primaryReleaseDateGte schema: type: string example: 2022-01-01 - in: query name: primaryReleaseDateLte schema: type: string example: 2023-01-01 - in: query name: withRuntimeGte schema: type: number example: 60 - in: query name: withRuntimeLte schema: type: number example: 120 - in: query name: voteAverageGte schema: type: number example: 7 - in: query name: voteAverageLte schema: type: number example: 10 - in: query name: voteCountGte schema: type: number example: 7 - in: query name: voteCountLte schema: type: number example: 10 - in: query name: watchRegion schema: type: string example: US - in: query name: watchProviders schema: type: string example: 8|9 - in: query name: certification schema: type: string example: PG-13 description: Exact certification to filter by (used when certificationMode is 'exact') - in: query name: certificationGte schema: type: string example: G description: Minimum certification to filter by (used when certificationMode is 'range') - in: query name: certificationLte schema: type: string example: PG-13 description: Maximum certification to filter by (used when certificationMode is 'range') - in: query name: certificationCountry schema: type: string example: US description: Country code for the certification system (e.g., US, GB, CA) - in: query name: certificationMode schema: type: string enum: [exact, range] example: exact description: Determines whether to use exact certification matching or a certification range (internal use only, not sent to TMDB API) - in: query name: shuffleSeed schema: type: string maxLength: 128 example: refresh-1 responses: '200': description: Results content: application/json: schema: type: object properties: page: type: number example: 1 totalPages: type: number example: 20 totalResults: type: number example: 200 stale: type: boolean description: True when saved results are served because TMDB is unavailable. results: type: array items: $ref: '#/components/schemas/MovieResult' /discover/movies/genre/{genreId}: get: summary: Discover movies by genre description: Returns a list of movies based on the provided genre ID in a JSON object. tags: - search parameters: - in: path name: genreId required: true schema: type: string example: '1' - in: query name: page schema: type: number example: 1 default: 1 - in: query name: language schema: type: string example: en responses: '200': description: Results content: application/json: schema: type: object properties: page: type: number example: 1 totalPages: type: number example: 20 totalResults: type: number example: 200 genre: $ref: '#/components/schemas/Genre' results: type: array items: $ref: '#/components/schemas/MovieResult' /discover/movies/language/{language}: get: summary: Discover movies by original language description: Returns a list of movies based on the provided ISO 639-1 language code in a JSON object. tags: - search parameters: - in: path name: language required: true schema: type: string example: en - in: query name: page schema: type: number example: 1 default: 1 - in: query name: language schema: type: string example: en responses: '200': description: Results content: application/json: schema: type: object properties: page: type: number example: 1 totalPages: type: number example: 20 totalResults: type: number example: 200 language: $ref: '#/components/schemas/SpokenLanguage' results: type: array items: $ref: '#/components/schemas/MovieResult' /discover/movies/studio/{studioId}: get: summary: Discover movies by studio description: Returns a list of movies based on the provided studio ID in a JSON object. tags: - search parameters: - in: path name: studioId required: true schema: type: string example: '1' - in: query name: page schema: type: number example: 1 default: 1 - in: query name: language schema: type: string example: en responses: '200': description: Results content: application/json: schema: type: object properties: page: type: number example: 1 totalPages: type: number example: 20 totalResults: type: number example: 200 studio: $ref: '#/components/schemas/ProductionCompany' results: type: array items: $ref: '#/components/schemas/MovieResult' /discover/movies/upcoming: get: summary: Upcoming movies description: Returns a list of movies in a JSON object. tags: - search parameters: - in: query name: page schema: type: number example: 1 default: 1 - in: query name: language schema: type: string example: en responses: '200': description: Results 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' /discover/tv: get: summary: Discover TV shows description: Returns a list of TV shows in a JSON object. tags: - search parameters: - in: query name: page schema: type: number example: 1 default: 1 - in: query name: language schema: type: string example: en - in: query name: search description: Searches TV titles instead of using structured discovery filters schema: type: string maxLength: 256 example: Reacher - in: query name: availability description: Selects the client-side scanned library quality view schema: type: string enum: [hd, 4k] - in: query name: genre schema: type: string example: 18 - in: query name: network schema: type: number example: 1 - in: query name: keywords schema: type: string example: 1,2 - in: query name: excludeKeywords schema: type: string example: 3,4 description: Comma-separated list of keyword IDs to exclude from results - in: query name: sortBy schema: type: string example: popularity.desc - in: query name: firstAirDateGte schema: type: string example: 2022-01-01 - in: query name: firstAirDateLte schema: type: string example: 2023-01-01 - in: query name: withRuntimeGte schema: type: number example: 60 - in: query name: withRuntimeLte schema: type: number example: 120 - in: query name: voteAverageGte schema: type: number example: 7 - in: query name: voteAverageLte schema: type: number example: 10 - in: query name: voteCountGte schema: type: number example: 7 - in: query name: voteCountLte schema: type: number example: 10 - in: query name: watchRegion schema: type: string example: US - in: query name: watchProviders schema: type: string example: 8|9 - in: query name: status schema: type: string example: 3|4 - in: query name: certification schema: type: string example: TV-14 description: Exact certification to filter by (used when certificationMode is 'exact') - in: query name: certificationGte schema: type: string example: TV-PG description: Minimum certification to filter by (used when certificationMode is 'range') - in: query name: certificationLte schema: type: string example: TV-MA description: Maximum certification to filter by (used when certificationMode is 'range') - in: query name: certificationCountry schema: type: string example: US description: Country code for the certification system (e.g., US, GB, CA) - in: query name: certificationMode schema: type: string enum: [exact, range] example: exact description: Determines whether to use exact certification matching or a certification range (internal use only, not sent to TMDB API) - in: query name: shuffleSeed schema: type: string maxLength: 128 example: refresh-1 responses: '200': description: Results 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/TvResult' /discover/tv/language/{language}: get: summary: Discover TV shows by original language description: Returns a list of TV shows based on the provided ISO 639-1 language code in a JSON object. tags: - search parameters: - in: path name: language required: true schema: type: string example: en - in: query name: page schema: type: number example: 1 default: 1 - in: query name: language schema: type: string example: en responses: '200': description: Results content: application/json: schema: type: object properties: page: type: number example: 1 totalPages: type: number example: 20 totalResults: type: number example: 200 language: $ref: '#/components/schemas/SpokenLanguage' results: type: array items: $ref: '#/components/schemas/TvResult' /discover/tv/genre/{genreId}: get: summary: Discover TV shows by genre description: Returns a list of TV shows based on the provided genre ID in a JSON object. tags: - search parameters: - in: path name: genreId required: true schema: type: string example: '1' - in: query name: page schema: type: number example: 1 default: 1 - in: query name: language schema: type: string example: en responses: '200': description: Results content: application/json: schema: type: object properties: page: type: number example: 1 totalPages: type: number example: 20 totalResults: type: number example: 200 genre: $ref: '#/components/schemas/Genre' results: type: array items: $ref: '#/components/schemas/TvResult' /discover/tv/network/{networkId}: get: summary: Discover TV shows by network description: Returns a list of TV shows based on the provided network ID in a JSON object. tags: - search parameters: - in: path name: networkId required: true schema: type: string example: '1' - in: query name: page schema: type: number example: 1 default: 1 - in: query name: language schema: type: string example: en responses: '200': description: Results content: application/json: schema: type: object properties: page: type: number example: 1 totalPages: type: number example: 20 totalResults: type: number example: 200 network: $ref: '#/components/schemas/Network' results: type: array items: $ref: '#/components/schemas/TvResult' /discover/tv/upcoming: get: summary: Discover Upcoming TV shows description: Returns a list of upcoming TV shows in a JSON object. tags: - search parameters: - in: query name: page schema: type: number example: 1 default: 1 - in: query name: language schema: type: string example: en responses: '200': description: Results 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/TvResult' /discover/trending: get: summary: Trending movies and TV description: Returns a list of trending movies, TV shows, and people from TMDB in a JSON object. tags: - search parameters: - in: query name: page schema: type: number example: 1 default: 1 - in: query name: language schema: type: string example: en - in: query name: mediaType schema: type: string enum: - all - movie - tv default: all - in: query name: timeWindow schema: type: string enum: - day - week default: day responses: '200': description: Results 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: anyOf: - $ref: '#/components/schemas/MovieResult' - $ref: '#/components/schemas/TvResult' - $ref: '#/components/schemas/PersonResult' /discover/list/{listId}: get: summary: Browse a public TMDB list description: Returns a paginated public TMDB list with mixed movie and series results. tags: - search parameters: - in: path name: listId required: true schema: type: string pattern: '^[1-9][0-9]{0,11}$' example: '8254132' - in: query name: page schema: type: number minimum: 1 maximum: 500 default: 1 - in: query name: language schema: type: string example: en responses: '200': description: Public list results. content: application/json: schema: type: object required: - page - totalPages - totalResults - list - results properties: page: type: number example: 1 totalPages: type: number example: 8 totalResults: type: number description: TMDB v4 list item_count. example: 158 list: type: object required: - name - description properties: name: type: string example: Weekend watchlist description: type: string example: A collection of films and series. results: type: array items: anyOf: - $ref: '#/components/schemas/MovieResult' - $ref: '#/components/schemas/TvResult' '400': description: Invalid language query. '404': description: The list does not exist or is not public. '502': description: TMDB could not return the list. /discover/music: get: summary: Discover music description: Returns fresh music releases from ListenBrainz. tags: - search parameters: - in: query name: page schema: type: number example: 1 default: 1 - in: query name: days schema: type: number enum: - 7 - 14 - 30 - 90 default: 14 - in: query name: sortBy schema: type: string enum: - ranked - ranked.asc - popular.week - popular.week.asc - popular.month - popular.month.asc - popular.year - popular.year.asc - listen_count.desc - listen_count.asc - release_date.desc - release_date.asc default: ranked - in: query name: genre schema: type: string example: jazz - in: query name: releaseType schema: type: string example: Album - in: query name: primaryReleaseDateGte schema: type: string example: '2024-01-01' - in: query name: primaryReleaseDateLte schema: type: string example: '2024-12-31' - in: query name: query schema: type: string example: kind of blue - in: query name: artist schema: { type: string, maxLength: 256 } description: Restrict results to the credited artist before pagination. - in: query name: artistId schema: { type: string, maxLength: 36 } description: Exact MusicBrainz artist identifier selected from autocomplete. - in: query name: availability description: Selects the client-side scanned Lidarr quality view schema: type: string enum: [mp3, flac] - in: query name: shuffleSeed schema: type: string maxLength: 128 example: refresh-1 responses: '200': description: Music discovery results content: application/json: schema: type: object properties: page: type: number example: 1 totalPages: type: number example: 2 totalResults: type: number example: 20 results: type: array items: $ref: '#/components/schemas/MusicResult' /discover/books: get: summary: Discover books description: Returns book discovery results from Open Library, or audiobook narrator matches from configured Bookshelf catalogs. tags: - search parameters: - in: query name: page schema: type: number example: 1 default: 1 - in: query name: query schema: type: string example: subject:fiction - in: query name: author schema: type: string maxLength: 256 description: Author terms sent to the book provider alongside the other search constraints. - in: query name: narrator schema: type: string maxLength: 256 description: Audiobook-only narrator terms matched against populated Bookshelf narrator metadata. Only books in configured audiobook libraries can match. - in: query name: subject schema: type: string example: fiction - in: query name: format schema: type: string enum: [ebook, audiobook] description: Format context for book requests from this discovery view. - in: query name: sortBy schema: type: string enum: - ranked - ranked.asc - newest - oldest - random - rating - rating.asc - rating.desc - editions - editions.asc - trending default: ranked - in: query name: firstPublishYear schema: type: string maxLength: 16 example: '2024' - in: query name: language schema: type: string maxLength: 3 example: eng - in: query name: minRating schema: type: string maxLength: 3 example: '4.0' - in: query name: shuffleSeed schema: type: string maxLength: 128 example: refresh-1 - in: query name: responseVersion description: Client response-contract version used to retire incompatible browser cache entries. schema: type: integer enum: [2, 3] default: 3 responses: '200': description: Book discovery results 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/BookResult' /discover/comics: get: summary: Discover comics description: Returns comic discovery results from ComicVine. Publisher, start-year, and issue-count filters use a durable local volume index; while its first scan runs, the response includes indexing progress and no filtered results. Empty if no ComicVine API key is configured. tags: - search parameters: - in: query name: page schema: type: number example: 1 default: 1 - in: query name: query schema: type: string example: Batman - in: query name: publisher schema: type: string maxLength: 128 - in: query name: startYear schema: type: integer minimum: 1800 maximum: 2200 - in: query name: minIssues schema: type: integer minimum: 0 maximum: 100000 - in: query name: maxIssues schema: type: integer minimum: 0 maximum: 100000 responses: '200': description: Comic discovery results content: application/json: schema: type: object properties: page: type: number example: 1 totalPages: type: number example: 20 totalResults: type: number example: 200 comicVineConfigured: type: boolean description: Whether a ComicVine API key is configured. indexing: type: boolean description: True while the first complete filtered catalog index is building. indexedResults: type: integer description: Volumes scanned so far when indexing is true. expectedResults: type: integer description: ComicVine's reported volume count when indexing is true. indexError: type: string nullable: true description: A safe, non-secret code describing the most recent index retry. lastIndexedAt: type: integer description: Unix timestamp of the last complete index used for filtered results. results: type: array items: $ref: '#/components/schemas/ComicResult' /discover/sports: get: summary: Search Sportarr leagues description: Searches the configured default Sportarr catalog and annotates each league with its current library and request state. Requires an authenticated user and the Sports media category to be enabled. tags: - search parameters: - in: query name: query description: League title search. An empty query returns an empty page. schema: type: string maxLength: 256 - in: query name: page schema: type: integer minimum: 1 maximum: 500 default: 1 responses: '200': description: Sportarr league search results content: application/json: schema: type: object required: [page, totalPages, totalResults, results] properties: page: type: integer totalPages: type: integer totalResults: type: integer results: type: array items: $ref: '#/components/schemas/SportarrResult' '400': description: Invalid search query '503': description: Sportarr is not configured or is unavailable /sportarr/{externalId}: get: summary: Get Sportarr league details description: Returns the league and its state on the default Sportarr service. Advanced Request or Manage Requests users may select a configured service with serverId. tags: - service parameters: - in: path name: externalId required: true schema: type: string pattern: '^lg-[0-9]{1,20}$' - in: query name: serverId description: Optional Sportarr service destination. Requires Advanced Request or Manage Requests permission. schema: type: integer minimum: 0 maximum: 1000000 responses: '200': description: Sportarr league details and selected service library state content: application/json: schema: $ref: '#/components/schemas/SportarrResult' '403': description: Advanced Request or Manage Requests permission is required to choose a service '404': description: League or selected service not found '503': description: No Sportarr service is configured '502': description: Sportarr is unavailable /sportarr/{externalId}/events: get: summary: List Sportarr league events description: Returns monitored events and file availability for a league on the default Sportarr service. Unmonitored leagues return an empty page. tags: - service parameters: - in: path name: externalId required: true schema: type: string pattern: '^lg-[0-9]{1,20}$' - in: query name: page schema: type: integer minimum: 1 maximum: 1000 default: 1 - in: query name: pageSize schema: type: integer minimum: 1 maximum: 200 default: 50 responses: '200': description: Paged Sportarr event and file state content: application/json: schema: $ref: '#/components/schemas/SportarrEventPage' '404': description: League not found '503': description: No Sportarr service is configured '502': description: Sportarr events are unavailable /sportarr/cover/{serviceId}/{leagueId}: get: summary: Get a Sportarr league cover image description: Returns a sanitized image through SeerrNG's authenticated image proxy. tags: - service parameters: - in: path name: serviceId required: true schema: type: integer minimum: 0 - in: path name: leagueId required: true schema: oneOf: - type: integer minimum: 1 - type: string pattern: '^lg-[0-9]{1,20}$' responses: '200': description: Sanitized Sportarr cover image content: image/*: schema: type: string format: binary '404': description: Cover image not found /discover/magazines: get: summary: Discover magazines description: Returns magazines tracked by configured LazyLibrarian instances, or public Google Books results when catalog is public. tags: - search parameters: - in: query name: catalog description: Select the tracked LazyLibrarian catalog or the public Google Books catalog. schema: type: string enum: - tracked - public default: tracked - in: query name: page schema: type: number example: 1 default: 1 - in: query name: query schema: type: string maxLength: 256 example: National Geographic responses: '200': description: Magazine discovery results content: application/json: schema: type: object properties: page: type: number totalPages: type: number totalResults: type: number results: type: array items: $ref: '#/components/schemas/MagazineResult' /discover/keyword/{keywordId}/movies: get: summary: Get movies from keyword description: Returns list of movies based on the provided keyword ID a JSON object. tags: - search parameters: - in: path name: keywordId required: true schema: type: number example: 207317 - 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' /discover/genreslider/movie: get: summary: Get genre slider data for movies description: Returns a list of genres with backdrops attached tags: - search parameters: - in: query name: language schema: type: string example: en responses: '200': description: Genre slider data returned content: application/json: schema: type: array items: type: object properties: id: type: number example: 1 backdrops: type: array items: type: string name: type: string example: Genre Name /discover/genreslider/tv: get: summary: Get genre slider data for TV series description: Returns a list of genres with backdrops attached tags: - search parameters: - in: query name: language schema: type: string example: en responses: '200': description: Genre slider data returned content: application/json: schema: type: array items: type: object properties: id: type: number example: 1 backdrops: type: array items: type: string name: type: string example: Genre Name /discover/watchlist: get: summary: Get the Plex watchlist. tags: - search parameters: - in: query name: page schema: type: number example: 1 default: 1 responses: '200': description: Watchlist data returned content: application/json: schema: type: object properties: page: type: number totalPages: type: number totalResults: type: number results: type: array items: type: object properties: tmdbId: type: number example: 1 ratingKey: type: string type: type: string title: type: string /music/{musicId}: get: summary: Get music album details tags: - search parameters: - in: path name: musicId required: true schema: type: string example: f5093c06-23e3-404f-aeaa-40f72885ee3a responses: '200': description: Album details returned content: application/json: schema: $ref: '#/components/schemas/MusicResult' /music/{musicId}/artwork: get: summary: Resolve cached album artwork without loading album details tags: - search parameters: - in: path name: musicId required: true schema: type: string responses: '200': description: Resolved artwork, or null when no cover exists content: application/json: schema: type: object required: [posterPath] properties: posterPath: type: string nullable: true '400': description: Invalid album identifier '503': description: Artwork provider temporarily unavailable /music/{musicId}/rating: get: summary: Get album ratings from MusicBrainz, TheAudioDB and Discogs, with a Lidarr fallback tags: - search parameters: - in: path name: musicId required: true schema: type: string responses: '200': description: Separate provider ratings; failedSources identifies retryable provider failures content: application/json: schema: type: object properties: ratings: type: array items: $ref: '#/components/schemas/MusicSourceRating' failedSources: type: array items: type: string enum: [musicbrainz, lidarr, theaudiodb, discogs] rating: type: object required: [score, votes, url, source] properties: score: type: number minimum: 0 maximum: 10 votes: type: integer minimum: 0 url: type: string source: type: string enum: [musicbrainz, lidarr] '404': description: Album identifier not found /music/{musicId}/artist: get: summary: Get the primary artist for an album tags: - search parameters: - in: path name: musicId required: true schema: type: string responses: '200': description: Artist details returned /music/{musicId}/artist-discography: get: summary: Get the primary artist discography for an album tags: - search parameters: - in: path name: musicId required: true schema: type: string - in: query name: page schema: type: number default: 1 - in: query name: pageSize schema: type: number default: 20 responses: '200': description: Artist discography returned /music/{musicId}/artist-similar: get: summary: Get similar artists for the primary artist on an album tags: - search parameters: - in: path name: musicId required: true schema: type: string - in: query name: page schema: type: number default: 1 - in: query name: pageSize schema: type: number default: 20 responses: '200': description: Similar artists returned /artist/{artistId}: get: summary: Get artist details tags: - search parameters: - in: path name: artistId required: true schema: type: string example: b10bbbfc-cf9e-42e0-be17-e2c3e1d2600d - in: query name: page schema: type: number default: 1 - in: query name: pageSize schema: type: number default: 20 - in: query name: albumType schema: type: string responses: '200': description: Artist details returned content: application/json: schema: type: object properties: releaseGroups: type: array items: $ref: '#/components/schemas/MusicResult' pagination: type: object /book/search: get: summary: Search books tags: - search parameters: - in: query name: query required: true schema: type: string example: dune - in: query name: page schema: type: number default: 1 responses: '200': description: Book search results returned content: application/json: schema: type: object properties: page: type: number totalPages: type: number totalResults: type: number results: type: array items: $ref: '#/components/schemas/BookResult' /comic/{comicId}/issues: get: summary: List issues in a comic volume description: Returns a paged ComicVine issue list for browsing a volume. Comic requests continue to target the full volume. tags: - search parameters: - in: path name: comicId required: true schema: type: string - in: query name: page schema: type: integer minimum: 1 maximum: 500 responses: '200': description: Comic issue page returned content: application/json: schema: type: object properties: page: type: integer totalPages: type: integer totalResults: type: integer results: type: array items: type: object '503': description: ComicVine is unavailable /comic/{comicId}: get: summary: Get comic details description: Returns ComicVine volume details, merged with local availability if the volume is already tracked by a configured Mylar or Kapowarr instance. tags: - search parameters: - in: path name: comicId description: ComicVine volume ID. required: true schema: type: string example: '1234' responses: '200': description: Comic details returned content: application/json: schema: $ref: '#/components/schemas/ComicResult' '404': description: Comic not found '503': description: ComicVine is not configured on this server /magazine/cover/{serviceId}/{coverId}: get: summary: Get a magazine cover description: Returns a cached LazyLibrarian magazine cover through SeerrNG. tags: - search parameters: - in: path name: serviceId required: true schema: type: integer minimum: 1 - in: path name: coverId required: true schema: type: string pattern: '^(?:[a-fA-F0-9]{32}|[a-fA-F0-9]{40})$' responses: '200': description: Magazine cover image returned content: image/*: schema: type: string format: binary '404': description: Magazine cover not found /magazine/{title}: get: summary: Get magazine details description: Returns a magazine title and its known issues from LazyLibrarian. tags: - search parameters: - in: path name: title required: true schema: type: string maxLength: 256 responses: '200': description: Magazine details returned content: application/json: schema: $ref: '#/components/schemas/MagazineDetails' '404': description: Magazine not found '503': description: LazyLibrarian is unavailable /book/{bookId}: get: summary: Get book details tags: - search parameters: - in: path name: bookId required: true schema: type: string example: OL27448W - in: query name: lookupTitle description: Fallback title used to resolve provider-qualified Bookshelf records. schema: type: string maxLength: 512 responses: '200': description: Book details returned content: application/json: schema: $ref: '#/components/schemas/BookResult' '404': description: Book not found /book/{bookId}/ratings: get: summary: Get book ratings tags: - search parameters: - in: path name: bookId required: true schema: type: string example: OL27448W - in: query name: lookupTitle description: Fallback title used to resolve provider-qualified Bookshelf records. schema: type: string maxLength: 512 responses: '200': description: Book ratings returned content: application/json: schema: type: object required: - count - source properties: average: type: number minimum: 0 maximum: 5 count: type: integer minimum: 0 source: type: string enum: [openlibrary, bookshelf] workId: type: string '404': description: Book not found '503': description: Book ratings provider is unavailable /series/{seriesId}: get: summary: Get a Bookshelf book series description: Returns the Bookshelf books that belong to a series. tags: - search parameters: - in: path name: seriesId required: true schema: type: string maxLength: 4096 responses: '200': description: Books in the series content: application/json: schema: $ref: '#/components/schemas/BookSeriesDetails' '404': description: Series not found /book/{bookId}/cover: get: summary: Get linked Bookshelf cover image description: Streams a cover image from the linked Bookshelf/Readarr-compatible service for a saved book media row. tags: - search parameters: - in: path name: bookId required: true schema: type: string example: OL27448W - in: query name: mediaId required: true schema: type: integer minimum: 1 - in: query name: format schema: type: string enum: [ebook, audiobook] responses: '200': description: Book cover image content: image/jpeg: schema: type: string format: binary image/png: schema: type: string format: binary image/webp: schema: type: string format: binary '404': description: Book cover not found /author/{authorId}: get: summary: Get author details tags: - search parameters: - in: path name: authorId required: true schema: type: string example: OL23919A - in: query name: limit schema: type: number default: 20 - in: query name: offset schema: type: number default: 0 responses: '200': description: Author details returned content: application/json: schema: $ref: '#/components/schemas/AuthorResult' /author/{authorId}/works: get: summary: Get author works tags: - search parameters: - in: path name: authorId required: true schema: type: string example: OL23919A - in: query name: limit schema: type: number default: 20 - in: query name: offset schema: type: number default: 0 responses: '200': description: Author works returned content: application/json: schema: $ref: '#/components/schemas/AuthorWorksResponse' /service/lidarr: get: summary: Get Lidarr service summaries tags: - service responses: '200': description: Lidarr services returned content: application/json: schema: type: array items: $ref: '#/components/schemas/LidarrSettings' /service/reader-delivery: get: summary: Get the preferred reader catalog and Grimmory comic-reader URL tags: - service responses: '200': description: Configured reader delivery addresses returned content: application/json: schema: type: object required: - preferredProvider - provider - serviceName - serviceUrl - grimmoryUrl properties: preferredProvider: type: string enum: [grimmory, bookorbit] provider: type: string enum: [grimmory, bookorbit] serviceName: type: string enum: [Grimmory, BookOrbit] serviceUrl: type: string nullable: true format: uri grimmoryUrl: type: string nullable: true format: uri /service/lidarr/{lidarrId}: get: summary: Get Lidarr service details tags: - service parameters: - in: path name: lidarrId required: true schema: type: number responses: '200': description: Lidarr service details returned content: application/json: schema: $ref: '#/components/schemas/ServarrServiceDetails' /service/comic: get: summary: Get Mylar3/Kapowarr comic service summaries tags: - service responses: '200': description: Comic services returned content: application/json: schema: type: array items: $ref: '#/components/schemas/ComicServiceOption' /service/comic/{id}/rootfolders: get: summary: List Kapowarr comic root folders description: Returns a Kapowarr instance's configured folders for requesters with Advanced Request or Manage Requests permission. tags: - service parameters: - in: path name: id required: true schema: type: integer minimum: 0 responses: '200': description: Kapowarr folders and the configured default returned content: application/json: schema: $ref: '#/components/schemas/KapowarrRootFoldersResponse' '403': description: Advanced Request or Manage Requests permission is required '404': description: Kapowarr service not found /service/magazine: get: summary: Get LazyLibrarian magazine service summaries tags: - service responses: '200': description: Magazine services returned content: application/json: schema: type: array items: $ref: '#/components/schemas/MagazineServiceOption' /service/sportarr: get: summary: Get Sportarr service summaries description: Returns Sportarr destinations and their active quality-profile names. tags: - service responses: '200': description: Sportarr services returned content: application/json: schema: type: array items: $ref: '#/components/schemas/SportarrServiceOption' /service/readarr: get: summary: Get Bookshelf service summaries tags: - service responses: '200': description: Bookshelf services returned content: application/json: schema: type: array items: $ref: '#/components/schemas/ReadarrSettings' /service/readarr/{readarrId}: get: summary: Get Bookshelf service details tags: - service parameters: - in: path name: readarrId required: true schema: type: number responses: '200': description: Bookshelf service details returned content: application/json: schema: $ref: '#/components/schemas/ServarrServiceDetails' /settings/lidarr: get: summary: Get Lidarr settings tags: - settings responses: '200': description: Lidarr settings returned content: application/json: schema: type: array items: $ref: '#/components/schemas/LidarrSettings' post: summary: Create Lidarr settings tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/LidarrSettings' responses: '201': description: Lidarr settings created content: application/json: schema: $ref: '#/components/schemas/LidarrSettings' /settings/lidarr/test: post: summary: Test Lidarr settings tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ServarrConnectionSettings' responses: '200': description: Lidarr connection details returned content: application/json: schema: $ref: '#/components/schemas/ServarrServiceDetails' /settings/lidarr/{lidarrId}: put: summary: Update Lidarr settings tags: - settings parameters: - in: path name: lidarrId required: true schema: type: number responses: '200': description: Lidarr settings updated content: application/json: schema: $ref: '#/components/schemas/LidarrSettings' delete: summary: Delete Lidarr settings tags: - settings parameters: - in: path name: lidarrId required: true schema: type: number responses: '200': description: Lidarr settings deleted content: application/json: schema: $ref: '#/components/schemas/LidarrSettings' /settings/readarr: get: summary: Get Bookshelf settings tags: - settings responses: '200': description: Bookshelf settings returned content: application/json: schema: type: array items: $ref: '#/components/schemas/ReadarrSettings' post: summary: Create Bookshelf settings tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ReadarrSettings' responses: '201': description: Bookshelf settings created content: application/json: schema: $ref: '#/components/schemas/ReadarrSettings' /settings/readarr/test: post: summary: Test Bookshelf settings tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ServarrConnectionSettings' responses: '200': description: Bookshelf connection details returned content: application/json: schema: $ref: '#/components/schemas/ServarrServiceDetails' /settings/readarr/diagnose: post: summary: Diagnose Bookshelf lookup and add readiness tags: - settings requestBody: required: true content: application/json: schema: allOf: - $ref: '#/components/schemas/ServarrConnectionSettings' - type: object properties: activeDirectory: type: string activeProfileId: type: number activeMetadataProfileId: type: number term: type: string example: isbn:9780547928227 testAdd: type: boolean default: false responses: '200': description: Bookshelf diagnostic result content: application/json: schema: type: object required: [ok, category, message] properties: ok: type: boolean category: type: string enum: - ok - backend_unreachable - lookup_empty - lookup_incomplete - backend_add_rejected message: type: string term: type: string provider: type: string enum: - hardcover - softcover - unknown legacyWarning: type: string metadataSource: type: string lookupCount: type: number /settings/readarr/{readarrId}/media-move/configuration: get: summary: List Bookshelf library details for a path move description: Admin-only. Reads authors and accessible root folders from one Bookshelf instance. It does not merge separate Bookshelf databases. tags: - settings parameters: - in: path name: readarrId required: true schema: type: integer - in: query name: format required: true schema: type: string enum: [ebook, audiobook] responses: '200': description: Bookshelf library and accessible destination folders content: application/json: schema: $ref: '#/components/schemas/BookshelfMediaMoveConfiguration' '400': description: Unsupported format '403': description: Administrator permission required '409': description: BookshelfNG does not support this operation '502': description: Bookshelf library details could not be loaded /settings/readarr/{readarrId}/media-move/preview: post: summary: Preview a bulk Bookshelf media path move description: Admin-only. Returns file paths, conflicts, missing files, and space estimates for selected authors in one Bookshelf instance. The preview token expires when the underlying move inputs change. tags: - settings parameters: - in: path name: readarrId required: true schema: type: integer requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/BookshelfMediaMovePreviewRequest' responses: '200': description: Fresh batch preview and preview token content: application/json: schema: $ref: '#/components/schemas/BookshelfMediaMoveBatchPreview' '400': description: Invalid selection, source folder, or destination '403': description: Administrator permission required '409': description: BookshelfNG does not support this operation '502': description: BookshelfNG could not produce a preview /settings/readarr/{readarrId}/media-move/start: post: summary: Start a previewed bulk Bookshelf media path move description: Admin-only. Requires the preview token and queues the move in the selected Bookshelf instance. Preview again if the library changes. tags: - settings parameters: - in: path name: readarrId required: true schema: type: integer requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/BookshelfMediaMoveStartRequest' responses: '202': description: BookshelfNG accepted the move command content: application/json: schema: type: object required: [command] properties: command: $ref: '#/components/schemas/BookshelfMediaMoveCommand' '400': description: Invalid move request or missing preview token '403': description: Administrator permission required '409': description: Preview is stale, destination changed, or BookshelfNG lacks move support '502': description: BookshelfNG could not start the move /settings/readarr/{readarrId}/media-move/commands/{commandId}: get: summary: Read a Bookshelf media move command description: Admin-only. Returns the queued move command status from the selected Bookshelf instance. tags: - settings parameters: - in: path name: readarrId required: true schema: type: integer - in: path name: commandId required: true schema: type: integer responses: '200': description: Current Bookshelf command status content: application/json: schema: type: object required: [command] properties: command: $ref: '#/components/schemas/BookshelfMediaMoveCommand' '403': description: Administrator permission required '404': description: Bookshelf or command not found '502': description: Bookshelf command status could not be loaded /settings/readarr/{readarrId}: put: summary: Update Bookshelf settings tags: - settings parameters: - in: path name: readarrId required: true schema: type: number responses: '200': description: Bookshelf settings updated content: application/json: schema: $ref: '#/components/schemas/ReadarrSettings' delete: summary: Delete Bookshelf settings tags: - settings parameters: - in: path name: readarrId required: true schema: type: number responses: '200': description: Bookshelf settings deleted content: application/json: schema: $ref: '#/components/schemas/ReadarrSettings' /settings/audiobookshelf: get: summary: Get Audiobookshelf availability settings description: Returns the configured read-only book library connection, with its API token redacted, or null when not configured. tags: - settings responses: '200': description: Audiobookshelf availability settings returned content: application/json: schema: allOf: - $ref: '#/components/schemas/AudiobookshelfSettings' nullable: true put: summary: Save Audiobookshelf availability settings description: Configures a read-only Audiobookshelf book library. SeerrNG matches books by ISBN and never modifies Audiobookshelf items. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/AudiobookshelfSettings' responses: '200': description: Audiobookshelf availability settings saved with the API token redacted content: application/json: schema: $ref: '#/components/schemas/AudiobookshelfSettings' '400': description: Invalid Audiobookshelf settings delete: summary: Remove Audiobookshelf availability settings description: Removes the configured library and clears linked Audiobookshelf availability from books. tags: - settings responses: '204': description: Audiobookshelf availability settings removed /settings/audiobookshelf/test: post: summary: Test Audiobookshelf connection description: Lists available Audiobookshelf book libraries without changing them. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ServarrConnectionSettings' responses: '200': description: Available book libraries content: application/json: schema: type: object required: [libraries] properties: libraries: type: array items: $ref: '#/components/schemas/AudiobookshelfLibrary' '400': description: Invalid connection settings '502': description: Audiobookshelf connection failed /settings/mylar: get: summary: Get Mylar settings description: Returns all Mylar settings in a JSON array. tags: - settings responses: '200': description: 'Values were returned' content: application/json: schema: type: array items: $ref: '#/components/schemas/MylarSettings' post: summary: Create Mylar instance description: Creates a new Mylar instance from the request body. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/MylarSettings' responses: '201': description: 'New Mylar instance created' content: application/json: schema: $ref: '#/components/schemas/MylarSettings' /settings/mylar/test: post: summary: Test Mylar configuration description: Tests if the Mylar configuration is valid. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ServarrConnectionSettings' responses: '200': description: Succesfully connected to Mylar instance content: application/json: schema: type: object properties: version: type: string /settings/mylar/{mylarId}: put: summary: Update Mylar instance tags: - settings parameters: - in: path name: mylarId required: true schema: type: number requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/MylarSettings' responses: '200': description: Mylar instance updated content: application/json: schema: $ref: '#/components/schemas/MylarSettings' delete: summary: Delete Mylar instance tags: - settings parameters: - in: path name: mylarId required: true schema: type: number responses: '200': description: Mylar instance deleted content: application/json: schema: $ref: '#/components/schemas/MylarSettings' /settings/kapowarr: get: summary: Get Kapowarr settings description: Returns all Kapowarr settings in a JSON array. tags: - settings responses: '200': description: 'Values were returned' content: application/json: schema: type: array items: $ref: '#/components/schemas/KapowarrSettings' post: summary: Create Kapowarr instance description: Creates a new Kapowarr instance from the request body. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/KapowarrSettings' responses: '201': description: 'New Kapowarr instance created' content: application/json: schema: $ref: '#/components/schemas/KapowarrSettings' /settings/kapowarr/test: post: summary: Test Kapowarr configuration description: Tests if the Kapowarr configuration is valid. Returns root folders on success. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ServarrConnectionSettings' responses: '200': description: Succesfully connected to Kapowarr instance content: application/json: schema: type: object properties: version: type: string rootFolders: type: array items: type: object properties: id: type: number path: type: string /settings/kapowarr/{kapowarrId}: put: summary: Update Kapowarr instance tags: - settings parameters: - in: path name: kapowarrId required: true schema: type: number requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/KapowarrSettings' responses: '200': description: Kapowarr instance updated content: application/json: schema: $ref: '#/components/schemas/KapowarrSettings' delete: summary: Delete Kapowarr instance tags: - settings parameters: - in: path name: kapowarrId required: true schema: type: number responses: '200': description: Kapowarr instance deleted content: application/json: schema: $ref: '#/components/schemas/KapowarrSettings' /settings/backissue: get: summary: Get BackIssue settings description: Returns all BackIssue settings in a JSON array. tags: - settings responses: '200': description: Values were returned content: application/json: schema: type: array items: $ref: '#/components/schemas/BackIssueSettings' post: summary: Create BackIssue instance description: Creates a new BackIssue instance from the request body. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/BackIssueSettings' responses: '201': description: New BackIssue instance created content: application/json: schema: $ref: '#/components/schemas/BackIssueSettings' /settings/backissue/test: post: summary: Test BackIssue configuration description: Tests if the BackIssue configuration is valid. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ServarrConnectionSettings' responses: '200': description: Successfully connected to BackIssue content: application/json: schema: type: object properties: version: type: string /settings/backissue/{id}: put: summary: Update BackIssue instance tags: - settings parameters: - in: path name: id required: true schema: type: number requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/BackIssueSettings' responses: '200': description: BackIssue instance updated content: application/json: schema: $ref: '#/components/schemas/BackIssueSettings' delete: summary: Delete BackIssue instance tags: - settings parameters: - in: path name: id required: true schema: type: number responses: '200': description: BackIssue instance deleted content: application/json: schema: $ref: '#/components/schemas/BackIssueSettings' /settings/lazylibrarian: get: summary: Get LazyLibrarian settings description: Returns all LazyLibrarian settings in a JSON array. tags: - settings responses: '200': description: Values were returned content: application/json: schema: type: array items: $ref: '#/components/schemas/LazyLibrarianSettings' post: summary: Create LazyLibrarian instance description: Creates a LazyLibrarian instance from the request body. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/LazyLibrarianSettings' responses: '201': description: New LazyLibrarian instance created content: application/json: schema: $ref: '#/components/schemas/LazyLibrarianSettings' /settings/lazylibrarian/test: post: summary: Test LazyLibrarian configuration description: Tests the LazyLibrarian API connection. tags: - settings requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ServarrConnectionSettings' responses: '200': description: Successfully connected to LazyLibrarian content: application/json: schema: type: object properties: version: type: string /settings/lazylibrarian/{lazylibrarianId}: put: summary: Update LazyLibrarian instance tags: - settings parameters: - in: path name: lazylibrarianId required: true schema: type: number requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/LazyLibrarianSettings' responses: '200': description: LazyLibrarian instance updated content: application/json: schema: $ref: '#/components/schemas/LazyLibrarianSettings' delete: summary: Delete LazyLibrarian instance tags: - settings parameters: - in: path name: lazylibrarianId required: true schema: type: number responses: '200': description: LazyLibrarian instance deleted content: application/json: schema: $ref: '#/components/schemas/LazyLibrarianSettings' /request/lists: get: summary: Get the signed-in user's external request lists tags: - request responses: '200': description: External request lists returned content: application/json: schema: type: array items: $ref: '#/components/schemas/ExternalRequestList' post: summary: Add a public IMDb or Goodreads list for recurring requests tags: - request requestBody: required: true content: application/json: schema: type: object required: [url] additionalProperties: false properties: url: type: string maxLength: 2048 example: https://www.imdb.com/user/ur12345678/watchlist/ responses: '201': description: External request list saved content: application/json: schema: $ref: '#/components/schemas/ExternalRequestList' /request/lists/hardcover: post: summary: Connect a Hardcover Want to Read shelf description: Validates and stores the signed-in user's Hardcover token. The token is not returned by list routes. tags: [request] requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: [apiToken] properties: apiToken: type: string minLength: 16 maxLength: 4096 responses: '201': description: Hardcover shelf connected '200': description: Existing Hardcover shelf updated '400': description: Hardcover rejected the token or query /request/lists/{listId}/import: post: summary: Import IMDb watchlist export title IDs description: Imports up to 100 unique IMDb title IDs from the signed-in user's CSV export. Imported IMDb lists are updated manually and are excluded from scheduled server-side fetching. tags: [request] parameters: - in: path name: listId required: true schema: type: integer minimum: 1 requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: [itemIds] properties: itemIds: type: array minItems: 1 maxItems: 100 uniqueItems: true items: type: string pattern: '^tt[0-9]{5,20}$' responses: '200': description: Imported IMDb titles were sent through normal request permissions content: application/json: schema: $ref: '#/components/schemas/ExternalRequestListSyncResult' '400': description: The list is not an IMDb watchlist or the title IDs are invalid /request/lists/{listId}/sync: post: summary: Sync a configured public list now tags: - request parameters: - in: path name: listId required: true schema: type: integer minimum: 1 responses: '200': description: List synchronization results content: application/json: schema: $ref: '#/components/schemas/ExternalRequestListSyncResult' /request/lists/{listId}: delete: summary: Remove a configured external request list tags: - request parameters: - in: path name: listId required: true schema: type: integer minimum: 1 responses: '204': description: External request list removed /readmeabook/status: get: summary: Get ReadMeABook availability tags: [books] responses: '200': description: Whether ReadMeABook is enabled /readmeabook/search: get: summary: Search audiobooks through ReadMeABook tags: [books] parameters: - in: query name: query required: true schema: type: string minLength: 1 maxLength: 160 responses: '200': description: Audiobook search results '400': description: Invalid search query '502': description: ReadMeABook could not be reached /readmeabook/discover: get: summary: Get a ReadMeABook home section tags: [books] parameters: - in: query name: section required: true schema: type: string enum: [popular, new, subject] - in: query name: subject schema: type: string maxLength: 64 responses: '200': description: Audiobook section results '400': description: Invalid section '502': description: ReadMeABook could not be reached /readmeabook/requests: get: summary: Get the signed-in user's ReadMeABook requests tags: [books] responses: '200': description: Audiobook requests content: application/json: schema: type: array items: $ref: '#/components/schemas/ReadMeABookRequest' post: summary: Request an audiobook through ReadMeABook tags: [books] requestBody: required: true content: application/json: schema: type: object required: [asin, title, author] properties: asin: type: string pattern: '^[A-Za-z0-9]{10}$' title: type: string maxLength: 512 author: type: string maxLength: 512 narrator: type: string maxLength: 512 description: type: string maxLength: 8000 coverArtUrl: type: string format: uri durationMinutes: type: integer minimum: 1 maximum: 100000 responses: '201': description: Audiobook request created content: application/json: schema: $ref: '#/components/schemas/ReadMeABookRequest' '400': description: Invalid audiobook '403': description: The user cannot request books '409': description: The audiobook is already requested '429': description: Book quota reached /readmeabook/requests/{id}: get: summary: Refresh the status of a ReadMeABook request tags: [books] parameters: - in: path name: id required: true schema: type: integer minimum: 1 responses: '200': description: Updated audiobook request status '404': description: Request not found '409': description: Request is waiting for approval '502': description: ReadMeABook could not be reached /readmeabook/admin/dashboard: get: summary: Get the ReadMeABook acquisition dashboard tags: [admin] responses: '200': description: Metrics, active downloads, and recent requests '403': description: Admin permission required /readmeabook/admin/requests: get: summary: Get audiobook requests awaiting SeerrNG approval tags: [admin] responses: '200': description: Requests awaiting approval /readmeabook/admin/requests/{id}/approve: post: summary: Approve and submit a ReadMeABook request tags: [admin] parameters: - in: path name: id required: true schema: type: integer minimum: 1 responses: '200': description: Request approved '404': description: Request not found '409': description: Request is no longer awaiting approval '502': description: ReadMeABook could not process the request /readmeabook/admin/requests/{id}/deny: post: summary: Deny a ReadMeABook request tags: [admin] parameters: - in: path name: id required: true schema: type: integer minimum: 1 responses: '200': description: Request denied '404': description: Request not found '409': description: Request is no longer awaiting approval /request: get: summary: Get all requests description: | Returns all requests if the user has the `ADMIN` or `MANAGE_REQUESTS` permissions. Otherwise, only the logged-in user's requests are returned. If the `requestedBy` parameter is specified, only requests from that particular user ID will be returned. tags: - request 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, recent, approved, available, pending, processing, unavailable, failed, deleted, completed, ] - in: query name: sort schema: type: string enum: [added, modified] default: added - in: query name: sortDirection schema: type: string enum: [asc, desc] nullable: true default: desc - in: query name: requestedBy schema: type: number nullable: true example: 1 - in: query name: mediaType schema: type: string enum: [movie, tv, music, book, comic, magazine, sports, all] nullable: true default: all - in: query name: category description: Restrict results to one software request category. schema: type: string enum: [retro, modern, game] responses: '200': description: Requests returned content: application/json: schema: type: object properties: pageInfo: $ref: '#/components/schemas/PageInfo' results: type: array items: $ref: '#/components/schemas/MediaRequest' post: summary: Create new request description: | Creates a new request with the provided media ID and type. The `REQUEST` permission is required. If the user has the `ADMIN` or `AUTO_APPROVE` permissions, their request will be auomatically approved. tags: - request requestBody: required: true content: application/json: schema: type: object properties: mediaType: type: string enum: [movie, tv, music, book, comic, magazine, sports] example: movie mediaId: oneOf: - type: number example: 123 - type: string example: OL27448W tvdbId: type: number example: 123 seasons: oneOf: - type: array items: type: number minimum: 0 - type: string enum: [all] seasonRequests: type: array description: Exact season and episode selections. Omit episodeNumbers to request an entire season. items: $ref: '#/components/schemas/SeasonEpisodeSelection' watchAheadEpisodeCount: type: integer minimum: 0 maximum: 5 description: Optional Episode Queue buffer for the requesting user's Plex, Jellyfin, or Emby playback. On create, seasonRequests must specify exactly one starting episode; edits preserve existing selections. is4k: type: boolean example: false serverId: type: number profileId: type: number rootFolder: type: string description: For an advanced Kapowarr comic request, choose a path returned by /service/comic/{id}/rootfolders. If omitted, the service's configured default is used. languageProfileId: type: number metadataProfileId: type: number tags: type: array items: type: number format: type: string enum: [ebook, audiobook, both] description: Book request format. editionId: type: string example: OL8934157M isbn13: type: string example: '9780441478125' authorId: type: string example: OL23919A userId: type: number nullable: true description: >- Optional requester ID. Omit this field to use the authenticated user. When supplied, the request is attributed to that account. Supplying it requires both `MANAGE_USERS` and `MANAGE_REQUESTS`; otherwise the API returns HTTP 403. ignoreQuota: type: boolean example: false description: If true, this request will not count against the user's quota. Requires MANAGE_REQUESTS permission. required: - mediaType - mediaId responses: '201': description: Succesfully created the request content: application/json: schema: $ref: '#/components/schemas/MediaRequest' /request/bulk: post: summary: Create bulk media requests description: | Creates individual music or book requests for the selected items. Duplicate, covered, or blocklisted items are returned in the summary instead of failing the whole batch. Quota overage rejects before any requests are created. tags: - request requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/BulkMediaRequestBody' responses: '207': description: Bulk request summary returned content: application/json: schema: $ref: '#/components/schemas/BulkMediaRequestResponse' /request/person-movies: post: summary: Create movie requests from a person's movie credits description: | Requires the administrator's person-page bulk movie request setting and the normal movie request permissions. Each unique ID is processed through standard request admission and quota checks. Already-requested and blocklisted movies are listed as skipped; individual failures are listed in the response. Processing stops when a quota or service-configuration error prevents further requests. Submit between 1 and 100 movie IDs per call. The person page sends larger credit lists as separate calls. tags: - request requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/PersonMovieBulkRequestBody' responses: '200': description: Movie request summary returned content: application/json: schema: $ref: '#/components/schemas/PersonMovieBulkRequestResponse' '400': description: Invalid or out-of-range movie ID list '401': description: Authentication required '403': description: Bulk requests are disabled, movie requests are disabled, or the user lacks request permission /request/count: get: summary: Gets request counts description: | Returns the number of requests by status including pending, approved, declined, failed, available, and completed requests. tags: - request responses: '200': description: Request counts returned content: application/json: schema: type: object properties: total: type: number movie: type: number tv: type: number music: type: number book: type: number pending: type: number approved: type: number declined: type: number failed: type: number processing: type: number available: type: number completed: type: number /request/software: post: summary: Submit a ROM or PC game request description: Creates a SeerrNG software request from the configured IGDB catalog. Emulation uses the selected QuestarrNG or ROMarrNG catalog and is acquired by ROMarrNG; PC game requests use QuestarrNG and require operating system and architecture. tags: - request requestBody: required: true content: application/json: schema: type: object required: [category, catalogId] properties: category: type: string enum: [retro, modern, game] catalogId: type: integer minimum: 1 platformSlug: type: string variant: type: object required: [operatingSystem, architecture] properties: operatingSystem: type: string enum: [windows, linux, macos] architecture: type: string enum: [x64, arm64, x86, universal] responses: '201': description: Software request submitted content: application/json: schema: $ref: '#/components/schemas/SoftwareRequestMutationResponse' '400': description: Invalid title, category, system, or PC target '403': description: Caller lacks request permission or has reached the software request quota '409': description: Matching request already exists /request/software/catalog/systems: get: summary: List ROMarrNG-supported emulation systems description: Returns ROMarrNG-supported platform slugs and the Retro or Modern group assigned by an administrator. Unassigned systems are not requestable, regardless of which service supplies the emulation IGDB catalog. tags: - request responses: '200': description: Supported emulation systems returned content: application/json: schema: type: object properties: results: type: array items: type: object /request/software/catalog/search: get: summary: Search ROM and PC game catalog description: Searches the selected QuestarrNG or ROMarrNG IGDB catalog for emulation categories, or QuestarrNG for PC games. Results are filtered to the requested emulation group or PC platform and include availability (available, tracked, downloading, missing, or unknown) and ROM availableSystems when known. Pass the returned nextCursor to load the next page. tags: - request parameters: - in: query name: q required: true schema: type: string minLength: 1 maxLength: 200 - in: query name: category required: true schema: type: string enum: [retro, modern, game] - in: query name: system description: ROMarrNG system slug for Retro or Modern results. schema: type: string maxLength: 64 - in: query name: platform description: PC operating-system platform for game results. schema: type: string enum: [windows, linux, macos] - in: query name: genre description: IGDB genre name, matched before pagination. schema: type: string minLength: 1 maxLength: 64 - in: query name: releaseYear description: UTC release year, matched before pagination. schema: type: integer minimum: 1950 maximum: 2200 - in: query name: limit schema: type: integer minimum: 1 maximum: 50 default: 24 - in: query name: cursor schema: type: string maxLength: 20000 responses: '200': description: Matching catalog titles returned content: application/json: schema: type: object properties: results: type: array items: type: object nextCursor: type: string nullable: true '503': description: Selected emulation catalog is unavailable, unconfigured, or needs the SeerrNG integration contract. /request/software/catalog/popular: get: summary: List popular ROM and PC game catalog titles description: Returns popular titles from the selected QuestarrNG or ROMarrNG IGDB catalog for emulation, or QuestarrNG for PC games. Results are filtered to the selected emulation group or PC platform and include provider and SeerrNG request availability. Pass the returned nextOffset to load the next page. tags: - request parameters: - in: query name: category required: true schema: type: string enum: [retro, modern, game] - in: query name: system description: ROMarrNG system slug for Retro or Modern results. schema: type: string maxLength: 64 - in: query name: platform description: PC operating-system platform for game results. schema: type: string enum: [windows, linux, macos] - in: query name: genre description: IGDB genre name, matched before pagination. schema: type: string minLength: 1 maxLength: 64 - in: query name: releaseYear description: UTC release year, matched before pagination. schema: type: integer minimum: 1950 maximum: 2200 - in: query name: limit schema: type: integer minimum: 1 maximum: 50 default: 24 - in: query name: offset schema: type: integer minimum: 0 maximum: 10000 responses: '200': description: Popular catalog titles returned content: application/json: schema: type: object properties: results: type: array items: type: object nextOffset: type: integer nullable: true '503': description: Selected emulation catalog is unavailable, unconfigured, or needs the SeerrNG integration contract. /request/software/catalog/games/{id}: get: summary: Get one ROM or PC game catalog title description: Returns metadata from the selected QuestarrNG or ROMarrNG IGDB catalog for emulation, or QuestarrNG for PC games, with supported request targets, screenshots, video IDs, rating normalized to a 0-10 scale, and provider or SeerrNG request availability. tags: - request parameters: - in: path name: id required: true schema: type: integer minimum: 1 - in: query name: category required: true schema: type: string enum: [retro, modern, game] responses: '200': description: Software catalog title returned content: application/json: schema: type: object properties: game: type: object '404': description: Title not found in the selected category '503': description: Selected emulation catalog is unavailable or unconfigured /game-library: get: summary: List the signed-in user's personal game library description: Returns only the caller's entries, progress, ownership facts, private sharing setting, and the caller's own latest software request state. tags: [game library] parameters: - in: query name: q schema: type: string maxLength: 120 - in: query name: status schema: type: string enum: [backlog, playing, played, completed, paused, dropped] - in: query name: category schema: type: string enum: [game, retro, modern] - in: query name: limit schema: type: integer minimum: 1 maximum: 100 default: 48 - in: query name: offset schema: type: integer minimum: 0 maximum: 9999999 default: 0 responses: '200': description: Personal game library page content: application/json: schema: $ref: '#/components/schemas/GameLibraryPage' '400': description: Invalid filter or pagination input content: application/json: schema: $ref: '#/components/schemas/GameLibraryErrorResponse' '401': description: Sign-in required content: application/json: schema: $ref: '#/components/schemas/GameLibraryErrorResponse' '403': description: Sign-in required content: application/json: schema: $ref: '#/components/schemas/GameLibraryErrorResponse' post: summary: Add a catalog title to the caller's personal game library description: Adds a private backlog entry by default. Existing progress, ownership, and sharing choices are preserved when a title is already tracked. Requires a signed-in browser session. tags: [game library] security: - cookieAuth: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/GameLibraryMutation' responses: '200': description: Existing library entry returned after refreshing catalog metadata content: application/json: schema: $ref: '#/components/schemas/GameLibraryMutationResponse' '400': description: Invalid game or library state content: application/json: schema: $ref: '#/components/schemas/GameLibraryErrorResponse' '403': description: A browser session is required content: application/json: schema: $ref: '#/components/schemas/GameLibraryErrorResponse' '502': description: The configured catalog could not confirm the title content: application/json: schema: $ref: '#/components/schemas/GameLibraryErrorResponse' /game-library/manual: post: summary: Add a game that is missing from the catalog description: Creates a private personal entry without requiring a catalog or acquisition provider. Requires a signed-in browser session. tags: [game library] security: - cookieAuth: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/GameLibraryManualMutation' responses: '201': description: Manual game added content: application/json: schema: $ref: '#/components/schemas/GameLibraryMutationResponse' '200': description: Matching manual entry already exists content: application/json: schema: $ref: '#/components/schemas/GameLibraryMutationResponse' '400': description: Invalid game title or library state content: application/json: schema: $ref: '#/components/schemas/GameLibraryErrorResponse' '403': description: A browser session is required content: application/json: schema: $ref: '#/components/schemas/GameLibraryErrorResponse' /game-library/shared: get: summary: Browse games explicitly shared by household members description: Returns only entries whose owners opted in and marked them owned. Owner names, progress, store, and playtime are visible only for a shared owned title. tags: [game library] parameters: - in: query name: q schema: type: string maxLength: 120 - in: query name: minOwners description: Use 2 to show titles shared by at least two owners. schema: type: integer minimum: 1 maximum: 20 default: 1 - in: query name: limit schema: type: integer minimum: 1 maximum: 100 default: 48 - in: query name: offset schema: type: integer minimum: 0 maximum: 9999999 default: 0 responses: '200': description: Shared game library page content: application/json: schema: $ref: '#/components/schemas/SharedGameLibraryPage' '400': description: Invalid filter or pagination input content: application/json: schema: $ref: '#/components/schemas/GameLibraryErrorResponse' '401': description: Sign-in required content: application/json: schema: $ref: '#/components/schemas/GameLibraryErrorResponse' '403': description: Sign-in required content: application/json: schema: $ref: '#/components/schemas/GameLibraryErrorResponse' /game-library/lookup: get: summary: Check whether the caller tracks a catalog game description: The response contains only the caller's own entry and does not reveal household data. tags: [game library] parameters: - in: query name: category required: true schema: type: string enum: [game, retro, modern] - in: query name: catalogId required: true schema: type: integer minimum: 1 maximum: 2147483647 responses: '200': description: Caller-specific tracked entry, if present content: application/json: schema: type: object required: [entry] properties: entry: type: object nullable: true properties: id: type: integer minimum: 1 '400': description: Invalid catalog lookup content: application/json: schema: $ref: '#/components/schemas/GameLibraryErrorResponse' '403': description: Sign-in required content: application/json: schema: $ref: '#/components/schemas/GameLibraryErrorResponse' /game-library/{id}: patch: summary: Update the caller's game progress and sharing choices description: Only the owner can update an entry. Sharing requires the caller to mark the game owned. tags: [game library] security: - cookieAuth: [] parameters: - in: path name: id required: true schema: type: integer minimum: 1 requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/GameLibraryPatch' responses: '200': description: Updated personal entry content: application/json: schema: $ref: '#/components/schemas/GameLibraryMutationResponse' '400': description: Invalid state or sharing an unowned title content: application/json: schema: $ref: '#/components/schemas/GameLibraryErrorResponse' '403': description: A browser session is required content: application/json: schema: $ref: '#/components/schemas/GameLibraryErrorResponse' '404': description: Entry not owned by the caller content: application/json: schema: $ref: '#/components/schemas/GameLibraryErrorResponse' delete: summary: Remove one of the caller's game library entries tags: [game library] security: - cookieAuth: [] parameters: - in: path name: id required: true schema: type: integer minimum: 1 responses: '204': description: Entry removed '403': description: A browser session is required content: application/json: schema: $ref: '#/components/schemas/GameLibraryErrorResponse' '404': description: Entry not owned by the caller content: application/json: schema: $ref: '#/components/schemas/GameLibraryErrorResponse' /game-library/{id}/match: post: summary: Match an imported game to a software catalog title description: Explicitly links one of the caller's unmatched Steam or manual titles to QuestarrNG's PC game catalog, without automatic title guessing. tags: [game library] security: - cookieAuth: [] parameters: - in: path name: id required: true schema: type: integer minimum: 1 requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/GameLibraryMutation' responses: '200': description: Catalog match applied content: application/json: schema: $ref: '#/components/schemas/GameLibraryMutationResponse' '400': description: Invalid catalog match content: application/json: schema: $ref: '#/components/schemas/GameLibraryErrorResponse' '403': description: A browser session is required content: application/json: schema: $ref: '#/components/schemas/GameLibraryErrorResponse' '404': description: Entry not owned by the caller content: application/json: schema: $ref: '#/components/schemas/GameLibraryErrorResponse' '409': description: Entry is already matched content: application/json: schema: $ref: '#/components/schemas/GameLibraryErrorResponse' '502': description: Catalog provider unavailable content: application/json: schema: $ref: '#/components/schemas/GameLibraryErrorResponse' /game-library/steam/status: get: summary: Get the caller's Steam link and sync status tags: [game library] responses: '200': description: Private caller-specific Steam status; never returns the administrator API key content: application/json: schema: type: object required: [connected, lastSyncedAt, lastSyncCount, apiKeyConfigured] properties: connected: type: boolean lastSyncedAt: type: string format: date-time nullable: true lastSyncCount: type: integer apiKeyConfigured: type: boolean '403': description: Sign-in required content: application/json: schema: $ref: '#/components/schemas/GameLibraryErrorResponse' /game-library/steam/connect: get: summary: Start the Steam OpenID account linking flow description: Starts a one-use, session-bound Steam identity verification. Requires a configured SeerrNG application URL and a signed-in browser session. tags: [game library] security: - cookieAuth: [] responses: '302': description: Redirect to Steam to authenticate the account '400': description: Application URL is not configured content: application/json: schema: $ref: '#/components/schemas/GameLibraryErrorResponse' '403': description: A browser session is required content: application/json: schema: $ref: '#/components/schemas/GameLibraryErrorResponse' /game-library/steam/callback: get: summary: Complete the Steam OpenID account linking flow description: Validates the session state, exact callback URL, Steam issuer, signed identity assertion, and Steam's check_authentication response before linking an account. tags: [game library] security: - cookieAuth: [] parameters: - in: query name: state required: true schema: type: string pattern: ^[a-f0-9]{64}$ - in: query name: openid.ns schema: type: string - in: query name: openid.mode schema: type: string - in: query name: openid.op_endpoint schema: type: string - in: query name: openid.claimed_id schema: type: string - in: query name: openid.identity schema: type: string - in: query name: openid.return_to schema: type: string - in: query name: openid.response_nonce schema: type: string - in: query name: openid.assoc_handle schema: type: string - in: query name: openid.signed schema: type: string - in: query name: openid.sig schema: type: string - in: query name: openid.invalidate_handle schema: type: string responses: '302': description: Redirect back to My Games with a connection result '403': description: Sign-in required content: application/json: schema: $ref: '#/components/schemas/GameLibraryErrorResponse' /game-library/steam/sync: post: summary: Synchronize the caller's public Steam game library description: Imports owned Steam titles and playtime. Unmatched Steam games remain private; sync never changes manual progress, and missing titles are no longer treated as Steam-owned. Requires a signed-in browser session and an administrator-configured API key. tags: [game library] security: - cookieAuth: [] responses: '200': description: Sync counts content: application/json: schema: type: object required: [imported, updated, total] properties: imported: type: integer updated: type: integer total: type: integer '403': description: A browser session is required content: application/json: schema: $ref: '#/components/schemas/GameLibraryErrorResponse' '409': description: Steam account is not linked or game details are private content: application/json: schema: $ref: '#/components/schemas/GameLibraryErrorResponse' '413': description: Steam returned more titles than the sync limit content: application/json: schema: $ref: '#/components/schemas/GameLibraryErrorResponse' '503': description: Steam API key is not configured content: application/json: schema: $ref: '#/components/schemas/GameLibraryErrorResponse' '502': description: Steam is unavailable content: application/json: schema: $ref: '#/components/schemas/GameLibraryErrorResponse' '429': description: Steam sync rate limit reached content: application/json: schema: $ref: '#/components/schemas/GameLibraryErrorResponse' /game-library/steam: delete: summary: Unlink Steam from the caller's game library description: Removes the account link, preserves imported titles and playtime, and clears verified Steam ownership and household sharing for entries not manually marked owned. tags: [game library] security: - cookieAuth: [] responses: '204': description: Steam account unlinked '403': description: A browser session is required content: application/json: schema: $ref: '#/components/schemas/GameLibraryErrorResponse' /request/software/status: get: summary: List software request status description: Returns request ownership, lifecycle state, verified available assets, and pageInfo. Users with request-view permission may inspect other users' software requests. tags: - request parameters: - in: query name: take schema: type: integer minimum: 1 maximum: 100 default: 20 - in: query name: skip schema: type: integer minimum: 0 default: 0 - in: query name: requestedBy schema: type: integer minimum: 1 - in: query name: requestId description: Restrict the result to a single software request, as used by availability notification links. schema: type: integer minimum: 1 - in: query name: filter description: Filter software requests using the Requests page status groups. Groups without a software equivalent, such as incomplete and unavailable, return no software requests. schema: type: string enum: [ all, pending, approved, processing, active, incomplete, attention, completed, unavailable, requested, searching, downloading, importing, library, available, failed, declined, cancelled, ] default: all responses: '200': description: Software request status returned content: application/json: schema: $ref: '#/components/schemas/SoftwareRequestsResponse' /request/software/status/{id}: get: summary: Get software request status and history description: Returns one software request and its lifecycle history when the caller may view it. tags: - request parameters: - in: path name: id required: true schema: type: integer minimum: 1 responses: '200': description: Software request details returned content: application/json: schema: $ref: '#/components/schemas/SoftwareRequestDetailResponse' '404': description: Request not found or caller may not view it delete: summary: Clear a cancelled software request description: Permanently removes the caller's cancelled software request and saved status history. Request managers may clear any cancelled request. tags: - request parameters: - in: path name: id required: true schema: type: integer minimum: 1 responses: '204': description: Cancelled software request cleared '404': description: Request not found or caller may not clear it '409': description: Request is not cancelled /request/software/status/{id}/approve: post: summary: Approve a software request description: Approves a pending software request and dispatches it idempotently to its acquisition provider. Requires MANAGE_REQUESTS. tags: - request parameters: - in: path name: id required: true schema: type: integer minimum: 1 responses: '200': description: Software request approved content: application/json: schema: $ref: '#/components/schemas/SoftwareRequestMutationResponse' '409': description: Request is no longer pending /request/software/status/{id}/decline: post: summary: Decline a software request description: Declines a pending software request. Requires MANAGE_REQUESTS. tags: - request parameters: - in: path name: id required: true schema: type: integer minimum: 1 responses: '200': description: Software request declined content: application/json: schema: $ref: '#/components/schemas/SoftwareRequestMutationResponse' '409': description: Request is no longer pending /request/software/status/{id}/withdraw: post: summary: Withdraw a pending software request description: Allows the requester to withdraw their own request before provider dispatch. Requires REQUEST permission. tags: - request parameters: - in: path name: id required: true schema: type: integer minimum: 1 responses: '200': description: Software request withdrawn content: application/json: schema: $ref: '#/components/schemas/SoftwareRequestMutationResponse' '403': description: Request permission is required '404': description: Request not found or caller is not the requester '409': description: Request is no longer pending /request/software/status/{id}/cancel: post: summary: Cancel an active software request description: Lets the original requester with REQUEST permission or an administrator with MANAGE_REQUESTS cancel provider work. QuestarrNG stops only downloads correlated to this request; ROMarrNG cancellation is available before download handoff. An interrupted handoff can require explicit confirmation after checking the download queue and history. tags: - request parameters: - in: path name: id required: true schema: type: integer minimum: 1 requestBody: required: false content: application/json: schema: type: object properties: confirmNoExistingDownload: type: boolean description: Set true only after checking the download client queue and history for a matching download. responses: '200': description: Provider confirmed that the request was cancelled content: application/json: schema: $ref: '#/components/schemas/SoftwareRequestMutationResponse' '403': description: Caller does not have permission to manage this request '404': description: Request not found or caller may not view it '409': description: Provider cannot safely cancel the request in its current state content: application/json: schema: type: object properties: confirmationRequired: type: string enum: [confirmNoExistingDownload] error: type: string '502': description: Acquisition provider is unavailable /request/software/status/{id}/retry: post: summary: Retry a failed software request description: Retries a failed provider request using its existing idempotency key. The original requester must still have REQUEST permission, or the caller must have MANAGE_REQUESTS. QuestarrNG or ROMarrNG can require explicit confirmation when a restart interrupted a download handoff. tags: - request parameters: - in: path name: id required: true schema: type: integer minimum: 1 requestBody: required: false content: application/json: schema: type: object properties: confirmNoExistingDownload: type: boolean description: Set true only after checking the download client queue and history for a matching download. responses: '200': description: Software request retry started content: application/json: schema: $ref: '#/components/schemas/SoftwareRequestMutationResponse' '409': description: Request is not failed or the provider requires a download handoff confirmation content: application/json: schema: type: object properties: confirmationRequired: type: string enum: [confirmNoExistingDownload] error: type: string /request/software/status/{id}/downloads: get: summary: List available files for a software request description: Returns verified, imported request assets only. Provider URLs and local paths are never returned. tags: - request parameters: - in: path name: id required: true schema: type: integer minimum: 1 responses: '200': description: Downloadable software files returned content: application/json: schema: type: object /request/software/status/{id}/downloads/{assetId}: get: summary: Download a software request asset through SeerrNG description: Streams one verified, request-scoped provider asset after checking request access and current availability. tags: - request parameters: - in: path name: id required: true schema: type: integer minimum: 1 - in: path name: assetId required: true schema: type: string responses: '200': description: Asset bytes streamed to the caller content: application/octet-stream: schema: type: string format: binary '206': description: Requested byte range streamed when supported by the provider '404': description: Request or asset not found or no longer available /request/status: get: summary: Get request lifecycle status description: | Returns request lifecycle projections for the authenticated user. Users with `MANAGE_REQUESTS` or `REQUEST_VIEW` may inspect all users' requests and may narrow the result with `requestedBy`. Status filters are evaluated against current media availability and the latest synchronized download queue snapshot, so a request is not hidden by a stale historical stage. tags: - request parameters: - in: query name: take schema: type: number minimum: 1 maximum: 100 default: 10 - in: query name: skip schema: type: number minimum: 0 default: 0 - in: query name: requestedBy schema: type: number minimum: 1 - in: query name: requestId description: Restrict results to one request; used by Request Status notification links. schema: type: number minimum: 1 - in: query name: mediaId description: Restrict results to requests for one internal media record. schema: type: number minimum: 1 - in: query name: bookFormat description: Restrict book requests to ebook-compatible or audiobook-compatible requests. schema: type: string enum: [ebook, audiobook] - in: query name: timeFrame description: Restrict results to requests created in the selected rolling time window. Defaults to the last 7 days; use all for complete history. schema: type: string enum: [7d, 14d, 30d, 1m, 6m, all] default: 7d - in: query name: sort description: Sort field. Metadata-backed fields are resolved from the configured metadata provider and fall back safely when unavailable. schema: type: string enum: [ added, modified, status, incomplete, title, director, writer, rating, releaseDate, artist, author, publisher, ] default: added - in: query name: sortDirection schema: type: string enum: [asc, desc] default: desc - in: query name: mediaType schema: type: string enum: [movie, tv, music, book, comic, magazine, sports, all] default: all - in: query name: filter schema: type: string enum: [ all, pending, processing, deleted, active, incomplete, attention, requested, approved, searching, downloading, importing, library, available, unavailable, failed, declined, cancelled, completed, ] default: all - in: query name: search description: Search locally stored request, media, requester, service, and external identifier metadata. schema: type: string maxLength: 512 nullable: true responses: '200': description: Request lifecycle statuses returned content: application/json: schema: $ref: '#/components/schemas/RequestStatusPage' /request/status/users: get: summary: Get users available for request status viewing description: Returns minimal user identities for users with request-view permission selecting another user's request history. No account or permission fields are returned. tags: - request parameters: - in: query name: take schema: type: number minimum: 1 maximum: 100 default: 100 - in: query name: skip schema: type: number minimum: 0 default: 0 responses: '200': description: Status viewer users returned content: application/json: schema: type: object properties: pageInfo: $ref: '#/components/schemas/PageInfo' results: type: array items: type: object properties: id: type: integer displayName: type: string avatar: type: string required: [id, displayName, avatar] required: [pageInfo, results] /request/status/{requestId}: get: summary: Get request lifecycle history description: Returns the current lifecycle projection and durable status history for a request the caller may view. tags: - request parameters: - in: path name: requestId required: true description: Request ID schema: type: string example: '1' responses: '200': description: Request lifecycle status and history returned content: application/json: schema: $ref: '#/components/schemas/RequestStatusDetail' /request/status/{requestId}/downloads: get: summary: List downloadable copies for a request description: Returns verified imported files only when the caller may view the request and its current lifecycle stage is available. Filesystem paths and provider credentials are never returned. tags: - request parameters: - in: path name: requestId required: true description: Request ID schema: type: string example: '1' responses: '200': description: Downloadable copies returned content: application/json: schema: type: object properties: results: type: array items: type: object properties: id: type: string description: Opaque, request-scoped asset ID. name: type: string size: type: integer minimum: 0 format: type: string description: Book file format; omitted for non-book assets. enum: [ebook, audiobook] required: [id, name] hadErrors: type: boolean description: True when one or more provider lookups failed; results may still contain usable files. required: [results, hadErrors] '403': description: Caller may not view this request '404': description: Request not found /request/status/{requestId}/downloads/{assetId}: get: summary: Download a request asset through SeerrNG description: Streams one verified request asset after rechecking request access and availability. Provider URLs, credentials, and filesystem paths stay server-side. tags: - request parameters: - in: path name: requestId required: true description: Request ID schema: type: string example: '1' - in: path name: assetId required: true description: Opaque asset ID returned by the downloads listing. schema: type: string responses: '200': description: Asset bytes streamed to the caller content: application/octet-stream: schema: type: string format: binary '206': description: Requested byte range streamed for a filesystem-backed asset '403': description: Caller may not view this request '404': description: Request or asset not found or no longer available /request/{requestId}: get: summary: Get MediaRequest description: Returns a specific MediaRequest in a JSON object. tags: - request parameters: - in: path name: requestId description: Request ID required: true example: '1' schema: type: string responses: '200': description: Succesfully returns request content: application/json: schema: $ref: '#/components/schemas/MediaRequest' put: summary: Update MediaRequest description: Updates a specific media request and returns the request in a JSON object. Requires the `MANAGE_REQUESTS` permission. tags: - request parameters: - in: path name: requestId description: Request ID required: true example: '1' schema: type: string requestBody: required: true content: application/json: schema: type: object properties: mediaType: type: string enum: [movie, tv, music, book, comic, magazine, sports] seasons: type: array items: type: number minimum: 0 watchAheadEpisodeCount: type: integer minimum: 0 maximum: 5 description: Episode Queue buffer for the request owner's Plex, Jellyfin, or Emby playback. is4k: type: boolean example: false serverId: type: number profileId: type: number rootFolder: type: string languageProfileId: type: number metadataProfileId: type: number tags: type: array items: type: number format: type: string enum: [ebook, audiobook, both] description: Book request format. userId: type: number nullable: true required: - mediaType responses: '200': description: Succesfully updated request content: application/json: schema: $ref: '#/components/schemas/MediaRequest' '409': description: Only pending requests can be modified delete: summary: Delete request description: Removes a request. If the user has the `MANAGE_REQUESTS` permission, any request can be removed. Otherwise, only pending requests can be removed. tags: - request parameters: - in: path name: requestId description: Request ID required: true example: '1' schema: type: string responses: '204': description: Succesfully removed request /request/{requestId}/watch-ahead: put: summary: Update the TV Episode Queue description: | Sets the number of upcoming episodes to keep requested for a TV request as the owner watches in Plex, Jellyfin, or Emby. Only the request owner can enable or change the buffer; setting episodeCount to 0 disables future Episode Queue additions. tags: - request parameters: - in: path name: requestId description: TV request ID required: true schema: type: string example: '1' requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: [episodeCount] properties: episodeCount: type: integer minimum: 0 maximum: 5 responses: '200': description: Updated TV request content: application/json: schema: $ref: '#/components/schemas/MediaRequest' '400': description: The request is not eligible for watch-ahead '403': description: Only the request owner can enable watch-ahead '404': description: Request not found '409': description: Jellyfin or Sonarr is not configured, the series has no TVDB identity, or the request cannot be enrolled /request/{requestId}/fail-download: post: summary: Fail an active request download and search again description: | Removes and blocklists the selected active Radarr or Sonarr release, then starts a fresh search. The request owner may use this action while they still have permission to request the media; users with `MANAGE_REQUESTS` may use it on any request. tags: - request parameters: - in: path name: requestId description: Request ID required: true schema: type: string example: '1' requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: [downloadId] properties: downloadId: type: string minLength: 1 maxLength: 2048 description: Identifier of the active Radarr or Sonarr queue download. responses: '200': description: Release removed and a new search started content: application/json: schema: type: object required: [success] properties: success: type: boolean enum: [true] '400': description: Invalid download identifier or unsupported request media type '401': description: Authentication required '403': description: Caller may not manage this request download '404': description: Request not found '409': description: Request is not active, the selected download is stale, or its acquisition service changed '502': description: The release was removed but a new search could not be started, or the acquisition service failed /request/{requestId}/retry: post: summary: Retry failed or unavailable request description: | Retries a failed or unavailable request by returning it to the normal dispatch/search flow. The request owner may retry their own request when they still have permission to request that media; users with `MANAGE_REQUESTS` or `ADMIN` may retry any request. tags: - request parameters: - in: path name: requestId description: Request ID required: true schema: type: string example: '1' responses: '200': description: Retry triggered content: application/json: schema: $ref: '#/components/schemas/MediaRequest' /request/{requestId}/status: delete: summary: Delete request status entry description: | Cancels and cleans up active work when required, then permanently removes the request and its lifecycle history. The owner may remove their own request; users with `MANAGE_REQUESTS` or `ADMIN` may remove any request. tags: - request parameters: - in: path name: requestId description: Request ID required: true schema: type: string example: '1' responses: '204': description: Request status entry and history removed '409': description: Active work could not be cleaned up safely /request/{requestId}/{status}: post: summary: Update a request's status description: | Updates a request's status to approved or declined. Also returns the request in a JSON object. Requires the `MANAGE_REQUESTS` permission or `ADMIN`. tags: - request parameters: - in: path name: requestId description: Request ID required: true schema: type: string example: '1' - in: path name: status description: New status required: true schema: type: string enum: [approve, decline] responses: '200': description: Request status changed content: application/json: schema: $ref: '#/components/schemas/MediaRequest' '400': description: Status must be approve or decline '409': description: Only pending requests can be approved or declined /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}/cover: get: summary: Get linked Radarr cover image description: Streams a poster image from the linked Radarr service for a saved movie media row. tags: - movies parameters: - in: path name: movieId required: true schema: type: number example: 337401 - in: query name: mediaId required: true schema: type: integer minimum: 1 - in: query name: is4k schema: type: boolean default: false responses: '200': description: Movie cover image content: image/jpeg: schema: type: string format: binary image/png: schema: type: string format: binary image/webp: schema: type: string format: binary '404': description: Movie cover not found /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 - in: query name: shuffleSeed schema: type: string maxLength: 128 example: refresh-1 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 - in: query name: shuffleSeed schema: type: string maxLength: 128 example: refresh-1 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/ratings/mdblist/batch: post: summary: Get MDBList movie ratings for a batch description: Looks up MDBList ratings for up to 200 TMDB movie IDs and primes the shared title-rating cache. tags: - movies requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/MdblistRatingBatchRequest' responses: '200': description: Available ratings keyed by TMDB movie ID. Titles without ratings are omitted. content: application/json: schema: $ref: '#/components/schemas/MdblistRatingsBatchResponse' '400': description: The batch contains invalid TMDB IDs. '502': description: MDBList ratings are temporarily unavailable. /movie/{movieId}/ratingscombined: get: summary: Get combined movie ratings description: Returns available Rotten Tomatoes, IMDb, and MDBList ratings for the provided movieId. MDBList is optional and best-effort. tags: - movies parameters: - in: path name: movieId required: true schema: type: number example: 337401 responses: '200': description: Ratings returned content: application/json: schema: $ref: '#/components/schemas/MediaRatings' /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}/media-server-saved-item: parameters: - in: path name: tvId required: true schema: type: integer minimum: 1 maximum: 1000000000 get: summary: Get the current account's native Series saved state description: Reads Plex Universal Watchlist or Jellyfin/Emby Favorites for the authenticated user's linked native account. Favorites use the trusted Series item for the selected quality, without falling back to a different quality. Plex Watchlist is format-independent. Does not mutate provider state or the Seerr watchlist. Provider credentials and catalog identities are resolved server-side and never returned. tags: [tv] parameters: - in: query name: is4k schema: type: boolean default: false description: Select the trusted 4K Series root for native Favorites. Accepts only true or false. Ignored by format-independent Plex Watchlist. security: - cookieAuth: [] responses: '200': description: Native account capability and saved state content: application/json: schema: &mediaServerSavedItemStatus type: object required: [serverType, kind, available] properties: serverType: type: integer enum: [1, 2, 3, 4] kind: type: string enum: [watchlist, favorites] available: type: boolean saved: type: boolean reason: type: string enum: [account-not-linked, series-not-found] '400': description: Invalid Series ID '401': description: Authentication required '403': description: Current account authority changed '429': description: Too many saved-state requests '502': description: Sanitized provider failure; no saved success is asserted content: application/json: schema: &mediaServerSavedItemFailure type: object additionalProperties: false required: [message] properties: message: type: string diagnostic: type: object additionalProperties: false required: [phase, category] properties: phase: type: string enum: [ series-metadata, account, catalog-search, catalog-identity, watchlist-state, watchlist-write, watchlist-confirmation, ] category: type: string enum: [ http, transport, invalid-response, identity-mismatch, confirmation-mismatch, unexpected, ] upstreamStatus: type: integer minimum: 400 maximum: 599 post: summary: Set the current account's native Series saved state description: Adds or removes the entire Series from Plex Universal Watchlist or Jellyfin/Emby Favorites using only the authenticated user's fresh linked credentials. Strict desired-state mutation is idempotent and verified by provider readback. Selected seasons and episodes are not added separately. Does not create Seerr requests, change auto-request settings, or move/synchronize membership with any other list. Existing Plex Watchlist auto-request behavior may independently observe membership. Uses application cookie authentication and existing CSRF protection. tags: [tv] security: - cookieAuth: [] requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: [saved] properties: saved: type: boolean is4k: type: boolean default: false description: Select the trusted 4K Series root for Favorites, without other-quality fallback. Plex Watchlist is format-independent. responses: '200': description: Confirmed native saved state content: application/json: schema: *mediaServerSavedItemStatus '400': description: Invalid Series ID or mutation body '401': description: Authentication required '403': description: Current account authority changed or CSRF rejection '409': description: Linked account or matching native Series is unavailable '429': description: Too many saved-state requests '502': description: Sanitized provider failure or unconfirmed write content: application/json: schema: *mediaServerSavedItemFailure /tv/{tvId}/media-server-collections: get: summary: Get existing authorized media-server Collections for this Series description: Lists existing eligible Collections and whole-Series membership using only the authenticated user's linked native credentials. Collections may be shared server/library assets, not private watchlists. Uses a trusted quality-selected Series root. Plex requires current-account ownership of the configured PMS; Jellyfin/Emby require native Collection-management permission. Smart Collections and unsupported media types are excluded. No Collection is created, and no membership is synchronized with Watchlist or Favorites. tags: [tv] security: - cookieAuth: [] parameters: - in: path name: tvId required: true schema: type: integer minimum: 1 maximum: 1000000000 - in: query name: is4k schema: type: boolean default: false description: Select the trusted 4K Series root. Accepts only true or false; no other-quality fallback. responses: '200': description: Native Collection capability and confirmed existing membership content: application/json: schema: &mediaServerCollectionsStatus type: object required: [serverType, available, collections] properties: serverType: type: integer enum: [1, 2, 3, 4] available: type: boolean reason: type: string enum: [ account-not-linked, not-authorized, series-not-found, unsupported-server, collection-limit, ] collections: type: array items: type: object required: [id, name, member] properties: id: type: string minLength: 1 maxLength: 128 pattern: '^[a-zA-Z0-9-]+$' name: type: string minLength: 1 maxLength: 512 member: type: boolean '400': description: Invalid Series ID or strict quality query '401': description: Authentication required '403': description: Current account authority changed '429': description: Too many native Collection requests '502': description: Sanitized provider failure or incomplete native response /tv/{tvId}/media-server-collections/{collectionId}: post: summary: Set whole-Series membership in one existing authorized Collection description: Idempotently adds or removes the trusted quality-selected Series root in an existing eligible media-server Collection using fresh current-user native authority. Revalidates Collection and Series identities and verifies membership after any write. Does not create or delete a Collection, add selected episodes, synchronize other list membership, or directly create Seerr requests. Uses application cookie authentication and existing CSRF protection. Tokens, native Series item IDs and user IDs are never client parameters. tags: [tv] security: - cookieAuth: [] parameters: - in: path name: tvId required: true schema: type: integer minimum: 1 maximum: 1000000000 - in: path name: collectionId required: true schema: type: string minLength: 1 maxLength: 128 pattern: '^[a-zA-Z0-9-]+$' requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: [member] properties: member: type: boolean is4k: type: boolean default: false description: Select the trusted 4K Series root, without other-quality fallback. responses: '200': description: Refreshed native Collection membership content: application/json: schema: *mediaServerCollectionsStatus '400': description: Invalid Series or Collection ID, unexpected query, or mutation body '401': description: Authentication required '403': description: Current account authority changed, native permission denied, or CSRF rejection '409': description: Linked account, selected-quality Series, or eligible Collection is unavailable '429': description: Too many native Collection requests '502': description: Sanitized provider failure or unconfirmed write /tv/{tvId}/cover: get: summary: Get linked Sonarr cover image description: Streams a poster image from the linked Sonarr service for a saved TV media row. tags: - tv parameters: - in: path name: tvId required: true schema: type: number example: 76479 - in: query name: mediaId required: true schema: type: integer minimum: 1 - in: query name: is4k schema: type: boolean default: false responses: '200': description: TV cover image content: image/jpeg: schema: type: string format: binary image/png: schema: type: string format: binary image/webp: schema: type: string format: binary '404': description: TV cover not found /tv/{tvId}/season/{seasonNumber}: 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: seasonNumber required: true schema: type: number example: 123456 - in: query name: language schema: type: string example: en responses: '200': description: TV details content: application/json: schema: $ref: '#/components/schemas/Season' /tv/{tvId}/recommendations: get: summary: Get recommended TV series description: Returns list of recommended TV series based on the provided tvId in a JSON object. tags: - tv parameters: - in: path name: tvId required: true schema: type: number example: 76479 - in: query name: page schema: type: number example: 1 default: 1 - in: query name: language schema: type: string example: en - in: query name: shuffleSeed schema: type: string maxLength: 128 example: refresh-1 responses: '200': description: List of TV series 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/TvResult' /tv/{tvId}/similar: get: summary: Get similar TV series description: Returns list of similar TV series based on the provided tvId in a JSON object. tags: - tv parameters: - in: path name: tvId required: true schema: type: number example: 76479 - in: query name: page schema: type: number example: 1 default: 1 - in: query name: language schema: type: string example: en - in: query name: shuffleSeed schema: type: string maxLength: 128 example: refresh-1 responses: '200': description: List of TV series 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/TvResult' /tv/{tvId}/ratings: get: summary: Get TV ratings description: Returns ratings based on provided tvId in a JSON object. tags: - tv parameters: - in: path name: tvId required: true schema: type: number example: 76479 responses: '200': description: Ratings returned content: application/json: schema: type: object properties: title: type: string example: The Boys year: type: number example: 2019 url: type: string example: 'http://www.rottentomatoes.com/m/mulan_2020/' criticsScore: type: number example: 85 criticsRating: type: string enum: ['Rotten', 'Fresh'] /tv/ratings/mdblist/batch: post: summary: Get MDBList TV ratings for a batch description: Looks up MDBList ratings for up to 200 TMDB series IDs and primes the shared title-rating cache. tags: - tv requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/MdblistRatingBatchRequest' responses: '200': description: Available ratings keyed by TMDB series ID. Titles without ratings are omitted. content: application/json: schema: $ref: '#/components/schemas/MdblistRatingsBatchResponse' '400': description: The batch contains invalid TMDB IDs. '502': description: MDBList ratings are temporarily unavailable. /tv/{tvId}/ratingscombined: get: summary: Get combined TV ratings description: Returns available Rotten Tomatoes and MDBList ratings for the provided tvId. MDBList is optional and best-effort. tags: - tv parameters: - in: path name: tvId required: true schema: type: number example: 76479 responses: '200': description: Ratings returned content: application/json: schema: $ref: '#/components/schemas/MediaRatings' /person/{personId}: get: summary: Get person details description: Returns person details based on provided personId in a JSON object. tags: - person parameters: - in: path name: personId required: true schema: type: number example: 287 - in: query name: language schema: type: string example: en responses: '200': description: Returned person content: application/json: schema: $ref: '#/components/schemas/PersonDetails' /person/{personId}/combined_credits: get: summary: Get combined credits description: Returns the person's combined credits based on the provided personId in a JSON object. tags: - person parameters: - in: path name: personId required: true schema: type: number example: 287 - in: query name: language schema: type: string example: en responses: '200': description: Returned combined credits content: application/json: schema: type: object properties: cast: type: array items: $ref: '#/components/schemas/CreditCast' crew: type: array items: $ref: '#/components/schemas/CreditCrew' id: type: number /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 - in: query name: mediaType schema: type: string nullable: true example: movie,tv responses: '200': description: Returned media content: application/json: schema: type: object properties: pageInfo: $ref: '#/components/schemas/PageInfo' results: type: array items: $ref: '#/components/schemas/MediaInfo' /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}/library: parameters: - in: path name: mediaId required: true schema: type: string get: summary: Resolve all verified library copies description: Read-only inventory across configured services. Requires MANAGE_REQUESTS. Returns a confirmation token bound to the exact media, targets and service configuration. No default-service guessing or deletion. tags: [media] responses: '200': description: Verified library copies and confirmation token content: application/json: schema: type: object required: [targets, token] properties: token: type: string targets: type: array items: type: object required: [ key, serviceId, serviceType, externalId, service, quality, url, ] properties: key: type: string serviceId: type: integer serviceType: type: string enum: [radarr, sonarr, lidarr, readarr] externalId: type: integer service: type: string quality: type: string url: type: string '403': description: Not authorized '404': description: Media not found '502': description: Could not verify the complete library scope delete: summary: Delete all confirmed library copies description: Requires MANAGE_REQUESTS. Revalidates the exact confirmation scope before deleting files and entries from every listed service. Stops on failure and preserves requests, issues, other titles, authors and artists. tags: [media] requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: [token] properties: token: type: string pattern: '^[a-f0-9]{64}$' responses: '204': description: All confirmed copies removed '400': description: Missing or invalid confirmation '403': description: No longer authorized '404': description: Media not found '409': description: Scope changed or deletion failed; review refreshed state '502': description: Could not verify services before deletion /media/{mediaId}/file: delete: summary: Delete media file description: Removes a media file from radarr/sonarr. The `ADMIN` permission is required to perform this action. tags: - media parameters: - in: path name: mediaId description: Media ID required: true example: '1' schema: type: string - in: query name: is4k description: Whether to remove from 4K service instance (true) or regular service instance (false) required: false example: false schema: type: boolean - in: query name: format description: Book format to remove (ebook, audiobook, or both) required: false example: audiobook schema: type: string enum: [ebook, audiobook, both] responses: '204': description: Successfully 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 description: | When true, updates the 4K status field (status4k). When false or not provided, updates the regular status field (status). This applies to all status values (available, partial, processing, pending, unknown). responses: '200': description: Returned media content: application/json: schema: $ref: '#/components/schemas/MediaInfo' /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' /collection/{collectionId}: get: summary: Get collection details description: Returns full collection details in a JSON object. tags: - collection parameters: - in: path name: collectionId required: true schema: type: number example: 537982 - in: query name: language schema: type: string example: en responses: '200': description: Collection details content: application/json: schema: $ref: '#/components/schemas/Collection' /collection/{collectionId}/availability: post: summary: Check indexed collection members and linked media-server collections description: Performs bounded identity lookups and additive synchronization of explicitly managed collections. Does not scan media files or create collections. tags: [collection] parameters: - in: path name: collectionId required: true schema: type: integer minimum: 1 maximum: 1000000000 responses: '200': description: Fresh availability and collection destinations (destinations are admin-only) content: application/json: schema: type: object properties: collection: $ref: '#/components/schemas/Collection' sync: type: object '503': description: Media server could not be verified; cached availability must be retained /collection/{collectionId}/server: post: summary: Add a collection to Plex, Jellyfin or Emby description: Admin-only. Creates missing collections from selected indexed members. Selection applies to creation only; newly available members are added automatically. Existing unrelated collections are not modified. tags: [collection] parameters: - in: path name: collectionId required: true schema: type: integer minimum: 1 maximum: 1000000000 requestBody: required: true content: application/json: schema: type: object required: [libraryIds] additionalProperties: false properties: selectedIds: description: Initial member selection only, not a filter for automatic updates. Omit to select all. type: array minItems: 1 maxItems: 500 uniqueItems: true items: type: string pattern: '^[1-9]\d{0,9}$' libraryIds: type: array minItems: 1 maxItems: 50 uniqueItems: true items: type: string pattern: '^[a-zA-Z0-9-]{1,128}$' responses: '200': description: Per-library result; unknown destinations may require a later retry content: application/json: schema: type: object '403': description: Administrator permission required '503': description: Unable to verify the media server delete: summary: Remove a collection without deleting media description: Admin-only. Rechecks each confirmed remote collection identity, stops automatic updates, and removes the collection container only. Movies and media files are preserved. tags: [collection] parameters: - in: path name: collectionId required: true schema: type: integer minimum: 1 maximum: 1000000000 requestBody: required: true content: application/json: schema: type: object required: [destinations] additionalProperties: false properties: destinations: type: array minItems: 1 maxItems: 50 items: type: object additionalProperties: false required: [libraryId, removalToken] properties: libraryId: type: string pattern: '^[a-zA-Z0-9-]{1,128}$' removalToken: type: string pattern: '^[a-f0-9]{64}$' responses: '200': description: Verified removal result per destination content: application/json: schema: type: object '400': description: Invalid confirmation '403': description: Administrator permission required '503': description: Collection identity or removal could not be verified /collection-catalog/tv/for-series/{id}: get: summary: Find official TV franchise collections for a series tags: [collection] parameters: - in: path name: id required: true schema: type: integer minimum: 1 maximum: 999999999 responses: '200': description: Verified collection result content: application/json: schema: type: object '400': description: Invalid selection or confirmation '403': description: Administrator permission required for changes '404': description: Collection not found '503': description: Provider or media server could not be verified /collection-catalog/{kind}/{id}: parameters: - in: path name: kind required: true schema: type: string enum: [tv, music] - in: path name: id required: true schema: type: string pattern: '^[a-zA-Z0-9-]{1,128}$' get: summary: Get a TV franchise or artist album collection tags: [collection] responses: '200': description: Verified collection result content: application/json: schema: type: object '400': description: Invalid selection or confirmation '403': description: Administrator permission required for changes '404': description: Collection not found '503': description: Provider or media server could not be verified /collection-catalog/{kind}/{id}/availability: parameters: - in: path name: kind required: true schema: type: string enum: [tv, music] - in: path name: id required: true schema: type: string pattern: '^[a-zA-Z0-9-]{1,128}$' post: summary: Check available collection members and synchronize existing managed collections tags: [collection] responses: '200': description: Verified collection result content: application/json: schema: type: object '400': description: Invalid selection or confirmation '403': description: Administrator permission required for changes '404': description: Collection not found '503': description: Provider or media server could not be verified /collection-catalog/{kind}/{id}/server: parameters: - in: path name: kind required: true schema: type: string enum: [tv, music] - in: path name: id required: true schema: type: string pattern: '^[a-zA-Z0-9-]{1,128}$' post: summary: Create a collection from the selected available members description: Admin-only. Selection affects initial creation, not future automatic additions. tags: [collection] requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: [libraryIds, selectedIds] properties: libraryIds: type: array minItems: 1 maxItems: 50 uniqueItems: true items: type: string pattern: '^[a-zA-Z0-9-]{1,128}$' selectedIds: type: array minItems: 1 maxItems: 500 uniqueItems: true items: type: string pattern: '^[a-zA-Z0-9-]{1,128}$' responses: '200': description: Verified collection result content: application/json: schema: type: object '400': description: Invalid selection or confirmation '403': description: Administrator permission required for changes '404': description: Collection not found '503': description: Provider or media server could not be verified delete: summary: Remove a verified collection without deleting media files tags: [collection] requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: [destinations] properties: destinations: type: array minItems: 1 maxItems: 50 items: type: object additionalProperties: false required: [libraryId, removalToken] properties: libraryId: type: string pattern: '^[a-zA-Z0-9-]{1,128}$' removalToken: type: string pattern: '^[a-f0-9]{64}$' responses: '200': description: Verified collection result content: application/json: schema: type: object '400': description: Invalid selection or confirmation '403': description: Administrator permission required for changes '404': description: Collection not found '503': description: Provider or media server could not be verified /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' /regions: get: summary: Regions supported by TMDB description: Returns a list of regions in a JSON object. tags: - tmdb responses: '200': description: Results content: application/json: schema: type: array items: type: object properties: iso_3166_1: type: string example: US english_name: type: string example: United States of America /languages: get: summary: Languages supported by TMDB description: Returns a list of languages in a JSON object. tags: - tmdb responses: '200': description: Results content: application/json: schema: type: array items: type: object properties: iso_639_1: type: string example: en english_name: type: string example: English name: type: string example: English /studio/{studioId}: get: summary: Get movie studio details description: Returns movie studio details in a JSON object. tags: - tmdb parameters: - in: path name: studioId required: true schema: type: number example: 2 responses: '200': description: Movie studio details content: application/json: schema: $ref: '#/components/schemas/ProductionCompany' /network/{networkId}: get: summary: Get TV network details description: Returns TV network details in a JSON object. tags: - tmdb parameters: - in: path name: networkId required: true schema: type: number example: 1 responses: '200': description: TV network details content: application/json: schema: $ref: '#/components/schemas/ProductionCompany' /genres/movie: get: summary: Get list of official TMDB movie genres description: Returns a list of genres in a JSON array. tags: - tmdb parameters: - in: query name: language schema: type: string example: en responses: '200': description: Results content: application/json: schema: type: array items: type: object properties: id: type: number example: 10751 name: type: string example: Family /genres/tv: get: summary: Get list of official TMDB movie genres description: Returns a list of genres in a JSON array. tags: - tmdb parameters: - in: query name: language schema: type: string example: en responses: '200': description: Results content: application/json: schema: type: array items: type: object properties: id: type: number example: 18 name: type: string example: Drama /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 /issue: get: summary: Get all issues description: | Returns a list of issues in JSON format. tags: - issue 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: [added, modified, status] default: added - in: query name: sortDirection schema: type: string enum: [asc, desc] default: desc - in: query name: filter schema: type: string enum: [all, open, resolved] default: open - in: query name: requestedBy schema: type: number nullable: true example: 1 - in: query name: timeFrame schema: type: string enum: [7d, 14d, 30d, 6m, all] default: all - in: query name: mediaType schema: type: string enum: [all, movie, tv, music, book, comic, magazine] default: all - in: query name: issueType schema: type: string enum: [all, audio, video, subtitle, other] default: all - in: query name: search schema: type: string nullable: true example: playback responses: '200': description: Issues returned content: application/json: schema: type: object properties: pageInfo: $ref: '#/components/schemas/PageInfo' results: type: array items: $ref: '#/components/schemas/Issue' post: summary: Create new issue description: | Creates a new issue tags: - issue requestBody: required: true content: application/json: schema: type: object properties: issueType: type: number issueSubtype: type: string maxLength: 64 enum: - missing_content - missing_issue - wrong_edition - wrong_issue - damaged_file - incorrect_metadata - other message: type: string mediaId: type: number problemSeason: type: number minimum: 0 problemEpisode: type: number minimum: 0 problemEpisodes: type: array maxItems: 500 items: type: number minimum: 1 problemEpisodeSelections: type: array maxItems: 100 items: $ref: '#/components/schemas/SeasonEpisodeSelection' is4k: type: boolean userId: type: number nullable: true responses: '201': description: Succesfully created the issue content: application/json: schema: $ref: '#/components/schemas/Issue' /issue/count: get: summary: Gets issue counts description: | Returns the number of open and closed issues, as well as the number of issues of each type. tags: - issue responses: '200': description: Issue counts returned content: application/json: schema: type: object properties: total: type: number video: type: number audio: type: number subtitles: type: number others: type: number open: type: number closed: type: number /issue/{issueId}: get: summary: Get issue description: | Returns a single issue in JSON format. tags: - issue parameters: - in: path name: issueId required: true schema: type: number example: 1 responses: '200': description: Issues returned content: application/json: schema: $ref: '#/components/schemas/Issue' delete: summary: Delete issue description: Removes an issue. If the user has the `MANAGE_ISSUES` permission, any issue can be removed. Otherwise, only a users own issues can be removed. tags: - issue parameters: - in: path name: issueId description: Issue ID required: true example: '1' schema: type: string responses: '204': description: Succesfully removed issue /issue/{issueId}/comment: post: summary: Create a comment description: | Creates a comment and returns associated issue in JSON format. tags: - issue parameters: - in: path name: issueId required: true schema: type: number example: 1 requestBody: required: true content: application/json: schema: type: object properties: message: type: string required: - message responses: '200': description: Issue returned with new comment content: application/json: schema: $ref: '#/components/schemas/Issue' /issueComment/{commentId}: get: summary: Get issue comment description: | Returns a single issue comment in JSON format. tags: - issue parameters: - in: path name: commentId required: true schema: type: string example: 1 responses: '200': description: Comment returned content: application/json: schema: $ref: '#/components/schemas/IssueComment' put: summary: Update issue comment description: | Updates and returns a single issue comment in JSON format. tags: - issue parameters: - in: path name: commentId required: true schema: type: string example: 1 requestBody: required: true content: application/json: schema: type: object properties: message: type: string responses: '200': description: Comment updated content: application/json: schema: $ref: '#/components/schemas/IssueComment' delete: summary: Delete issue comment description: | Deletes an issue comment. Only users with `MANAGE_ISSUES` or the user who created the comment can perform this action. tags: - issue parameters: - in: path name: commentId description: Issue Comment ID required: true example: '1' schema: type: string responses: '204': description: Succesfully removed issue comment /issue/{issueId}/{status}: post: summary: Update an issue's status description: | Updates an issue's status to approved or declined. Also returns the issue in a JSON object. Requires the `MANAGE_ISSUES` permission or `ADMIN`. tags: - issue parameters: - in: path name: issueId description: Issue ID required: true schema: type: string example: '1' - in: path name: status description: New status required: true schema: type: string enum: [open, resolved] responses: '200': description: Issue status changed content: application/json: schema: $ref: '#/components/schemas/Issue' /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 (null if not found) content: application/json: schema: nullable: true $ref: '#/components/schemas/Keyword' '500': description: Internal server error content: application/json: schema: type: object properties: message: type: string example: 'Unable to retrieve keyword data.' /watchproviders/regions: get: summary: Get watch provider regions description: | Returns a list of all available watch provider regions. tags: - other responses: '200': description: Watch provider regions returned content: application/json: schema: type: array items: $ref: '#/components/schemas/WatchProviderRegion' /watchproviders/movies: get: summary: Get watch provider movies description: | Returns a list of all available watch providers for movies. tags: - other parameters: - in: query name: watchRegion required: true schema: type: string example: US responses: '200': description: Watch providers for movies returned content: application/json: schema: type: array items: $ref: '#/components/schemas/WatchProviderDetails' /watchproviders/tv: get: summary: Get watch provider series description: | Returns a list of all available watch providers for series. tags: - other parameters: - in: query name: watchRegion required: true schema: type: string example: US responses: '200': description: Watch providers for series returned content: application/json: schema: type: array items: $ref: '#/components/schemas/WatchProviderDetails' /certifications/movie: get: summary: Get movie certifications description: Returns list of movie certifications from TMDB. tags: - other security: - cookieAuth: [] - apiKey: [] responses: '200': description: Movie certifications returned content: application/json: schema: $ref: '#/components/schemas/CertificationResponse' '500': description: Unable to retrieve movie certifications content: application/json: schema: type: object properties: status: type: number example: 500 message: type: string example: Unable to retrieve movie certifications. /certifications/tv: get: summary: Get TV certifications description: Returns list of TV show certifications from TMDB. tags: - other security: - cookieAuth: [] - apiKey: [] responses: '200': description: TV certifications returned content: application/json: schema: $ref: '#/components/schemas/CertificationResponse' '500': description: Unable to retrieve TV certifications content: application/json: schema: type: object properties: status: type: number example: 500 message: type: string example: Unable to retrieve TV certifications. /overrideRule: get: summary: Get override rules description: Returns a list of all override rules with their conditions and settings tags: - overriderule responses: '200': description: Override rules returned content: application/json: schema: type: array items: $ref: '#/components/schemas/OverrideRule' post: summary: Create override rule description: Creates a new Override Rule from the request body. tags: - overriderule requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/OverrideRuleWrite' responses: '200': description: 'Values were successfully created' content: application/json: schema: $ref: '#/components/schemas/OverrideRule' /overrideRule/{ruleId}: put: summary: Update override rule description: Updates an Override Rule from the request body. tags: - overriderule parameters: - in: path name: ruleId required: true schema: type: integer minimum: 1 maximum: 1000000000 requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/OverrideRuleWrite' responses: '200': description: 'Values were successfully updated' content: application/json: schema: $ref: '#/components/schemas/OverrideRule' delete: summary: Delete override rule by ID description: Deletes the override rule with the provided ruleId. tags: - overriderule parameters: - in: path name: ruleId required: true schema: type: integer minimum: 1 maximum: 1000000000 responses: '200': description: Override rule successfully deleted content: application/json: schema: $ref: '#/components/schemas/OverrideRule' /playlist/spotify/connect: get: summary: Start the Spotify connection flow description: | Requires an existing SeerrNG browser session (not just an API key). Redirects the browser to Spotify's OAuth authorization page so the signed-in user can grant SeerrNG read access to their playlists. tags: - playlist responses: '302': description: Redirect to Spotify's authorization page. headers: Location: schema: type: string format: uri '400': description: Spotify playlist integration is not configured, or the SeerrNG application URL is not set. content: application/json: schema: type: object properties: message: type: string example: 'Spotify playlist integration is not configured by an administrator.' '403': description: The request did not come from an authenticated browser session (e.g. it used an API key instead of a session cookie). content: application/json: schema: type: object properties: message: type: string example: 'A browser session is required.' /playlist/spotify/callback: get: summary: Handle the Spotify OAuth callback description: | The redirect target Spotify sends the browser back to after the user approves or denies access. Always redirects back to `/discover/music`, appending `?playlist=connected` on success or `?playlist=error` if the state/code could not be validated or the token exchange failed. Never returns a JSON error body. tags: - playlist parameters: - in: query name: state required: false schema: type: string description: Opaque anti-CSRF value echoed back from the authorization request. - in: query name: code required: false schema: type: string description: Authorization code issued by Spotify. responses: '302': description: Redirect back to /discover/music with a playlist=connected or playlist=error query parameter. headers: Location: schema: type: string format: uri /playlist/spotify/status: get: summary: Get the current user's Spotify connection status tags: - playlist responses: '200': description: Spotify connection status for the current user. content: application/json: schema: type: object properties: connected: type: boolean displayName: type: string nullable: true required: - connected - displayName /playlist/spotify/disconnect: post: summary: Disconnect the current user's Spotify account description: Removes the connected account's stored Spotify tokens from SeerrNG. tags: - playlist responses: '204': description: Spotify account disconnected. No response body. /playlist/resolve: post: summary: Resolve a playlist URL into matched music requests description: | Reads a Spotify or YouTube/YouTube Music playlist (at most 200 source tracks), matches its tracks to MusicBrainz release groups, and returns matched and unmatched candidates for review before they are submitted as music requests. Rate-limited to 10 requests per minute per client. Resolving a Spotify playlist requires the requesting user to have already connected Spotify via `/playlist/spotify/connect`. tags: - playlist requestBody: required: true content: application/json: schema: type: object properties: url: type: string description: A Spotify, YouTube, or YouTube Music playlist URL. example: 'https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M' required: - url responses: '200': description: Playlist read and matched successfully. content: application/json: schema: $ref: '#/components/schemas/PlaylistResolutionResponse' '400': description: The URL was not a supported playlist link, or the matching provider (Spotify/YouTube) is not configured, or the playlist had no importable tracks. content: application/json: schema: type: object properties: message: type: string example: 'Enter a supported Spotify or YouTube playlist URL.' '409': description: The requesting user has not connected Spotify yet. content: application/json: schema: type: object properties: message: type: string example: 'Connect Spotify before importing a Spotify playlist.' '502': description: The playlist could not be read or matched right now (upstream provider or MusicBrainz failure). content: application/json: schema: type: object properties: message: type: string example: 'The playlist could not be read or matched right now.' /playback/devices: get: summary: List active playback devices available to the current user tags: - playback responses: '200': description: Active playback devices. content: application/json: schema: type: array items: $ref: '#/components/schemas/PlaybackDevice' '502': description: Playback devices could not be retrieved. /playback/watched/{mediaType}/{tmdbId}: get: summary: Get the current user's watched status for a movie or series tags: - playback parameters: - in: path name: mediaType required: true schema: type: string enum: - movie - tv - in: path name: tmdbId required: true schema: type: integer minimum: 1 maximum: 1000000000 - in: query name: details required: false schema: type: string enum: - '1' responses: '200': description: Watched status for the current user and available media-server items. content: application/json: schema: $ref: '#/components/schemas/WatchStatusResponse' '404': description: The media type or TMDB ID is invalid. '502': description: Watched status could not be retrieved from the media server. /playback/media/{mediaId}: get: summary: Get the playable catalog for a media item tags: - playback parameters: - in: path name: mediaId required: true schema: type: integer minimum: 1 - in: query name: is4k required: false schema: type: boolean responses: '200': description: Playable catalog for the requested media item. content: application/json: schema: $ref: '#/components/schemas/PlaybackCatalogResponse' '403': description: Playback is not permitted for this user. '502': description: Playable media could not be retrieved. /playback/media/{mediaId}/play: post: summary: Start playback for selected items on a media-server device tags: - playback parameters: - in: path name: mediaId required: true schema: type: integer minimum: 1 requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/PlaybackCommand' responses: '204': description: Playback started. '400': description: The playback selection is invalid. '403': description: Playback is not permitted for this user. '404': description: The selected playback device is unavailable. '409': description: No media server is configured. '502': description: Playback could not be started. /playback/media/{mediaId}/playlist: post: summary: Replace the current user's media-server playlist with selected items tags: - playback parameters: - in: path name: mediaId required: true schema: type: integer minimum: 1 requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/PlaybackPlaylistCommand' responses: '200': description: Playlist replaced and ready to open. content: application/json: schema: $ref: '#/components/schemas/PlaybackPlaylistResponse' '400': description: The playlist selection is invalid. '403': description: Playback is not permitted for this user. '409': description: No media server is configured. '502': description: The media-server playlist could not be replaced. /playback/collection/play: post: summary: Start playback for selected collection movies tags: - playback requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CollectionPlaybackCommand' responses: '204': description: Collection playback started. '400': description: The collection playback selection is invalid. '403': description: Playback is not permitted for this user. '404': description: The selected playback device is unavailable. '409': description: No media server is configured. '502': description: Collection playback could not be started. /playback/collection/playlist: post: summary: Replace the current user's media-server playlist with selected collection movies tags: - playback requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CollectionPlaylistCommand' responses: '200': description: Playlist replaced and ready to open. content: application/json: schema: $ref: '#/components/schemas/PlaybackPlaylistResponse' '400': description: The collection playlist selection is invalid. '403': description: Playback is not permitted for this user. '409': description: No media server is configured. '502': description: The media-server playlist could not be replaced. /integrations/discovery/configuration: get: summary: Get discovery integration availability tags: - settings responses: '200': description: Integration response content: application/json: schema: $ref: '#/components/schemas/DiscoveryConfiguration' '400': description: Invalid request '401': description: Authentication required '403': description: Permission denied '409': description: Integration configuration or account state changed '429': description: Provider quota reached; retry later '502': description: Provider unavailable put: summary: Configure discovery integrations tags: - settings requestBody: required: true content: application/json: schema: type: object additionalProperties: false properties: trakt: type: object additionalProperties: false properties: clientId: type: string maxLength: 4096 clientSecret: type: string maxLength: 4096 anilist: type: object additionalProperties: false properties: clientId: type: string maxLength: 4096 clientSecret: type: string maxLength: 4096 simkl: type: object additionalProperties: false properties: clientId: type: string maxLength: 4096 mdblist: type: object additionalProperties: false properties: apiKey: type: string maxLength: 4096 responses: '200': description: Integration response content: application/json: schema: $ref: '#/components/schemas/DiscoveryConfiguration' '400': description: Invalid request '401': description: Authentication required '403': description: Permission denied '409': description: Integration configuration or account state changed '429': description: Provider quota reached; retry later '502': description: Provider unavailable /integrations/discovery/accounts: get: summary: Get your connected discovery accounts tags: - user responses: '200': description: Integration response content: application/json: schema: $ref: '#/components/schemas/DiscoveryAccounts' '400': description: Invalid request '401': description: Authentication required '403': description: Permission denied '409': description: Integration configuration or account state changed '429': description: Provider quota reached; retry later '502': description: Provider unavailable /integrations/discovery/accounts/{provider}: parameters: - name: provider in: path required: true schema: type: string enum: - trakt - anilist - simkl delete: summary: Disconnect your discovery account tags: - user responses: '204': description: Operation completed '400': description: Invalid request '401': description: Authentication required '403': description: Permission denied '409': description: Integration configuration or account state changed '429': description: Provider quota reached; retry later '502': description: Provider unavailable /integrations/discovery/accounts/{provider}/preferences: parameters: - name: provider in: path required: true schema: type: string enum: - trakt - anilist - simkl put: summary: Set personal tracking write consent tags: - user requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: - allowWrites properties: allowWrites: type: boolean responses: '204': description: Operation completed '400': description: Invalid request '401': description: Authentication required '403': description: Permission denied '409': description: Integration configuration or account state changed '429': description: Provider quota reached; retry later '502': description: Provider unavailable /integrations/discovery/accounts/{provider}/connect: parameters: - name: provider in: path required: true schema: type: string enum: - trakt - anilist - simkl post: summary: Begin connecting your discovery account tags: - user responses: '200': description: Integration response content: application/json: schema: type: object additionalProperties: true '400': description: Invalid request '401': description: Authentication required '403': description: Permission denied '409': description: Integration configuration or account state changed '429': description: Provider quota reached; retry later '502': description: Provider unavailable /integrations/discovery/accounts/{provider}/complete: parameters: - name: provider in: path required: true schema: type: string enum: - trakt - anilist - simkl post: summary: Complete your discovery account connection tags: - user requestBody: content: application/json: schema: type: object additionalProperties: false properties: code: type: string maxLength: 4096 responses: '200': description: Integration response content: application/json: schema: type: object additionalProperties: true '202': description: Authorization pending or rejected content: application/json: schema: type: object additionalProperties: true '400': description: Invalid request '401': description: Authentication required '403': description: Permission denied '409': description: Integration configuration or account state changed '429': description: Provider quota reached; retry later '502': description: Provider unavailable /integrations/discovery/feeds/{provider}/{feed}: get: summary: Browse provider discovery feeds tags: - discover parameters: - name: provider in: path required: true schema: type: string enum: - trakt - anilist - mdblist - name: feed in: path required: true schema: type: string enum: - watchlist - history - recommendations-movie - recommendations-tv - library - trending - popular - top - next-season - list - name: page in: query schema: type: integer minimum: 1 maximum: 100 - name: list in: query schema: type: string maxLength: 2048 responses: '200': description: A bounded provider feed page content: application/json: schema: $ref: '#/components/schemas/DiscoveryFeedPage' '400': description: Invalid feed '404': description: The requested public MDBList list could not be found content: application/json: schema: $ref: '#/components/schemas/DiscoveryProviderError' '409': description: Reconnect the account or configure MDBList content: application/json: schema: $ref: '#/components/schemas/DiscoveryProviderError' '429': description: Provider quota reached; wait for Retry-After before retrying headers: Retry-After: description: Minimum number of seconds before retrying, capped at one hour schema: type: integer minimum: 1 maximum: 3600 content: application/json: schema: $ref: '#/components/schemas/DiscoveryProviderError' '502': description: Provider unavailable content: application/json: schema: $ref: '#/components/schemas/DiscoveryProviderError' /integrations/discovery/library/{provider}: get: summary: Browse a page of your personal provider or media server library description: For Plex, Jellyfin, and Emby in-progress shelves, pass the previous response's nextCursor as cursor to continue a bounded scan. Other providers use page pagination. tags: - user parameters: - name: provider in: path required: true schema: type: string enum: [trakt, anilist, simkl, plex, jellyfin, emby] - name: shelf in: query schema: type: string enum: [ all, watchlist, watched, unwatched, in-progress, completed, rated, ] - name: page in: query schema: type: integer minimum: 1 maximum: 500 default: 1 - name: cursor in: query description: Cursor returned by the prior media-server in-progress page. schema: type: integer minimum: 0 maximum: 100000 - name: mediaType in: query schema: type: string enum: [movie, tv] - name: libraryId in: query schema: type: string maxLength: 128 responses: '200': description: A bounded page from the current user's personal library content: application/json: schema: $ref: '#/components/schemas/PersonalLibraryPage' '400': description: Invalid library shelf or page '403': description: Browser session or media permission required '409': description: Provider account needs to be connected '429': description: Provider quota reached; retry later '502': description: Provider unavailable /integrations/discovery/library/{provider}/repair: post: summary: Save exact external-ID matches across bounded provider-library pages description: Scans up to five pages per request. Only unique confirmed IMDb or TVDB matches are stored as private user mappings; existing personal or curated matches are not overwritten. tags: - user parameters: - name: provider in: path required: true schema: type: string enum: [trakt, anilist, simkl] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ProviderLibraryRepairRequest' responses: '200': description: Completed bounded provider-library identity scan content: application/json: schema: $ref: '#/components/schemas/ProviderLibraryRepairResult' '400': description: Invalid provider, shelf, or scan range '403': description: Browser session or media permission required '409': description: Provider account needs to be connected '429': description: Provider or scan quota reached; continue later '502': description: Provider unavailable /integrations/discovery/mappings: put: summary: Match a personal library item to a TMDB title tags: - user requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/DiscoveryIdentityMappingRequest' responses: '200': description: Personal title match saved content: application/json: schema: $ref: '#/components/schemas/DiscoveryIdentityMapping' '400': description: Invalid library identity or TMDB match '403': description: Browser session or enabled media category required '409': description: Source account is disconnected or the mapping limit was reached '429': description: Mapping update rate limit reached '502': description: TMDB could not confirm the selected title /integrations/discovery/mappings/pack: get: summary: Export the current user's private title matches tags: - user responses: '200': description: Versioned personal title-match pack without provider credentials content: application/json: schema: $ref: '#/components/schemas/PersonalIdentityMappingPack' '403': description: Browser session required post: summary: Import a versioned pack of private title matches tags: - user requestBody: required: true content: text/plain: schema: type: string maxLength: 5242880 description: UTF-8 JSON text containing a PersonalIdentityMappingPack responses: '200': description: Imported, updated, and unchanged mapping totals content: application/json: schema: $ref: '#/components/schemas/PersonalIdentityMappingPackImportResult' '400': description: Invalid or unsupported pack '403': description: Browser session required '409': description: Per-user saved title-match limit reached '413': description: Pack exceeds the 5 MiB upload limit '429': description: Pack import rate limit reached /integrations/discovery/mappings/packs: get: summary: List administrator-managed title-match packs shared by all accounts tags: - admin responses: '200': description: Shared mapping-pack names, update times, and entry counts content: application/json: schema: $ref: '#/components/schemas/CuratedIdentityPackList' '403': description: Administrator permission required post: summary: Import or replace an administrator-managed shared title-match pack tags: - admin requestBody: required: true content: text/plain: schema: type: string maxLength: 5242880 description: UTF-8 JSON text containing a CuratedIdentityMappingPack responses: '200': description: Shared entries imported, updated, retained, or removed content: application/json: schema: $ref: '#/components/schemas/CuratedIdentityPackImportResult' '400': description: Invalid or unsupported pack '403': description: Administrator permission and browser session required '409': description: Another shared pack owns one of these provider identities or the pack limit is reached '413': description: Pack exceeds the 5 MiB upload limit '429': description: Shared pack import rate limit reached /integrations/discovery/mappings/packs/{packId}: get: summary: Export an administrator-managed shared title-match pack tags: - admin parameters: - name: packId in: path required: true schema: type: string minLength: 1 maxLength: 64 pattern: '^[a-z0-9](?:[a-z0-9-]{0,62}[a-z0-9])?$' responses: '200': description: Versioned shared pack without provider credentials content: application/json: schema: $ref: '#/components/schemas/CuratedIdentityMappingPack' '403': description: Administrator permission required '404': description: Shared pack not found delete: summary: Delete a shared title-match pack for every account tags: - admin parameters: - name: packId in: path required: true schema: type: string minLength: 1 maxLength: 64 pattern: '^[a-z0-9](?:[a-z0-9-]{0,62}[a-z0-9])?$' responses: '200': description: Shared pack removed content: application/json: schema: type: object additionalProperties: false required: [removed] properties: removed: type: boolean enum: [true] '403': description: Administrator permission and browser session required '404': description: Shared pack not found '429': description: Shared pack modification rate limit reached /integrations/discovery/mappings/{identity}: delete: summary: Remove a personal library title match tags: - user parameters: - name: identity in: path required: true schema: type: string minLength: 3 maxLength: 256 responses: '200': description: Mapping removed, if present content: application/json: schema: type: object additionalProperties: false required: [removed] properties: removed: type: boolean '400': description: Invalid library identity '403': description: Browser session required '409': description: Source account is disconnected '429': description: Mapping update rate limit reached /integrations/discovery/tracking/{provider}: post: summary: Update watched status, progress, or rating in your linked account tags: - user parameters: - name: provider in: path required: true schema: type: string enum: [trakt, anilist, simkl] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/DiscoveryTrackingRequest' responses: '200': description: Provider confirmed the tracking action content: application/json: schema: $ref: '#/components/schemas/DiscoveryTrackingAction' '400': description: Invalid title or tracking value '403': description: Browser session, permission, or explicit write consent required '409': description: Account changed or a previous action has an uncertain outcome '429': description: Provider quota reached; retry later '502': description: Provider did not confirm the action /integrations/discovery/tracking/{provider}/episodes: get: summary: Read watched status for one show's episodes in your linked account tags: - user parameters: - name: provider in: path required: true schema: type: string enum: [trakt, simkl] - name: sourceId in: query required: true schema: type: string pattern: '^[1-9][0-9]{0,9}$' - name: tmdbId in: query required: true schema: type: integer minimum: 1 maximum: 2147483647 - name: season in: query required: true schema: type: integer minimum: 0 maximum: 10000 responses: '200': description: Provider watch state for the selected series season content: application/json: schema: $ref: '#/components/schemas/ProviderEpisodeWatchState' '400': description: Invalid provider title or season '403': description: Browser session or enabled series category required '409': description: Provider account needs reconnection or the catalog identity changed '429': description: Episode watch-state lookup rate limit reached '502': description: Provider or catalog unavailable /integrations/discovery/tracking/actions/{requestId}: get: summary: Check the outcome of one of your tracking actions tags: - user parameters: - name: requestId in: path required: true schema: type: string format: uuid responses: '200': description: Current user's tracking action state content: application/json: schema: $ref: '#/components/schemas/DiscoveryTrackingAction' '403': description: Browser session required '404': description: Tracking action not found /calendar: get: summary: Browse releases for your requests and shared acquisition services tags: - discover parameters: - name: start in: query schema: type: string pattern: ^\d{4}-\d{2}-\d{2}$ - name: end in: query schema: type: string pattern: ^\d{4}-\d{2}-\d{2}$ - name: scope in: query schema: type: string enum: - mine - all default: mine - name: mediaType in: query schema: type: string enum: - movie - tv - music - book - comic - magazine - software - name: includeUnmonitored in: query schema: type: boolean default: false - name: timeZone in: query schema: type: string maxLength: 64 default: UTC description: >- IANA time zone for episode month boundaries; all-day movie, album, book, comic, magazine, and game releases retain their calendar dates. responses: '200': description: Release calendar with unavailable sources indicated content: application/json: schema: type: object required: - results - partialSources - truncated properties: results: type: array maxItems: 5000 items: type: object required: - id - source - mediaType - title - startsAt - dateType - allDay - available - is4k properties: id: type: string source: type: string enum: - radarr - sonarr - lidarr - readarr - mylar - kapowarr - lazylibrarian - questarr - romarr mediaType: type: string enum: - movie - tv - music - book - comic - magazine - software title: type: string startsAt: type: string format: date-time dateType: type: string enum: - air - digital - physical - theatrical - album - book - issue - game allDay: type: boolean tmdbId: type: integer tvdbId: type: integer mbId: type: string artistName: type: string bookId: type: string description: Service-scoped Bookshelf ID suitable for the book details route. foreignBookId: type: string description: Provider-native Readarr-compatible book identity used for personal request matching. foreignEditionId: type: string description: Provider-native edition identity used for personal request matching. isbnCandidates: type: array maxItems: 24 items: type: string description: Public ISBN identities available from Readarr book editions, used for matching personal requests. bookFormat: type: string enum: - ebook - audiobook authorName: type: string comicId: type: string description: ComicVine identity suitable for the comic details route. magazineTitle: type: string description: LazyLibrarian magazine title suitable for the magazine details route. issueNumber: type: string softwareCategory: type: string enum: - game - retro - modern igdbId: type: integer platformName: type: string description: Requested PC target or emulation system. seasonNumber: type: integer episodeNumber: type: integer episodeTitle: type: string available: type: boolean is4k: type: boolean dateChanges: type: array maxItems: 3 description: Recent provider date or air-time changes captured by the background calendar history job. items: type: object required: - previousStartsAt - startsAt - changedAt - previousAllDay - allDay properties: previousStartsAt: type: string format: date-time startsAt: type: string format: date-time changedAt: type: string format: date-time previousAllDay: type: boolean allDay: type: boolean partialSources: type: array items: type: object properties: source: type: string serverId: type: integer truncated: type: boolean '400': description: Invalid calendar range or filters '403': description: Calendar scope not permitted '502': description: Calendar unavailable /downloads/interventions: get: tags: - Downloads summary: List download warnings or action history description: Requires Manage Downloads permission. Admins have this permission automatically. parameters: - in: query name: scope schema: type: string enum: - active - history default: active - in: query name: page schema: type: integer minimum: 1 maximum: 1000 default: 1 responses: '200': description: Download intervention result content: application/json: schema: type: object additionalProperties: false required: - results - total - page - partialSources - truncated properties: results: type: array items: $ref: '#/components/schemas/QueueIntervention' total: type: integer page: type: integer minimum: 1 partialSources: type: array items: type: object properties: serviceType: type: string serviceId: type: integer truncated: type: boolean '400': description: Invalid input '403': description: Download management permission required '409': description: Download or backend changed; refresh before retrying '502': description: Backend unavailable /downloads/interventions/{id}/preview: get: tags: - Downloads summary: Preview files for a confirmed library match description: Requires Manage Downloads permission. Admins have this permission automatically. parameters: - in: path name: id required: true schema: type: integer minimum: 1 - in: query name: targetId required: false description: Existing movie, series, album, or book ID from this backend's library schema: type: integer minimum: 1 maximum: 2147483647 responses: '200': description: Download intervention result content: application/json: schema: type: object additionalProperties: false required: - target - candidates - fingerprint properties: target: type: object nullable: true additionalProperties: false required: - id - title - subtitle properties: id: type: integer minimum: 1 title: type: string subtitle: type: string candidates: type: array items: type: object additionalProperties: false required: - id - name - size - rejections - eligible properties: id: type: integer minimum: 1 name: type: string size: type: number rejections: type: array items: type: string eligible: type: boolean fingerprint: type: string pattern: ^[a-f0-9]{64}$ '400': description: Invalid input '403': description: Download management permission required '409': description: Download or backend changed; refresh before retrying '502': description: Backend unavailable /downloads/interventions/{id}/targets: get: tags: - Downloads summary: Search existing manual-import targets in the acquisition library description: Searches titles already tracked by the selected acquisition service. This does not add media to that service. Requires Manage Downloads permission. Admins have this permission automatically. parameters: - in: path name: id required: true schema: type: integer minimum: 1 - in: query name: query required: true schema: type: string minLength: 2 maxLength: 120 responses: '200': description: Existing import targets content: application/json: schema: type: array maxItems: 20 items: type: object additionalProperties: false required: - id - title - subtitle properties: id: type: integer minimum: 1 title: type: string subtitle: type: string '400': description: Invalid search input '403': description: Download management permission required '409': description: Download or backend changed; refresh before retrying '502': description: Backend unavailable /downloads/interventions/{id}/reject: post: tags: - Downloads summary: Reject a download with explicit client removal and blocklist choices description: Requires Manage Downloads permission. Admins have this permission automatically. parameters: - in: path name: id required: true schema: type: integer minimum: 1 responses: '200': description: Download intervention result content: application/json: schema: $ref: '#/components/schemas/QueueIntervention' '400': description: Invalid input '403': description: Download management permission required '409': description: Download or backend changed; refresh before retrying '502': description: Backend unavailable requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: - blocklist - removeFromClient properties: blocklist: type: boolean removeFromClient: type: boolean /downloads/interventions/{id}/import: post: tags: - Downloads summary: Submit selected files for import and track backend confirmation description: Requires Manage Downloads permission. Admins have this permission automatically. parameters: - in: path name: id required: true schema: type: integer minimum: 1 responses: '200': description: Download intervention result content: application/json: schema: $ref: '#/components/schemas/QueueIntervention' '400': description: Invalid input '403': description: Download management permission required '409': description: Download or backend changed; refresh before retrying '502': description: Backend unavailable requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: - candidateIds - importMode - fingerprint properties: candidateIds: type: array minItems: 1 maxItems: 50 uniqueItems: true items: type: integer minimum: 1 fingerprint: type: string pattern: ^[a-f0-9]{64}$ importMode: type: string enum: - copy - move targetId: type: integer minimum: 1 maximum: 2147483647 security: - cookieAuth: [] - apiKey: []