Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions docs/Glossary.md
Original file line number Diff line number Diff line change
Expand Up @@ -2123,6 +2123,28 @@ Indicates whether the media was requested in Seerr.
- Availability: movies, shows, seasons, episodes
- Type: boolean

#### Watchlisted by (username)

:::info
List of Seerr users who have the movie or show in their watchlist. For seasons and episodes, this checks the parent show's watchlist.

:::

- Key: Seerr.watchlist_isListedByUsers
- Availability: movies, shows, seasons, episodes
- Type: text[]

#### Is Watchlisted

:::info
Indicates whether any Seerr user has the movie or show in their watchlist. For seasons and episodes, this checks the parent show's watchlist.

:::

- Key: Seerr.watchlist_isWatchlisted
- Availability: movies, shows, seasons, episodes
- Type: boolean

---

### Ombi
Expand Down
9 changes: 7 additions & 2 deletions docs/Rules.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ Troubleshooting tips:

:::

:::note Seerr Watchlist Rules
`Watchlisted by` (`Seerr.watchlist_isListedByUsers`) and `Is Watchlisted` (`Seerr.watchlist_isWatchlisted`) check the watchlists of all users returned by Seerr. They work with every media server; Plex users' watchlists are read through their linked plex.tv accounts. A season or episode uses its show's watchlist because Seerr tracks watchlisted titles, not individual seasons or episodes. If Maintainerr cannot read the Seerr user list or any watchlist response, the result is unknown for that run rather than an empty list.
:::

## Creating rules

### General
Expand Down Expand Up @@ -171,7 +175,7 @@ Season delete actions unmonitor the season in Sonarr and delete its episode file

Episode delete actions share the season folder with other episodes, so the folder is never removed by this action. No leftover folder cleanup is offered for episode rules.

Maintainerr finds the episode in Sonarr by its TVDB episode id when exactly one Sonarr episode has it, so a library numbered differently from Sonarr, such as absolute or DVD order, still acts on the right episode. Otherwise it matches by season and episode number, or by air date. When one file holds several episodes, all of them are unmonitored before the file is deleted, so Sonarr does not download it again. If any of them cannot be unmonitored, the file is kept.
Maintainerr first matches a Sonarr episode by the media file when its path identifies one file containing exactly one episode. If there is no unique file match, it falls back to a unique TVDB episode id, then to season and episode numbers or air date. When Sonarr's episode or file list cannot be read, episode-level rules stay unknown and episode actions skip the item rather than risk using the wrong episode. When one file holds several episodes, all of them are unmonitored before the file is deleted, so Sonarr does not download it again. If any of them cannot be unmonitored, the file is kept.

### Sportarr actions

Expand Down Expand Up @@ -470,7 +474,8 @@ Both walkthroughs work unchanged for daily series:
- Daily shows that use one season per year rank those year-seasons like any
other season.
- Some servers store daily episodes with only an air date and no episode
number. Those episodes are matched to Sonarr by broadcast date, so
number. Maintainerr first matches them by file when it identifies one
episode; otherwise it can match them to Sonarr by broadcast date, so
`Episode position by air date (1 = latest)` still resolves. When two
episodes of a date-only show share the same broadcast day, the newer one's
rank is used, which errs on the side of keeping media.
Expand Down
7 changes: 5 additions & 2 deletions docs/api/media-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ Response:
"addedAt": "2026-01-01T00:00:00.000Z",
"providerIds": { "tmdb": ["550"] },
"mediaSources": [{ "id": "1", "sizeBytes": 0 }],
"path": "/media/movies/Example title (2026)/Example title.mkv",
"library": { "id": "1", "title": "Movies" },
"maintainerrExclusionType": "global",
"maintainerrIsManual": true,
Expand All @@ -137,7 +138,7 @@ Response:
}
```

Items carry the full media item shape except `path`, which is only populated by the single-item metadata route. On top of the media server's own fields, this route adds Maintainerr state: `maintainerrExclusionId`, `maintainerrExclusionType` which is `specific` or `global`, `maintainerrIsManual`, and `maintainerrCollections`, the titles of every collection the item belongs to.
Items include the media server's path when that backend provides it. Movies and episodes return the media file; shows and seasons return the folder. Plex listings provide it only for movies and episodes, and Plex seasons have no path. On top of the media server's own fields, this route adds Maintainerr state: `maintainerrExclusionId`, `maintainerrExclusionType` which is `specific` or `global`, `maintainerrIsManual`, and `maintainerrCollections`, the titles of every collection the item belongs to.

| Status | Cause |
| ------ | ------------------------------------------------------------------------------------------- |
Expand Down Expand Up @@ -230,6 +231,8 @@ Response:

There is no way to choose which library is bootstrapped. It is always the first one the media server returned. The embedded page is always filtered to that library's own type, so a show library returns shows and never seasons or episodes.

The embedded content items can include `path`, as described for the paged content route.

A `sort` of `manual` or `excluded` pays the full-library sweep described above, at page load.

### `GET /api/media-server/search/{query}`
Expand Down Expand Up @@ -279,7 +282,7 @@ Response:

There is no way to tell a missing item from a failed read here.

`path` is the server's own filesystem path for that one item: movies and episodes return the media file, while shows and seasons return the folder. Only this single-item route populates it, and a Plex season has no path of its own.
`path` is the server's own filesystem path for that one item: movies and episodes return the media file, while shows and seasons return the folder. The paged content route and its embedded page in `overview/bootstrap` can also return it; other listing routes do not guarantee it. A Plex season has no path of its own.

:::caution Watch fields are per-user and cached
`viewCount`, `lastViewedAt` and `userRating` are scoped to the single Jellyfin or Emby user Maintainerr is configured with, and are cached for 5 minutes. Do not use them to drive watch or deletion decisions. Use `GET /api/media-server/meta/{id}/seen` for that.
Expand Down
4 changes: 2 additions & 2 deletions static/openapi-spec/maintainerr_api_specs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1322,7 +1322,7 @@ paths:
type: string
responses:
'200':
description: ''
description: The paged items can include the media server's filesystem path when the backend provides it. Plex listings provide it only for movies and episodes.
tags:
- MediaServer
/api/media-server/library/{id}/content/search/{query}:
Expand Down Expand Up @@ -1429,7 +1429,7 @@ paths:
application/json:
schema:
type: object
description: Single-item media metadata. Only this route populates `path`, which is the media server's own filesystem path for the item.
description: Single-item media metadata. `path` is the media server's own filesystem path for the item. The paged library content route and overview bootstrap content can also include it.
properties:
path:
type: string
Expand Down
Loading