Skip to content

Jellyfin Enhanced's API

Jellyfin Enhanced adds features like Bookmarks and User Reviews/Ratings that live entirely in this plugin, not in Jellyfin Server itself. A user of any other Jellyfin client (Wholphin, Streamyfin, Afinity, a custom app, etc.) only gets these features if that client talks to the endpoints on this page directly, over plain HTTP with a Jellyfin token or API key. No client-side plugin, SDK, or Jellyfin Enhanced code is required, just an HTTP client and the request shapes documented below.

Requirements before any of this works:

  • The Jellyfin Enhanced plugin must be installed and enabled on the target server
  • Your app needs a Jellyfin auth token (per-user, from that user logging in) or a server API key, exactly as it would for any other Jellyfin Server request. See Quick Start below for how to get one and which calls need which
  • Bookmarks and Reviews both use TMDB IDs, not Jellyfin item IDs, to key data server-side (bookmarks also take an itemId when adding one, see Bookmarks API endpoints)

What this lets a client build, using only these HTTP endpoints:

  • A "bookmark this moment" button on the video player, and a bookmarks list/library screen (see Bookmarks API)
  • Star ratings and written reviews on a movie/show/season/episode details page, shared across every user on the server (see Reviews API)

Jellyfin 10.11 vs 12: the auth header that works is not the same

This plugin builds one identical set of endpoints for both Jellyfin 10.11 and 12, so the request/response shapes on this page don't change between server versions, only which auth header Jellyfin Server itself accepts does. Confirmed live against both a 10.11.11 and a 12.0.0 server:

  • X-Emby-Token and X-Emby-Authorization work on Jellyfin 10.11
  • On Jellyfin 12, both of the above are rejected by default (401/400) — Jellyfin 12 ships with ServerConfiguration.EnableLegacyAuthorization off, and a server-side migration force-disables it even on servers upgraded from 10.x
  • Authorization: MediaBrowser Token="..." (and, for the one pre-login call below, Authorization: MediaBrowser Client="...", Device="...", DeviceId="...", Version="...") works on both versions, unaffected by that setting

A client that only wants to support one code path, rather than detecting the server version and switching headers, should always send Authorization, never X-Emby-Token/X-Emby-Authorization alone. Some examples below still show X-Emby-Token because that's what a plain server API key traditionally uses; substitute Authorization: MediaBrowser Token="{apiKeyOrUserToken}" for the same call if the target server might be running Jellyfin 12.

/JellyfinEnhanced

Check version

/JellyfinEnhanced/version

Bash
curl -X GET \
  "JELLYFIN_SERVER_URL/JellyfinEnhanced/version"
  • Jellyfin Server URL (JELLYFIN_URL)

Quick Start: Normal User vs Admin

There are two distinct ways to call the Bookmarks and Reviews endpoints below, depending on who is calling and whose data they are touching.

As a normal user, your own data only

Log in as that user to get a per-user access token, then use that token in Authorization: MediaBrowser Token="..." for every call. With this token you can only read or write your own bookmarks and your own review, never another user's.

How do I get JELLYFIN_USER_ACCESS_TOKEN?

Call Jellyfin's own POST /Users/AuthenticateByName with that user's username and password. This is not a Jellyfin Enhanced endpoint, it is part of Jellyfin Server's own API.

Bash
curl -X POST \
  -H 'Content-Type: application/json' \
  -H 'Authorization: MediaBrowser Client="MyApp", Device="MyApp", DeviceId="my-app-1", Version="1.0.0"' \
  -d '{"Username": "JELLYFIN_USERNAME", "Pw": "JELLYFIN_PASSWORD"}' \
  'JELLYFIN_SERVER_URL/Users/AuthenticateByName'

A client-identification header (Client, Device, DeviceId, Version, any values that identify your app) is required here, Jellyfin rejects the request without it even though no token exists yet at this point. Use the Authorization header for it, not X-Emby-Authorization: confirmed live against a Jellyfin 12 server, X-Emby-Authorization alone gets a bare 400 Error processing request there, because Jellyfin 12 disables the legacy X-Emby-*/X-MediaBrowser-* header family by default (ServerConfiguration.EnableLegacyAuthorization). Authorization: MediaBrowser ... is never gated by that setting, on 10.11 or 12, so it is the one header name safe to hard-code in a client.

The response body includes an AccessToken field, that is JELLYFIN_USER_ACCESS_TOKEN. It does not expire on its own, it stays valid until the user signs out or an admin revokes it from the Jellyfin Dashboard.

Alternatively, Quick Connect gets a token without the app ever handling the user's password.

  • Post your own review: POST /JellyfinEnhanced/reviews/{mediaType}/{tmdbId}
  • Delete your own review: DELETE /JellyfinEnhanced/reviews/{mediaType}/{tmdbId}
  • Add a bookmark for yourself: POST /JellyfinEnhanced/user-settings/{yourUserId}/bookmark.json/add
  • Remove a bookmark for yourself: DELETE /JellyfinEnhanced/user-settings/{yourUserId}/bookmark.json/{bookmarkId}

As an admin, any user's data

Generate a server API key from the Jellyfin Dashboard (Settings > API Keys), created by an Administrator account. Use that key in X-Emby-Token (Reviews) or Authorization: MediaBrowser Token="..." (Bookmarks), and put the target user's ID directly in the URL. This is the pattern a 3rd-party app should use to manage bookmarks and reviews for every user with a single credential, with no per-user login required.

  • Post a review as a specific user: POST /JellyfinEnhanced/reviews/admin/{userIdN}/{mediaType}/{tmdbId}
  • Delete a specific user's review: DELETE /JellyfinEnhanced/reviews/admin/{userIdN}/{mediaType}/{tmdbId}
  • Add a bookmark for a specific user: POST /JellyfinEnhanced/user-settings/{userId}/bookmark.json/add
  • Remove a bookmark for a specific user: DELETE /JellyfinEnhanced/user-settings/{userId}/bookmark.json/{bookmarkId}

A non-admin token used against another user's {userId} is rejected. Full request and response details for every endpoint are below.

Ratings vs. text reviews

{tmdbId} in every Reviews endpoint above also accepts {tmdbId}:s{season} or {tmdbId}:s{season}:e{episode}, so a TV show can carry its own review plus separate ones per season/episode. A review's rating (1-5) and content are independent: send rating alone for a star-rating-only UI, content alone for text-only, or both. See Rating and content rules in the Reviews API section.

Bookmarks API

New in v11.13.0.0

The additive bookmark.json/add and bookmark.json/{bookmarkId} endpoints below, and admin access to any user's bookmarks via a server API key, are new in v11.13.0.0. Earlier versions only support reading or replacing the whole file with a per-user access token.

Bookmarks Storage Directory

Bookmarks are stored as bookmark.json (singular), inside a folder named after the user's ID, under the plugin's own configuration directory:

bookmark.json
{JELLYFIN_DATA_DIR}/plugins/configurations/Jellyfin.Plugin.JellyfinEnhanced/JELLYFIN_USER_ID/bookmark.json

JELLYFIN_USER_ID here is the user's GUID with hyphens stripped and lowercased (e.g. 9285e8b541494149...), regardless of the casing or format used in the URL.

userID? JELLYFIN_USER_ID?

userID is Jellyfin Server's unique ID for each user

JELLYFIN_USER_ID is a placeholder for the user's userID


Reference:

Jellyfin's API documentation on /Users

Tip

A simple way to find which userID belongs to which user:

  • Jellyfin Dashboard: Users
  • Click a user's profile
  • The userID for that user appears in the URL. For example: 9285e8b54149414941494edb9e464dcd in the URL http://localhost:8096/#/dashboard/users/profile?userId=9285e8b54149414941494edb9e464dcd
bookmark.json: Example Data structure
{
  "Bookmarks": {
    "unique-bookmark-id": {
      "ItemId": "jellyfin-item-id",
      "TmdbId": "12345",
      "TvdbId": "67890",
      "MediaType": "movie" | "tv",
      "Name": "Item Name",
      "Timestamp": 123.45,
      "Label": "Epic scene",
      "CreatedAt": "2026-01-03T12:00:00.000Z",
      "UpdatedAt": "2026-01-03T12:00:00.000Z",
      "SyncedFrom": "original-item-id"
    }
  }
}

Field casing is PascalCase, except on add

The Get, Replace-all, and Remove endpoints below all read/write BookmarkItem fields in PascalCase (ItemId, TmdbId, MediaType, Timestamp, ...) as shown above — confirmed against a live server, not just the source. The one exception is the Add one Bookmark endpoint: its request body accepts either casing (ASP.NET Core's model binder is case-insensitive), but its own success response is a separate small object using camelCase ({"success": true, "id": "..."}). Don't assume one casing convention across every Bookmarks endpoint.

Authentication: two ways to call these

  • As the user themselves: pass a per-user access token (obtained by that user logging in) in Authorization: MediaBrowser Token="...". Works for the user's own JELLYFIN_USER_ID only.
  • As an admin, for any user: pass a server Administrator API key. The plugin will let an Administrator key act on any JELLYFIN_USER_ID, which is what lets a 3rd-party app manage bookmarks for every user with a single credential.

A non-admin user calling with someone else's JELLYFIN_USER_ID is rejected.

Bookmarks API endpoints

bookmark.json is one of several per-user settings files served under /user-settings/{userId}/{file} (the same pattern covers settings.json, shortcuts.json, elsewhere.json, and hidden-content.json).

Get Bookmarks

/JellyfinEnhanced/user-settings/{userId}/bookmark.json

Bash
curl -X GET \
  -H 'Authorization: MediaBrowser Token="JELLYFIN_TOKEN"' \
  'JELLYFIN_SERVER_URL/JellyfinEnhanced/user-settings/JELLYFIN_USER_ID/bookmark.json'
GET /JellyfinEnhanced/user-settings/JELLYFIN_USER_ID/bookmark.json
Authorization: MediaBrowser Token="JELLYFIN_TOKEN"
  • JELLYFIN_TOKEN: a per-user access token for JELLYFIN_USER_ID, or an Administrator API key
  • Jellyfin Server URL JELLYFIN_SERVER_URL

Returns the bookmark.json contents directly, not wrapped. An empty {"Bookmarks": {}} if the user has none yet.

Replace all Bookmarks

/JellyfinEnhanced/user-settings/{userId}/bookmark.json

Overwrites the whole file. Use the additive endpoint below instead if you only want to add or remove one bookmark.

Bash
curl -X POST \
  -H 'Content-Type: application/json' \
  -H 'Authorization: MediaBrowser Token="JELLYFIN_TOKEN"' \
  -d '{
        "Bookmarks": {}
      }' \
  'JELLYFIN_SERVER_URL/JellyfinEnhanced/user-settings/JELLYFIN_USER_ID/bookmark.json'
POST /JellyfinEnhanced/user-settings/JELLYFIN_USER_ID/bookmark.json
Authorization: MediaBrowser Token="JELLYFIN_TOKEN"
Content-Type: application/json

{ "Bookmarks": { ... } }
  • JELLYFIN_TOKEN: a per-user access token for JELLYFIN_USER_ID, or an Administrator API key
  • Jellyfin Server URL JELLYFIN_SERVER_URL
  • The request body is the raw bookmarks object itself, not wrapped in { "fileName": ..., "data": ... }. Each bookmark item's fields are PascalCase (ItemId, TmdbId, MediaType, Timestamp, Label, ...), matching the Example Data structure above.
Add one Bookmark

/JellyfinEnhanced/user-settings/{userId}/bookmark.json/add

Adds a single bookmark without touching the rest of the file. The server generates the bookmark ID and timestamps and returns the new ID.

Bash
curl -X POST \
  -H 'Content-Type: application/json' \
  -H 'Authorization: MediaBrowser Token="JELLYFIN_TOKEN"' \
  -d '{
        "itemId": "jellyfin-item-id",
        "tmdbId": "1949",
        "mediaType": "movie",
        "name": "Zodiac",
        "timestamp": 1234.5,
        "label": "Great scene"
      }' \
  'JELLYFIN_SERVER_URL/JellyfinEnhanced/user-settings/JELLYFIN_USER_ID/bookmark.json/add'
  • JELLYFIN_TOKEN: a per-user access token for JELLYFIN_USER_ID, or an Administrator API key
  • itemId is required. tmdbId, tvdbId, mediaType, name, timestamp, label, and syncedFrom are all optional.

Response: {"success": true, "id": "Bm_1234567890_abc123xyz"}

Remove one Bookmark

/JellyfinEnhanced/user-settings/{userId}/bookmark.json/{bookmarkId}

Bash
curl -X DELETE \
  -H 'Authorization: MediaBrowser Token="JELLYFIN_TOKEN"' \
  'JELLYFIN_SERVER_URL/JellyfinEnhanced/user-settings/JELLYFIN_USER_ID/bookmark.json/BOOKMARK_ID'
  • BOOKMARK_ID is the ID returned by the add endpoint, or a key from the Bookmarks object returned by the get endpoint
  • Returns 404 with {"success": false, "removed": false} if no bookmark with that ID exists

Reviews API

New in v11.13.0.0

Admin access to any user's reviews via a server API key is new in v11.13.0.0. Earlier versions only support reading reviews or writing your own review with a per-user access token.

User reviews and ratings, shared across all users on the server. Each review is a content string and an optional 1-5 star rating, keyed by author + item, and reviews for one item are stored together in a single shared reviews.json (not a per-user file). This is the API to use if you want to build star ratings, review lists, or an average-rating badge for a client.

Rating and content rules

Every write endpoint below (self or admin) validates the same ReviewPayload body:

  • content (string, optional): trimmed server-side; rejected with 400 if longer than 2000 characters
  • rating (number, optional): must be 1-5 inclusive in 0.5 increments (e.g. 4.5), or omitted; 0, 6, or a value not on a half-star boundary (e.g. 4.3) is rejected with 400
  • At least one of content or rating must be present, an empty payload ({}) is rejected with 400 {"success": false, "message": "A rating or review text is required."}
  • This means a ratings-only review ({"rating": 4}, no text) and a text-only review ({"content": "..."}, no rating) are both valid

Reviewing a season or episode of a TV show

{tmdbId} in the URL is not just the bare TMDB ID, it also accepts two extended forms so a single mediaType: tv item can carry separate reviews per season or per episode:

  • {tmdbId} — the show as a whole, e.g. 1399
  • {tmdbId}:s{season} — a specific season, e.g. 1399:s1
  • {tmdbId}:s{season}:e{episode} — a specific episode, e.g. 1399:s1:e1

Any other shape (letters, missing digits, extra segments) is rejected with 400 {"message": "Invalid TmdbId."}. mediaType must always be movie or tv, both movie:s1 and any mediaType other than movie/tv are rejected the same way. URL-encode the colons (%3A) if your HTTP client doesn't do it for you.

Get reviews for an item

/JellyfinEnhanced/reviews/{mediaType}/{tmdbId}

Bash
curl -X GET \
  -H "X-Emby-Token: JELLYFIN_API_KEY" \
  "JELLYFIN_SERVER_URL/JellyfinEnhanced/reviews/movie/TMDB_ID"
  • Jellyfin Server API key (JELLYFIN_API_KEY)
  • mediaType: movie or tv
  • TMDB_ID: the item's TMDB ID, or one of the season/episode forms above

A plain API key is enough to read reviews, there is no per-user identity involved here. Any authenticated caller (per-user token or API key) sees every non-hidden reviewer's review; an admin caller always sees every review, including ones from hidden or disabled authors, for moderation.

Response:

200 OK
{
  "reviews": [
    {
      "userId": "9285e8b541494149...",
      "userName": "alice",
      "tmdbId": "TMDB_ID",
      "mediaType": "movie",
      "content": "Great movie!",
      "rating": 5,
      "createdAt": "2026-01-03T12:00:00.000Z",
      "updatedAt": "2026-01-03T12:00:00.000Z"
    }
  ]
}
  • reviews is [], never missing, when nobody has reviewed the item yet
  • rating is omitted from the object entirely for a text-only review, it is not present as rating: null. Check "rating" in review (or the equivalent in your language) rather than a null check if you need to tell "no rating given" apart from "rated 0". content behaves differently: a rating-only review still gets content: "" rather than omitting the key
  • Average rating and review count are not pre-computed by the server, a client wanting those should reduce over the rating field of the returned array itself, skipping entries where the key is absent
Add or edit your own review

/JellyfinEnhanced/reviews/{mediaType}/{tmdbId}

Creates your review if you don't have one for this item yet, or updates it (both content and rating are replaced, not merged) if you do.

Bash
curl -X POST \
  -H "Content-Type: application/json" \
  -H 'Authorization: MediaBrowser Token="JELLYFIN_USER_ACCESS_TOKEN"' \
  -d '{"content": "Great movie!", "rating": 5}' \
  "JELLYFIN_SERVER_URL/JellyfinEnhanced/reviews/movie/TMDB_ID"
  • A per-user access token (JELLYFIN_USER_ACCESS_TOKEN), this writes the review under whichever user the token belongs to
  • rating is optional, omit it to leave a text-only review; see Rating and content rules above for the accepted values
  • Response: {"success": true}. A 400 with {"success": false, "message": "..."} explains which validation rule failed
Delete your own review

/JellyfinEnhanced/reviews/{mediaType}/{tmdbId}

Bash
curl -X DELETE \
  -H 'Authorization: MediaBrowser Token="JELLYFIN_USER_ACCESS_TOKEN"' \
  "JELLYFIN_SERVER_URL/JellyfinEnhanced/reviews/movie/TMDB_ID"
  • Response: {"success": true} whether or not a review existed, this endpoint does not report 404 for a no-op delete (unlike the bookmark and admin-review delete endpoints below)
Add or edit a review as a specific user (admin)

/JellyfinEnhanced/reviews/admin/{userIdN}/{mediaType}/{tmdbId}

Lets an Administrator API key create or update a review for any user, identified by an explicit userIdN. This is what a 3rd-party app should use to manage reviews for multiple users with one credential. Creates the review if none exists yet for that user and item, or updates it otherwise.

Bash
curl -X POST \
  -H "Content-Type: application/json" \
  -H "X-Emby-Token: JELLYFIN_API_KEY" \
  -d '{"content": "Great movie!", "rating": 5}' \
  "JELLYFIN_SERVER_URL/JellyfinEnhanced/reviews/admin/JELLYFIN_USER_ID/movie/TMDB_ID"
  • Jellyfin Server Administrator API key (JELLYFIN_API_KEY)
  • JELLYFIN_USER_ID here is the 32-character hex form with no dashes (the same format returned by the get-bookmarks endpoint, not the dashed form shown in the Jellyfin dashboard URL)
  • Same rating and content rules as the self-review endpoint above; rating still only allows 1-5 in 0.5 increments or omitted, an admin key does not bypass validation
  • Response: {"success": true}. A non-admin key gets 403 Forbidden, a malformed userIdN gets 400
Delete a specific user's review (admin)

/JellyfinEnhanced/reviews/admin/{userIdN}/{mediaType}/{tmdbId}

Bash
curl -X DELETE \
  -H "X-Emby-Token: JELLYFIN_API_KEY" \
  "JELLYFIN_SERVER_URL/JellyfinEnhanced/reviews/admin/JELLYFIN_USER_ID/movie/TMDB_ID"

Returns 404 with {"success": false, "removed": false} if no review exists for that user and item.

Seerr Integration API

/JellyfinEnhanced/jellyseerr

Jellyfin Server's API

These values are from Jellyfin Server's API:

  • X-Emby-Token:
    • API key
Check Seerr connection

/JellyfinEnhanced/jellyseerr/status

Bash
curl -X GET \
  -H "X-Emby-Token: JELLYFIN_API_KEY" \
  "<JELLYFIN_URL>/JellyfinEnhanced/jellyseerr/status"
  • Jellyfin Server API key (JELLYFIN_API_KEY)
  • Jellyfin Server User ID (JELLYFIN_USER_ID)
  • Jellyfin Server URL (JELLYFIN_URL)

Using Seerr configuration:

  • URL(s)
  • API keys
Check if user X-Jellyfin-User-Id has a successfully linked Seerr account

/JellyfinEnhanced/jellyseerr/user-status

Bash
curl -X GET \
  -H "X-Emby-Token: JELLYFIN_API_KEY" \
  -H "X-Jellyfin-User-Id: JELLYFIN_USER_ID" \
  "JELLYFIN_SERVER_URL/JellyfinEnhanced/jellyseerr/user-status"
  • Jellyfin Server API key X-Emby-Token (JELLYFIN_API_KEY)
  • Jellyfin Server User ID X-Jellyfin-User-Id (JELLYFIN_USER_ID)
  • Jellyfin Server URL (JELLYFIN_URL)

Example:

Bash
curl -X POST \
  -H "X-Emby-Token: <API_KEY>" \
  -H "X-Jellyfin-User-Id: <USER_ID>" \
  -H "Content-Type: application/json" \
  -d '{"mediaType": "movie", "mediaId": 27205}' \
  "<JELLYFIN_URL>/JellyfinEnhanced/jellyseerr/request"

Admin Hidden Content API

Admin-only endpoints that let an administrator view and manage what other users have hidden. Every endpoint requires a Jellyfin administrator token and the Let admins view and manage other users' hidden content toggle (Pages → Hidden Content → Admin Controls) to be enabled; otherwise it returns 403. <USER_ID> is the 32-character hex ("N" format) Jellyfin user id.

List Users With Hidden Content

Returns each user (except the caller) who has hidden at least one item, with their hidden-item count, used to populate the admin user-filter dropdown.

curl -X GET \
  -H "X-Emby-Token: <ADMIN_API_KEY>" \
  "<JELLYFIN_URL>/JellyfinEnhanced/admin/hidden-content-users"

Get A User's Hidden Content

Returns a single user's hidden content (read-only).

curl -X GET \
  -H "X-Emby-Token: <ADMIN_API_KEY>" \
  "<JELLYFIN_URL>/JellyfinEnhanced/admin/hidden-content/<USER_ID>"

Unhide Items For A User

Removes one or more items from a user's hidden list. The body is a JSON array of item keys (an itemId, or tmdb-<id> for items not in the library).

curl -X POST \
  -H "X-Emby-Token: <ADMIN_API_KEY>" \
  -H "Content-Type: application/json" \
  -d '["a1b2c3d4e5f6...", "tmdb-27205"]' \
  "<JELLYFIN_URL>/JellyfinEnhanced/admin/hidden-content/<USER_ID>/unhide"

Hide Items For A User

Adds one or more items to a user's hidden list (max 200 per call; an item the user hid themselves is never overwritten). The body is a JSON array of hidden-content items.

curl -X POST \
  -H "X-Emby-Token: <ADMIN_API_KEY>" \
  -H "Content-Type: application/json" \
  -d '[{"TmdbId": "27205", "Name": "Inception", "Type": "Movie", "PosterPath": "/edv5CZvWj09upOsy2Y6IwDhK8bt.jpg"}]' \
  "<JELLYFIN_URL>/JellyfinEnhanced/admin/hidden-content/<USER_ID>/hide"

Full Endpoint Index

The sections above document Bookmarks, Reviews, Seerr, and Admin Hidden Content in full (auth, request/response shapes, edge cases). Everything else this plugin exposes is listed here as a map, method + path + a one-line purpose, so a client author knows what exists before reading Controllers/JellyfinEnhancedController.cs for the exact request/response shape. All paths are relative to /JellyfinEnhanced/. [Authorize] means any authenticated Jellyfin user or API key; admin-only endpoints are noted individually.

Not fully documented yet

This index is deliberately terse. If you're building against one of these and need the exact request/response shape, the fastest source of truth is the corresponding controller method (grep the path string in JellyfinEnhancedController.cs) - contributions expanding any of these into full sections like the ones above are welcome.

Seerr Discovery & Requests

Method Path Purpose
GET jellyseerr/status Seerr connection/reachability check
GET jellyseerr/validate Validate configured Seerr URL(s) + API key
POST jellyseerr/trigger-recently-added-scan Kick off a Seerr library scan
GET jellyseerr/user-status Is the calling Jellyfin user linked to a Seerr account
GET jellyseerr/permission-audit Admin: audit every Jellyfin user's Seerr permission bits
GET jellyseerr/search Proxy a Seerr search query
GET jellyseerr/sonarr / jellyseerr/radarr List Sonarr/Radarr instances known to Seerr (read-only profile/folder discovery, no credentials)
GET jellyseerr/{type}/{serverId} Sonarr/Radarr server details by Seerr service id
GET jellyseerr/settings/{type} Admin-only: Seerr's own Radarr/Sonarr instance connection settings (hostname, port, apiKey, externalUrl, ...). Backs the *arr tab's "Import from Seerr" button; not the same endpoint as jellyseerr/sonarr/jellyseerr/radarr above
GET jellyfin-urls Admin-only: Jellyfin's own detected internal LAN URL and "Published server URIs" external/all override from Dashboard → Networking → Advanced, if configured. Backs the Seerr-import URL Mapping pre-fill
POST / GET jellyseerr/request Create / list Seerr requests
GET jellyseerr/quota Calling user's Seerr request quota
GET jellyseerr/tv/{tmdbId}, jellyseerr/movie/{tmdbId} TV/movie detail proxy
GET .../season/{seasonNumber} Season detail proxy
GET .../similar, .../recommendations Similar / recommended titles
GET jellyseerr/movie/{tmdbId}/ratingscombined, jellyseerr/tv/{tmdbId}/ratings Combined critic/audience ratings
GET jellyseerr/discover/movies, jellyseerr/discover/tv Discovery feed
GET .../upcoming Upcoming releases
GET .../trending Trending feed
GET .../network/{networkId}, .../studio/{studioId} Discovery filtered by network/studio
GET .../genre/{genreId}, .../keyword/{keywordId} Discovery filtered by genre/keyword
GET jellyseerr/discover/genreslider/movie, .../tv Genre-slider rows for the discovery UI
GET jellyseerr/person/{personId} Person detail proxy
GET jellyseerr/person/{personId}/combined_credits Person's filmography
GET jellyseerr/collection/{collectionId} Collection detail proxy
GET jellyseerr/overrideRule Seerr auto-approval override rules
GET jellyseerr/user Calling user's Seerr profile
POST jellyseerr/request/tv/{tmdbId}/seasons Request specific seasons of a show
GET jellyseerr/watchlist Calling user's Seerr watchlist
POST jellyseerr/sync-watchlist Trigger a watchlist sync
POST jellyseerr/import-users Admin: import Jellyfin users into Seerr
GET jellyseerr/settings/partial-requests Whether Seerr allows partial season requests
GET jellyseerr/issue, jellyseerr/issue/{id} List / get Seerr issues
POST jellyseerr/issue File a Seerr issue

TMDB Proxy & Metadata

Method Path Purpose
GET studio/{studioId} Studio metadata (non-Seerr TMDB proxy)
GET boxset/{boxsetId} Collection/boxset metadata
GET person/{personId} Person metadata
GET genre/{genreId} Genre metadata
GET tmdb/search/person, tmdb/search/keyword TMDB search proxy
GET tmdb/genres/movie, tmdb/genres/tv TMDB genre lists
GET tmdb/validate Validate the configured TMDB API key
GET tmdb/{**apiPath} Generic pass-through TMDB proxy (catch-all)

Client Bootstrap & Config

Method Path Purpose
GET script The injected client <script> bundle
GET js/{**path} Individual JS module files
GET Configuration/configPage.css Admin config page stylesheet
GET version Plugin version
GET private-config Admin-only: full plugin config
GET public-config Curated, non-sensitive config subset the client script reads
GET locales, locales/{lang}.json Available languages / one language's translation bundle
GET cdn/{source}/{**path} Local mirror of third-party static assets (icons, fonts, logos)

Per-User Settings Files

Same user-settings/{userId}/{file} pattern as Bookmarks (see above) for every other per-user JSON store:

Method Path Purpose
GET / POST user-settings/{userId}/settings.json Enhanced panel settings
GET / POST user-settings/{userId}/shortcuts.json Keyboard shortcut overrides
GET / POST user-settings/{userId}/elsewhere.json Elsewhere (streaming provider) preferences
GET / POST user-settings/{userId}/hidden-content.json Hidden Content list
GET / POST user-settings/{userId}/spoilerblur.json Spoiler Guard per-user state

Spoiler Guard

Method Path Purpose
GET spoiler-blur/health Diagnostic: blur filter health
DELETE spoiler-blur/health/{targetUserId} Reset a user's blur-health state
GET spoiler-blur/series Series currently under Spoiler Guard
GET / POST spoiler-blur/user-prefs Per-user Spoiler Guard preferences
POST / DELETE spoiler-blur/series/{seriesId} Enable/disable Spoiler Guard for a series
POST / DELETE spoiler-blur/movies/{movieId} Enable/disable for a movie
POST / DELETE spoiler-blur/collections/{collectionId} Enable/disable for a collection
POST / DELETE spoiler-blur/pending/{mediaType}/{tmdbId} Pre-arm Spoiler Guard for a title not yet in the library

Continue Watching / Next Up

Method Path Purpose
POST / DELETE continue-watching/hide/{itemId} Hide/unhide an item from Continue Watching
POST / DELETE next-up/hide/{itemId} Hide/unhide an item from Next Up

Tags, Cache & Watch Data

Method Path Purpose
POST tag-cache/rebuild Admin: force a full tag-cache rebuild
GET tag-cache/{userId} This user's tag cache
POST tag-data/{userId} Batch tag lookup by item ids
GET file-size/{userId}/{itemId} File size for an item
GET watch-progress/{userId}/{itemId} Watch progress for an item
GET awards/{mediaType}/{tmdbId} Wikidata award wins/nominations
GET mdblist-ratings/{mediaType}/{tmdbId} MDBList ratings for a title
GET mdblist-ratings/account-status MDBList account quota/status

Activity Feed & What's New

Method Path Purpose
GET activity The Activity Feed (recently watched/favorited/reviewed)
GET whats-new Admin: pending "What's New" settings for the config page
POST whats-new/dismiss Admin: acknowledge the current "What's New" state

Branding

Method Path Purpose
POST UploadBrandingImage Admin: upload a custom logo/banner/favicon
GET BrandingImage Serve a custom branding image
POST DeleteBrandingImage Admin: remove a custom branding image

*arr (Sonarr/Radarr/Bazarr)

Method Path Purpose
GET arr/validate/sonarr, arr/validate/radarr Validate an instance's URL/API key
GET arr/identify-url Resolve which configured instance owns a given item
GET arr/series-slug, arr/series-slugs Sonarr URL slug lookup, single/batch
GET arr/movie-instances Which Radarr instance(s) a movie belongs to
GET arr/queue Sonarr/Radarr download queue
GET arr/history Sonarr/Radarr import history
GET arr/requests Requests page data (Seerr + arr queue merged)
POST arr/requests/{requestId}/approve, .../decline Admin: approve/decline a Seerr request
GET arr/calendar Calendar page data
POST arr/calendar/user-data Per-user calendar preferences (favorites/watched highlighting)

Active Streams & Proxy

Method Path Purpose
GET active-streams/sessions Currently active playback sessions
POST active-streams/broadcast Admin: broadcast a message to active sessions
GET proxy/avatar Cached avatar image proxy
GET items/by-providers Look up Jellyfin items by external provider id

Maintenance Mode

All admin-only.

Method Path Purpose
GET MaintenanceMode/Status Current maintenance-mode state
POST MaintenanceMode/Enable Enable maintenance mode
POST MaintenanceMode/Disable Disable maintenance mode
GET MaintenanceMode/Users Users affected by the current maintenance-mode config
POST MaintenanceMode/Broadcast Send the maintenance notification immediately

Misc

Method Path Purpose
POST reset-all-users-settings Admin: overwrite every user's settings with the current defaults
GET {viewName} Catch-all: serves a Plugin Pages HTML view by name