Skip to main content

Admin API

All paths are relative to the /api mount. Admin controllers are annotated with @Security("BearerAuth") for OpenAPI.

Auth legend

  • Admin – requireAdmin: admin session JWT or an API key owned by an admin.
  • Admin session – requireAdminSession: real admin login only; API keys are rejected.

Overview – /admin/overview​

MethodPathAuthPurpose
GET/admin/overviewAdminDashboard aggregate (src/api/overview/overviewService.ts): counts (movies, series, episodes, albums, tracks, users), per-library items/sizeBytes, storage (used bytes + disks of the media roots via statfs, roots on the same disk merged), last 10 activity entries from watch_progress, and server (hostname, version, Node, OS, uptime, streamer and indexer reachability).

Media libraries – /admin/media-libraries​

MethodPathAuthPurpose
GET/admin/media-librariesAdminList libraries with folder availability.
GET/admin/media-libraries/rootsAdminList media roots ({id, name, path}).
GET/admin/media-libraries/browse?rootId=&path=AdminList sub-folders of a root path.
POST/admin/media-librariesAdminCreate {name, type, imageStorage?, folders[1..50]}. 409 duplicate name.
PATCH/admin/media-libraries/:idAdminUpdate any of the above.
DELETE/admin/media-libraries/:idAdminDelete (204).

Media items & subtitles – /admin/media​

MethodPathAuthPurpose
GET/admin/media/items?libraryId&type&parentId&search&page&sizeAdminPaged item list.
GET/admin/media/items/:idAdminItem with full metadata.
PATCH/admin/media/items/:idAdminEdit title, sortTitle, year, seasonNumber, episodeNumber, episodeEndNumber, overview.
DELETE/admin/media/items/:idAdminRemove item.
GET/admin/media/items/:id/images/:indexAdminImage bytes.
POST/admin/media/items/:id/images?type=AdminUpload image (multipart image, ≤ 15 MB).
DELETE/admin/media/items/:id/images/:indexAdminDelete image.
GET/admin/media/items/:id/subtitlesAdminList subtitle tracks ({tracks, configured}).
POST/admin/media/items/:id/subtitles/searchAdminSearch OpenSubtitles {query?, languages?}.
POST/admin/media/items/:id/subtitles/downloadAdminDownload {fileId, language}.
DELETE/admin/media/items/:id/subtitles?file=AdminDelete a subtitle file.

Indexer – /admin/indexer​

MethodPathAuthPurpose
GET/admin/indexer/statusAdmin{reachable, scans, queues, concurrency, maxConcurrency, enabledProviders}.
POST/admin/indexer/libraries/:id/scanAdminStart a scan; body {force?: boolean} re-reads everything.
POST/admin/indexer/refreshAdminRefresh one item {libraryId, path, itemType}.
GET/admin/indexer/tasks?queue&state&page&sizeAdminList queue tasks; state ∈ pending, active, scheduled, retry, archived, completed.
POST/admin/indexer/tasks/:queue/:id/cancelAdminCancel a task.
POST/admin/indexer/tasks/:queue/:id/retryAdminRetry a task.
POST/admin/indexer/queues/:queue/pauseAdminPause a queue.
POST/admin/indexer/queues/:queue/resumeAdminResume a queue.
PUT/admin/indexer/concurrencyAdminSet workers per queue, e.g. {"identify": 8} (1–64); persisted in indexer_concurrency.

Valid queues: scan, identify, metadata, images, probe, refresh (otherwise 404). An unreachable indexer yields 503.

The indexer-facing signed endpoints (/indexer/*) are listed in the API reference.

Streams – /admin/streams​

MethodPathAuthPurpose
GET/admin/streamsAdminStreamer sessions + transcodingAvailable, maxTranscodes, activeTranscodes.
DELETE/admin/streams/:sessionIdAdminStop a playback session (204, 404 if already ended).

Devices – /admin/devices​

MethodPathAuthPurpose
GET/admin/devicesAdmin sessionAll signed-in sessions as devices (parsed user agent, IP, last seen, current flag).
DELETE/admin/devices/:idAdmin sessionSign a device out (204); your own current device is refused.

Network shares – /admin/network-shares​

MethodPathAuthPurpose
GET/admin/network-sharesAdminList shares with status.
POST/admin/network-sharesAdminCreate and connect an SMB share.
PATCH/admin/network-shares/:idAdminUpdate; reconnects, rolls back on failure.
POST/admin/network-shares/:id/reconnectAdminRetry the connection.
DELETE/admin/network-shares/:idAdminUnmount/delete; 409 if a library uses it.

Users – /admin/users​

MethodPathAuthPurpose
GET/admin/usersAdmin sessionList users.
POST/admin/usersAdmin sessionCreate a user (409 duplicate username/e-mail).
PATCH/admin/users/:idAdmin sessionUpdate displayName, email, role, disabled. You cannot change your own role or disable yourself.
POST/admin/users/:id/avatarAdmin sessionSet avatar (multipart).
DELETE/admin/users/:id/avatarAdmin sessionRemove avatar.
PUT/admin/users/:id/passwordAdmin sessionSet a password (204).
DELETE/admin/users/:id/sessionsAdmin sessionRevoke the user's sessions ({revoked}).
DELETE/admin/users/:idAdmin sessionDelete (204); not yourself.

API keys – /admin/api-keys​

MethodPathAuthPurpose
GET/admin/api-keysAdmin sessionList keys (name, prefix, dates – never the secret).
POST/admin/api-keysAdmin sessionCreate {name}; the full key is returned once.
DELETE/admin/api-keys/:idAdmin sessionRevoke (204).

Settings and e-mail​

MethodPathAuthPurpose
GET/settingsBearerAll settings for admins, only public ones for others (secrets masked).
PUT/settings/:keyAdminUpdate a setting (404 unknown key). Validated per key; SMTP changes reset the mailer, Sentry changes re-apply, indexer keys trigger an indexer reload.
POST/settings/email/testAdmin sessionSend a test e-mail.

Jobs – /jobs (pg-boss)​

All Admin. Only the queue cleanup-expired-user-sessions (cron 0 * * * *) is currently supported.

MethodPathPurpose
GET/jobs/queuesQueue stats.
GET/jobs/queues/:queueName/jobs?limit=List jobs (limit 1–1000).
GET/jobs/queues/:queueName/jobs/:jobIdJob detail.
POST/jobs/queues/:queueName/jobsEnqueue a job.
POST/jobs/queues/:queueName/jobs/:jobId/retryRetry.
DELETE/jobs/queues/:queueName/jobs/:jobIdDelete.
GET/jobs/schedulesList schedules.
PUT/jobs/schedules/:queueNameSet schedule {cron, data}.
DELETE/jobs/schedules/:queueNameRemove schedule.

Logs​

The live log feed is a WebSocket (/api/logs/stream, admin) – see Real-time. There is no REST log endpoint.

Real-time companion​

Most dashboard data above is also pushed over /api/live (Real-time).