fix(api): update OpenAPI schema to match actual API responses#2700
fix(api): update OpenAPI schema to match actual API responses#2700electather wants to merge 4 commits intoseerr-team:developfrom
Conversation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The endpoint rejects email as read-only; confirmed via live API test.
📝 WalkthroughWalkthroughThe OpenAPI spec Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 2✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 📝 Coding Plan
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@seerr-api.yml`:
- Around line 76-77: The inline watchlist item schemas still use the field name
"type" while the top-level schema uses "mediaType", causing inconsistent
generated clients; locate the inline watchlist item definitions that declare
"type" (the watchlist item objects referenced by the watchlist endpoints) and
either rename those inline properties from "type" to "mediaType" to match the
existing schema or refactor by extracting a single shared WatchlistItem schema
and reference it from each endpoint so the contract for the watchlist item field
name is defined in one place.
- Around line 139-141: The settings property currently places nullable: true
alongside a $ref (settings with $ref '#/components/schemas/UserSettings' and
nullable: true), which OpenAPI 3.0.2 ignores; change the settings schema to use
an allOf composition that contains the $ref to
'#/components/schemas/UserSettings' and set nullable: true on the allOf wrapper
so the reference becomes properly nullable (i.e., replace the direct $ref +
nullable with an allOf array containing the $ref and apply nullable: true to the
allOf object).
- Rename inline `type` property to `mediaType` in watchlist item
schemas for /user/{userId}/watchlist and /discover/watchlist to
match the top-level Watchlist schema
- Replace $ref + nullable: true on User.settings with allOf
composition to comply with OpenAPI 3.0.2 (nullable on $ref is
ignored without allOf)
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@seerr-api.yml`:
- Around line 175-177: The OpenAPI schema declares User.avatarVersion as integer
but runtime/DB uses a varchar; update the schema to match runtime by changing
the avatarVersion property in seerr-api.yml (User.avatarVersion) from type:
integer to type: string (keeping nullable: true), or alternatively change the
model/serializer that emits avatarVersion to an actual integer—ensure both the
OpenAPI field "avatarVersion" and the runtime serialization agree on string vs
integer to avoid client/validator breakage.
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
seerr-api.yml (1)
1322-1340: Tighten free-form object arrays to preserve generated client typing.
MediaRequest.seasonsandMediaInfo.downloadStatus*useitems: { type: object }, which makes the contract too loose and reduces client/typegen value. Consider introducing explicit item schemas.♻️ Suggested schema tightening
MediaRequest: type: object properties: @@ seasons: type: array items: - type: object + $ref: '#/components/schemas/RequestSeason' @@ MediaInfo: type: object properties: @@ downloadStatus: type: array items: - type: object + $ref: '#/components/schemas/DownloadStatusEntry' downloadStatus4k: type: array items: - type: object + $ref: '#/components/schemas/DownloadStatusEntry' + + RequestSeason: + type: object + additionalProperties: true + + DownloadStatusEntry: + type: object + additionalProperties: trueAlso applies to: 1429-1436
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@seerr-api.yml` around lines 1322 - 1340, The schemas use items: { type: object } for MediaRequest.seasons and the MediaInfo.downloadStatus* arrays which produces loose typings; replace those with explicit item schemas (either inline objects with well-defined properties or references to new components like Season and DownloadStatusEntry) and update MediaRequest.seasons to use $ref: '#/components/schemas/Season' (or an equivalent explicit object with properties such as seasonNumber, episodes, quality, etc.), and change MediaInfo.downloadStatus* to arrays of a concrete DownloadStatus schema so generated clients receive precise typings; ensure new schema names match existing model naming and update any refs where seasons or download status arrays are used.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@seerr-api.yml`:
- Around line 2244-2276: The OpenAPI schema in seerr-api.yml mismatches the
entity server/entity/OverrideRule.ts: fields users, keywords, tags (now declared
as array<number>) and genre (declared as number) should be strings like the
entity and routes expect. Fix by changing the schema types for users, keywords,
tags to type: string (nullable: true) instead of array items:number, and change
genre (and ensure language) to type: string (nullable: true) so the spec matches
the OverrideRule.ts runtime types and generated clients will expect strings.
---
Nitpick comments:
In `@seerr-api.yml`:
- Around line 1322-1340: The schemas use items: { type: object } for
MediaRequest.seasons and the MediaInfo.downloadStatus* arrays which produces
loose typings; replace those with explicit item schemas (either inline objects
with well-defined properties or references to new components like Season and
DownloadStatusEntry) and update MediaRequest.seasons to use $ref:
'#/components/schemas/Season' (or an equivalent explicit object with properties
such as seasonNumber, episodes, quality, etc.), and change
MediaInfo.downloadStatus* to arrays of a concrete DownloadStatus schema so
generated clients receive precise typings; ensure new schema names match
existing model naming and update any refs where seasons or download status
arrays are used.
| users: | ||
| type: array | ||
| nullable: true | ||
| items: | ||
| type: number | ||
| genre: | ||
| type: number | ||
| nullable: true | ||
| language: | ||
| type: string | ||
| nullable: true | ||
| keywords: | ||
| type: array | ||
| nullable: true | ||
| items: | ||
| type: number | ||
| profileId: | ||
| type: number | ||
| nullable: true | ||
| rootFolder: | ||
| type: string | ||
| nullable: true | ||
| tags: | ||
| type: array | ||
| nullable: true | ||
| items: | ||
| type: number | ||
| radarrServiceId: | ||
| type: number | ||
| nullable: true | ||
| sonarrServiceId: | ||
| type: number | ||
| nullable: true |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Locating OverrideRule files..."
entity_file="$(fd 'OverrideRule\.ts$' | head -n1 || true)"
route_file="$(fd 'overrideRule\.ts$' | head -n1 || true)"
echo "Entity file: ${entity_file:-NOT FOUND}"
echo "Route file: ${route_file:-NOT FOUND}"
if [[ -n "${entity_file:-}" ]]; then
echo
echo "== Entity field declarations =="
rg -n -C2 'users|genre|language|keywords|profileId|rootFolder|tags|radarrServiceId|sonarrServiceId|createdAt|updatedAt' "$entity_file"
fi
if [[ -n "${route_file:-}" ]]; then
echo
echo "== Route request typing + assignments =="
rg -n -C3 'overrideRuleRoutes\.(post|put)|users\?:|genre\?:|language\?:|keywords\?:|profileId\?:|rootFolder\?:|tags\?:|radarrServiceId\?:|sonarrServiceId\?:|res\.status\(200\)\.json' "$route_file"
fiRepository: seerr-team/seerr
Length of output: 2975
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Check the full entity file for serialization hooks
echo "=== Full OverrideRule.ts Entity ==="
cat -n server/entity/OverrideRule.ts
echo
echo "=== Checking for serialization transformations in routes ==="
rg -n 'toJSON|transform|serialize|exclude|expose|plainToClass' server/routes/overrideRule.ts || echo "No explicit transformations found"Repository: seerr-team/seerr
Length of output: 1698
Fix schema type mismatch: users, keywords, tags are strings at runtime, not arrays.
The entity (server/entity/OverrideRule.ts) defines users, keywords, tags, genre, and language as string fields with no serialization transformations. The routes accept these as strings in request payloads. However, the schema now declares users/keywords/tags as array<number> and genre as number. Generated clients will expect numeric arrays but receive strings, causing runtime failures.
Either update the schema to match the string types or refactor the entity and routes to handle the numeric array types as intended.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@seerr-api.yml` around lines 2244 - 2276, The OpenAPI schema in seerr-api.yml
mismatches the entity server/entity/OverrideRule.ts: fields users, keywords,
tags (now declared as array<number>) and genre (declared as number) should be
strings like the entity and routes expect. Fix by changing the schema types for
users, keywords, tags to type: string (nullable: true) instead of array
items:number, and change genre (and ensure language) to type: string (nullable:
true) so the spec matches the OverrideRule.ts runtime types and generated
clients will expect strings.
Description
Updates seerr-api.yml to align schema definitions with actual API responses. Discrepancies were discovered while building https://github.com/electather/seer-cli, an MCP server and CLI for Seerr.
quota fields, etc.); relaxed required
I used claude code as an assistant.
How Has This Been Tested?
Validated by consuming the live API through https://github.com/electather/seer-cli and comparing actual response payloads against the schema.
Screenshots / Logs (if applicable)
Checklist:
pnpm buildpnpm i18n:extractSummary by CodeRabbit