From 98d82e21e19e69217a4deffa9c0aeae3362715c2 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 8 Feb 2026 15:24:32 +0000 Subject: [PATCH 1/6] Sync OpenAPI schema property order with documentation examples Reorder properties in 15 OpenAPI schema files to match the attribute order used in the markdown documentation JSON examples. This makes it easier to verify that both sources contain identical properties and improves consistency across the project. Affected schemas: AlbumID3, AlbumInfo, Artist, ArtistID3, ArtistInfo, ArtistInfo2, Bookmark, Child, Directory, Genre, JukeboxStatus, Lyrics, Playlist, Share, User https://claude.ai/code/session_015LLNEbErYFkRrZvQZ3NMoV --- openapi/schemas/AlbumID3.json | 44 +++++++----- openapi/schemas/AlbumInfo.json | 10 +-- openapi/schemas/Artist.json | 10 +-- openapi/schemas/ArtistID3.json | 10 +-- openapi/schemas/ArtistInfo.json | 10 +-- openapi/schemas/ArtistInfo2.json | 10 +-- openapi/schemas/Bookmark.json | 12 ++-- openapi/schemas/Child.json | 108 +++++++++++++++-------------- openapi/schemas/Directory.json | 24 +++---- openapi/schemas/Genre.json | 10 +-- openapi/schemas/JukeboxStatus.json | 10 +-- openapi/schemas/Lyrics.json | 10 +-- openapi/schemas/Playlist.json | 38 +++++----- openapi/schemas/Share.json | 22 +++--- openapi/schemas/User.json | 22 +++--- 15 files changed, 183 insertions(+), 167 deletions(-) diff --git a/openapi/schemas/AlbumID3.json b/openapi/schemas/AlbumID3.json index e2577892..4b3e1051 100644 --- a/openapi/schemas/AlbumID3.json +++ b/openapi/schemas/AlbumID3.json @@ -18,17 +18,18 @@ "type": "string", "description": "Artist name." }, - "artistId": { - "type": "string", - "description": "The id of the artist" + "year": { + "type": "integer", + "description": "The album year" }, "coverArt": { "type": "string", "description": "A covertArt id." }, - "songCount": { - "type": "integer", - "description": "Number of songs" + "starred": { + "type": "string", + "format": "date-time", + "description": "Date the album was added. [ISO 8601]" }, "duration": { "type": "integer", @@ -38,23 +39,22 @@ "type": "integer", "description": "Number of play of the album" }, + "genre": { + "type": "string", + "description": "The album genre" + }, "created": { "type": "string", "format": "date-time", "description": "Date the album was added. [ISO 8601]" }, - "starred": { + "artistId": { "type": "string", - "format": "date-time", - "description": "Date the album was added. [ISO 8601]" + "description": "The id of the artist" }, - "year": { + "songCount": { "type": "integer", - "description": "The album year" - }, - "genre": { - "type": "string", - "description": "The album genre" + "description": "Number of songs" }, "played": { "type": "string", @@ -115,11 +115,19 @@ "description": "The album sort name." }, "originalReleaseDate": { - "allOf": [{"$ref": "./ItemDate.json"}], + "allOf": [ + { + "$ref": "./ItemDate.json" + } + ], "description": "Date the album was originally released." }, "releaseDate": { - "allOf": [{"$ref": "./ItemDate.json"}], + "allOf": [ + { + "$ref": "./ItemDate.json" + } + ], "description": "Date the specific edition of the album was released. Note: for files using ID3 tags, releaseDate should generally be read from the TDRL tag. Servers that use a different source for this field should document the behavior." }, "isCompilation": { @@ -155,4 +163,4 @@ "description": "AlbumID3", "url": "https://opensubsonic.netlify.app/docs/responses/albumid3/" } -} \ No newline at end of file +} diff --git a/openapi/schemas/AlbumInfo.json b/openapi/schemas/AlbumInfo.json index e3bef9cd..f2d4bcbb 100644 --- a/openapi/schemas/AlbumInfo.json +++ b/openapi/schemas/AlbumInfo.json @@ -10,10 +10,6 @@ "type": "string", "description": "Album musicBrainzId" }, - "lastFmUrl": { - "type": "string", - "description": "Album lastFmUrl" - }, "smallImageUrl": { "type": "string", "description": "Album smallImageUrl" @@ -25,10 +21,14 @@ "largeImageUrl": { "type": "string", "description": "Album largeImageUrl" + }, + "lastFmUrl": { + "type": "string", + "description": "Album lastFmUrl" } }, "externalDocs": { "description": "AlbumInfo", "url": "https://opensubsonic.netlify.app/docs/responses/albuminfo/" } -} \ No newline at end of file +} diff --git a/openapi/schemas/Artist.json b/openapi/schemas/Artist.json index aacff72c..6696b140 100644 --- a/openapi/schemas/Artist.json +++ b/openapi/schemas/Artist.json @@ -10,15 +10,15 @@ "type": "string", "description": "Artist name" }, - "artistImageUrl": { - "type": "string", - "description": "Artist image url" - }, "starred": { "type": "string", "format": "date-time", "description": "Artist starred date [ISO 8601]" }, + "artistImageUrl": { + "type": "string", + "description": "Artist image url" + }, "userRating": { "type": "integer", "minimum": 1, @@ -40,4 +40,4 @@ "description": "Artist", "url": "https://opensubsonic.netlify.app/docs/responses/artist/" } -} \ No newline at end of file +} diff --git a/openapi/schemas/ArtistID3.json b/openapi/schemas/ArtistID3.json index df18a693..6ecb486f 100644 --- a/openapi/schemas/ArtistID3.json +++ b/openapi/schemas/ArtistID3.json @@ -14,14 +14,14 @@ "type": "string", "description": "A covertArt id." }, - "artistImageUrl": { - "type": "string", - "description": "An url to an external image source." - }, "albumCount": { "type": "integer", "description": "Artist album count." }, + "artistImageUrl": { + "type": "string", + "description": "An url to an external image source." + }, "starred": { "type": "string", "format": "date-time", @@ -51,4 +51,4 @@ "description": "ArtistID3", "url": "https://opensubsonic.netlify.app/docs/responses/artistid3/" } -} \ No newline at end of file +} diff --git a/openapi/schemas/ArtistInfo.json b/openapi/schemas/ArtistInfo.json index 18c389c4..b73dcc33 100644 --- a/openapi/schemas/ArtistInfo.json +++ b/openapi/schemas/ArtistInfo.json @@ -10,10 +10,6 @@ "type": "string", "description": "Artist musicBrainzId" }, - "lastFmUrl": { - "type": "string", - "description": "Artist lastFmUrl" - }, "smallImageUrl": { "type": "string", "description": "Artist smallImageUrl" @@ -26,6 +22,10 @@ "type": "string", "description": "Artist largeImageUrl" }, + "lastFmUrl": { + "type": "string", + "description": "Artist lastFmUrl" + }, "similarArtist": { "type": "array", "items": { @@ -38,4 +38,4 @@ "description": "ArtistInfo", "url": "https://opensubsonic.netlify.app/docs/responses/artistinfo/" } -} \ No newline at end of file +} diff --git a/openapi/schemas/ArtistInfo2.json b/openapi/schemas/ArtistInfo2.json index 056aaa19..6807c011 100644 --- a/openapi/schemas/ArtistInfo2.json +++ b/openapi/schemas/ArtistInfo2.json @@ -10,10 +10,6 @@ "type": "string", "description": "Artist musicBrainzId" }, - "lastFmUrl": { - "type": "string", - "description": "Artist lastFmUrl" - }, "smallImageUrl": { "type": "string", "description": "Artist smallImageUrl" @@ -26,6 +22,10 @@ "type": "string", "description": "Artist largeImageUrl" }, + "lastFmUrl": { + "type": "string", + "description": "Artist lastFmUrl" + }, "similarArtist": { "type": "array", "items": { @@ -38,4 +38,4 @@ "description": "ArtistInfo2", "url": "https://opensubsonic.netlify.app/docs/responses/artistinfo2/" } -} \ No newline at end of file +} diff --git a/openapi/schemas/Bookmark.json b/openapi/schemas/Bookmark.json index be200eaa..bdb94255 100644 --- a/openapi/schemas/Bookmark.json +++ b/openapi/schemas/Bookmark.json @@ -6,6 +6,14 @@ "url": "https://opensubsonic.netlify.app/docs/responses/bookmark/" }, "properties": { + "entry": { + "allOf": [ + { + "$ref": "./Child.json" + } + ], + "description": "The bookmark file" + }, "position": { "type": "integer", "description": "Bookmark position in milliseconds" @@ -27,10 +35,6 @@ "type": "string", "format": "date-time", "description": "Bookmark last updated date [ISO 8601]" - }, - "entry": { - "allOf": [{"$ref": "./Child.json"}], - "description": "The bookmark file" } }, "required": [ diff --git a/openapi/schemas/Child.json b/openapi/schemas/Child.json index 94ddc4a8..abd920ff 100644 --- a/openapi/schemas/Child.json +++ b/openapi/schemas/Child.json @@ -34,10 +34,6 @@ "type": "integer", "description": "The media year." }, - "genre": { - "type": "string", - "description": "The media genre" - }, "coverArt": { "type": "string", "description": "The coverArt id." @@ -54,13 +50,10 @@ "type": "string", "description": "The file suffix of the media." }, - "transcodedContentType": { - "type": "string", - "description": "The transcoded mediaType if transcoding should happen." - }, - "transcodedSuffix": { + "starred": { "type": "string", - "description": "The file suffix of the transcoded media." + "format": "date-time", + "description": "Date the media was starred. [ISO 8601]" }, "duration": { "type": "integer", @@ -86,26 +79,15 @@ "type": "string", "description": "The full path of the media." }, - "isVideo": { - "type": "boolean", - "description": "Media is a video" - }, - "userRating": { - "type": "integer", - "description": "The user rating of the media [1-5]", - "minimum": 1, - "maximum": 5 - }, - "averageRating": { - "type": "number", - "description": "The average rating of the media [1.0-5.0]", - "minimum": 0, - "maximum": 5 - }, "playCount": { "type": "integer", "description": "The play count." }, + "played": { + "type": "string", + "format": "date-time", + "description": "Date the album was last played. [ISO 8601]" + }, "discNumber": { "type": "integer", "description": "The disc number." @@ -115,11 +97,6 @@ "format": "date-time", "description": "Date the media was created. [ISO 8601]" }, - "starred": { - "type": "string", - "format": "date-time", - "description": "Date the media was starred. [ISO 8601]" - }, "albumId": { "type": "string", "description": "The corresponding album id" @@ -134,22 +111,9 @@ "mediaType": { "$ref": "./MediaType.json" }, - "bookmarkPosition": { - "type": "integer", - "description": "The bookmark position in seconds" - }, - "originalWidth": { - "type": "integer", - "description": "The video original Width" - }, - "originalHeight": { - "type": "integer", - "description": "The video original Height" - }, - "played": { - "type": "string", - "format": "date-time", - "description": "Date the album was last played. [ISO 8601]" + "isVideo": { + "type": "boolean", + "description": "Media is a video" }, "bpm": { "type": "integer", @@ -170,7 +134,7 @@ "isrc": { "type": "array", "description": "The track ISRC(s).", - "example" : [ + "example": [ "USSM18300073", "DELV42300297" ], @@ -225,12 +189,52 @@ }, "description": "The list of all moods of the song." }, + "explicitStatus": { + "$ref": "./ExplicitStatus.json" + }, "replayGain": { - "allOf": [{"$ref": "./ReplayGain.json"}], + "allOf": [ + { + "$ref": "./ReplayGain.json" + } + ], "description": "The replay gain data of the song." }, - "explicitStatus": { - "$ref": "./ExplicitStatus.json" + "genre": { + "type": "string", + "description": "The media genre" + }, + "transcodedContentType": { + "type": "string", + "description": "The transcoded mediaType if transcoding should happen." + }, + "transcodedSuffix": { + "type": "string", + "description": "The file suffix of the transcoded media." + }, + "userRating": { + "type": "integer", + "description": "The user rating of the media [1-5]", + "minimum": 1, + "maximum": 5 + }, + "averageRating": { + "type": "number", + "description": "The average rating of the media [1.0-5.0]", + "minimum": 0, + "maximum": 5 + }, + "bookmarkPosition": { + "type": "integer", + "description": "The bookmark position in seconds" + }, + "originalWidth": { + "type": "integer", + "description": "The video original Width" + }, + "originalHeight": { + "type": "integer", + "description": "The video original Height" } }, "required": [ @@ -242,4 +246,4 @@ "description": "Child", "url": "https://opensubsonic.netlify.app/docs/responses/child/" } -} \ No newline at end of file +} diff --git a/openapi/schemas/Directory.json b/openapi/schemas/Directory.json index 92f1d446..ceb30811 100644 --- a/openapi/schemas/Directory.json +++ b/openapi/schemas/Directory.json @@ -10,14 +10,21 @@ "type": "string", "description": "The id" }, - "parent": { - "type": "string", - "description": "Parent item" - }, "name": { "type": "string", "description": "The directory name" }, + "child": { + "type": "array", + "items": { + "$ref": "./Child.json" + }, + "description": "The directory content" + }, + "parent": { + "type": "string", + "description": "Parent item" + }, "starred": { "type": "string", "format": "date-time", @@ -38,17 +45,10 @@ "playCount": { "type": "integer", "description": "The play count" - }, - "child": { - "type": "array", - "items": { - "$ref": "./Child.json" - }, - "description": "The directory content" } }, "required": [ "id", "name" ] -} \ No newline at end of file +} diff --git a/openapi/schemas/Genre.json b/openapi/schemas/Genre.json index c46b39d2..24bc50bc 100644 --- a/openapi/schemas/Genre.json +++ b/openapi/schemas/Genre.json @@ -6,10 +6,6 @@ "url": "https://opensubsonic.netlify.app/docs/responses/genre/" }, "properties": { - "value": { - "type": "string", - "description": "Genre name" - }, "songCount": { "type": "integer", "description": "Genre song count" @@ -17,6 +13,10 @@ "albumCount": { "type": "integer", "description": "Genre album count" + }, + "value": { + "type": "string", + "description": "Genre name" } }, "required": [ @@ -24,4 +24,4 @@ "songCount", "albumCount" ] -} \ No newline at end of file +} diff --git a/openapi/schemas/JukeboxStatus.json b/openapi/schemas/JukeboxStatus.json index 659458c7..455bd547 100644 --- a/openapi/schemas/JukeboxStatus.json +++ b/openapi/schemas/JukeboxStatus.json @@ -14,16 +14,16 @@ "type": "boolean", "description": "Whether the queue is currently playing" }, + "position": { + "type": "integer", + "description": "The current position of the track in seconds" + }, "volume": { "type": "integer", "description": "Volume, in a range of [0.0, 1.0]", "format": "float", "minimum": 0.0, "maximum": 1.0 - }, - "position": { - "type": "integer", - "description": "The current position of the track in seconds" } }, "required": [ @@ -31,4 +31,4 @@ "playing", "volume" ] -} \ No newline at end of file +} diff --git a/openapi/schemas/Lyrics.json b/openapi/schemas/Lyrics.json index 75b6c617..40784b3f 100644 --- a/openapi/schemas/Lyrics.json +++ b/openapi/schemas/Lyrics.json @@ -6,10 +6,6 @@ "url": "https://opensubsonic.netlify.app/docs/responses/lyrics/" }, "properties": { - "value": { - "type": "string", - "description": "The lyrics" - }, "artist": { "type": "string", "description": "The artist name" @@ -17,9 +13,13 @@ "title": { "type": "string", "description": "The song title" + }, + "value": { + "type": "string", + "description": "The lyrics" } }, "required": [ "value" ] -} \ No newline at end of file +} diff --git a/openapi/schemas/Playlist.json b/openapi/schemas/Playlist.json index b9506cd2..947fa529 100644 --- a/openapi/schemas/Playlist.json +++ b/openapi/schemas/Playlist.json @@ -10,10 +10,6 @@ "type": "string", "description": "Name of the playlist" }, - "comment": { - "type": "string", - "description": "A comment" - }, "owner": { "type": "string", "description": "Owner of the playlist" @@ -22,6 +18,16 @@ "type": "boolean", "description": "Is the playlist public" }, + "created": { + "type": "string", + "format": "date-time", + "description": "Creation date [ISO 8601]" + }, + "changed": { + "type": "string", + "format": "date-time", + "description": "Last changed date [ISO 8601]" + }, "songCount": { "type": "integer", "description": "number of songs" @@ -30,15 +36,18 @@ "type": "integer", "description": "Playlist duration in seconds" }, - "created": { + "readonly": { + "type": "boolean", + "description": "[OS] If true the playlist cannot be edited by the current user" + }, + "validUntil": { "type": "string", "format": "date-time", - "description": "Creation date [ISO 8601]" + "description": "[OS] Date the playlist contents are considered valid until [ISO 8601]. Empty or absent means no caching guarantee." }, - "changed": { + "comment": { "type": "string", - "format": "date-time", - "description": "Last changed date [ISO 8601]" + "description": "A comment" }, "coverArt": { "type": "string", @@ -50,15 +59,6 @@ "type": "string" }, "description": "A list of allowed usernames" - }, - "readonly": { - "type": "boolean", - "description": "[OS] If true the playlist cannot be edited by the current user" - }, - "validUntil": { - "type": "string", - "format": "date-time", - "description": "[OS] Date the playlist contents are considered valid until [ISO 8601]. Empty or absent means no caching guarantee." } }, "required": [ @@ -73,4 +73,4 @@ "description": "Playlist", "url": "https://opensubsonic.netlify.app/docs/responses/playlist/" } -} \ No newline at end of file +} diff --git a/openapi/schemas/Share.json b/openapi/schemas/Share.json index 6be56df9..51a0f04e 100644 --- a/openapi/schemas/Share.json +++ b/openapi/schemas/Share.json @@ -23,16 +23,6 @@ "format": "date-time", "description": "Creation date [ISO 8601]" }, - "expires": { - "type": "string", - "format": "date-time", - "description": "Share expiration [ISO 8601]" - }, - "lastVisited": { - "type": "string", - "format": "date-time", - "description": "Last visit [ISO 8601]" - }, "visitCount": { "type": "integer", "description": "Visit count" @@ -43,6 +33,16 @@ "$ref": "./Child.json" }, "description": "A list of share" + }, + "expires": { + "type": "string", + "format": "date-time", + "description": "Share expiration [ISO 8601]" + }, + "lastVisited": { + "type": "string", + "format": "date-time", + "description": "Last visit [ISO 8601]" } }, "required": [ @@ -56,4 +56,4 @@ "description": "Share", "url": "https://opensubsonic.netlify.app/docs/responses/share/" } -} \ No newline at end of file +} diff --git a/openapi/schemas/User.json b/openapi/schemas/User.json index 9f1dc81f..a6baba79 100644 --- a/openapi/schemas/User.json +++ b/openapi/schemas/User.json @@ -6,6 +6,13 @@ "url": "https://opensubsonic.netlify.app/docs/responses/user/" }, "properties": { + "folder": { + "type": "array", + "items": { + "type": "integer" + }, + "description": "Folder ID(s)" + }, "username": { "type": "string", "description": "Username" @@ -14,9 +21,6 @@ "type": "boolean", "description": "Scrobbling enabled" }, - "maxBitRate": { - "type": "integer" - }, "adminRole": { "type": "boolean", "description": "Whether the user is an admin" @@ -61,6 +65,9 @@ "type": "boolean", "description": "Whether the user can create a stream" }, + "maxBitRate": { + "type": "integer" + }, "videoConversionRole": { "type": "boolean", "description": "Whether the user can convert videos" @@ -69,13 +76,6 @@ "type": "string", "format": "date-time", "description": "Last time the avatar was changed [ISO 8601]" - }, - "folder": { - "type": "array", - "items": { - "type": "integer" - }, - "description": "Folder ID(s)" } }, "required": [ @@ -94,4 +94,4 @@ "shareRole", "videoConversionRole" ] -} \ No newline at end of file +} From 965b07ee8fbf712db02be22e0c885e463d82d257 Mon Sep 17 00:00:00 2001 From: Deluan Date: Wed, 11 Feb 2026 18:16:35 -0500 Subject: [PATCH 2/6] Fix description inconsistencies from PR review feedback - Child.json: "played" refers to media, not album - AlbumID3.json: "starred" means starred/favorited, not added - Share.json: fix grammar "A list of shares" --- openapi/schemas/AlbumID3.json | 2 +- openapi/schemas/Child.json | 2 +- openapi/schemas/Share.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openapi/schemas/AlbumID3.json b/openapi/schemas/AlbumID3.json index 4b3e1051..6cfb7b10 100644 --- a/openapi/schemas/AlbumID3.json +++ b/openapi/schemas/AlbumID3.json @@ -29,7 +29,7 @@ "starred": { "type": "string", "format": "date-time", - "description": "Date the album was added. [ISO 8601]" + "description": "Date the album was starred. [ISO 8601]" }, "duration": { "type": "integer", diff --git a/openapi/schemas/Child.json b/openapi/schemas/Child.json index abd920ff..599be710 100644 --- a/openapi/schemas/Child.json +++ b/openapi/schemas/Child.json @@ -86,7 +86,7 @@ "played": { "type": "string", "format": "date-time", - "description": "Date the album was last played. [ISO 8601]" + "description": "Date the media was last played. [ISO 8601]" }, "discNumber": { "type": "integer", diff --git a/openapi/schemas/Share.json b/openapi/schemas/Share.json index 51a0f04e..b12d4eb2 100644 --- a/openapi/schemas/Share.json +++ b/openapi/schemas/Share.json @@ -32,7 +32,7 @@ "items": { "$ref": "./Child.json" }, - "description": "A list of share" + "description": "A list of shares" }, "expires": { "type": "string", From a3ba94df0575eebbcd5eeebc66c39c757663d072 Mon Sep 17 00:00:00 2001 From: Deluan Date: Wed, 11 Feb 2026 18:26:53 -0500 Subject: [PATCH 3/6] Fix JukeboxStatus: rename volume to gain and fix type The original Subsonic XSD and OpenSubsonic docs both use "gain" (float), not "volume" (integer). Fix the field name and change type from integer to number to match the 0.0-1.0 float range. --- openapi/schemas/JukeboxStatus.json | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/openapi/schemas/JukeboxStatus.json b/openapi/schemas/JukeboxStatus.json index 455bd547..8fed47f4 100644 --- a/openapi/schemas/JukeboxStatus.json +++ b/openapi/schemas/JukeboxStatus.json @@ -18,10 +18,9 @@ "type": "integer", "description": "The current position of the track in seconds" }, - "volume": { - "type": "integer", + "gain": { + "type": "number", "description": "Volume, in a range of [0.0, 1.0]", - "format": "float", "minimum": 0.0, "maximum": 1.0 } @@ -29,6 +28,6 @@ "required": [ "currentIndex", "playing", - "volume" + "gain" ] } From 1aacec450e5fb8c8560a142696417910a4f2f4c2 Mon Sep 17 00:00:00 2001 From: Deluan Date: Wed, 11 Feb 2026 18:27:54 -0500 Subject: [PATCH 4/6] Fix Child averageRating minimum: 0 -> 1 to match XSD The original Subsonic XSD defines AverageRating as xs:double with minInclusive=1.0, and the description already says "[1.0-5.0]". Directory and Artist schemas already use minimum: 1; only Child had the incorrect minimum: 0. --- openapi/schemas/Child.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openapi/schemas/Child.json b/openapi/schemas/Child.json index 599be710..4d988aed 100644 --- a/openapi/schemas/Child.json +++ b/openapi/schemas/Child.json @@ -221,7 +221,7 @@ "averageRating": { "type": "number", "description": "The average rating of the media [1.0-5.0]", - "minimum": 0, + "minimum": 1, "maximum": 5 }, "bookmarkPosition": { From c79da7e431caae58b98d217d2d3adfbc414a8760 Mon Sep 17 00:00:00 2001 From: Deluan Date: Wed, 11 Feb 2026 19:32:44 -0500 Subject: [PATCH 5/6] Reorder Child.md doc table to match schema property order Aligns the documentation table with the Child.json schema ordering. Also fixes "played" description from "album" to "media". --- content/en/docs/Responses/Child.md | 60 +++++++++++++++--------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/content/en/docs/Responses/Child.md b/content/en/docs/Responses/Child.md index e66b7e59..9fdedd42 100644 --- a/content/en/docs/Responses/Child.md +++ b/content/en/docs/Responses/Child.md @@ -164,52 +164,52 @@ description: > | `isDir` | `boolean` | **Yes** | | The media is a directory | | `title` | `string` | **Yes** | | The media name. | | `album` | `string` | No | | The album name. | -| `artist` | `string` | No | | The artist name. | -| `track` | `int` | No | | The track number. | +| `artist` | `string` | No | | The artist name. | +| `track` | `int` | No | | The track number. | | `year` | `int` | No | | The media year. | -| `genre` | `string` | No | | The media genre| -| `coverArt` | `string` | No | | A covertArt id. | -| `size` | `long` | No | | A file size of the media. | -| `contentType` | `string` | No | | The mimeType of the media. | -| `suffix` | `string` | No | | The file suffix of the media. | -| `transcodedContentType` | `string` | No | | The transcoded mediaType if transcoding should happen. | -| `transcodedSuffix` | `string` | No | | The file suffix of the transcoded media. | +| `coverArt` | `string` | No | | A covertArt id. | +| `size` | `long` | No | | A file size of the media. | +| `contentType` | `string` | No | | The mimeType of the media. | +| `suffix` | `string` | No | | The file suffix of the media. | +| `starred` | `string` | No | | Date the media was starred. [ISO 8601] | | `duration` | `int` | No | | The duration of the media in seconds. | | `bitRate` | `int` | No | | The bitrate of the media. | | `bitDepth` | `int` | No | **Yes** | The bit depth of the media. | | `samplingRate` | `int` | No | **Yes** | The sampling rate of the media. | | `channelCount` | `int` | No | **Yes** | The number of channels of the media. | | `path` | `string` | No | | The full path of the media. | -| `isVideo` | `boolean` | No | | Media is a video | -| `userRating` | `int` | No | | The user rating of the media [1-5] | -| `averageRating` | `number` | No | | The average rating of the media [1.0-5.0] | | `playCount` | `long` | No | | The play count. | +| `played` | `string` | No | **Yes** | Date the media was last played. [ISO 8601] | | `discNumber` | `int` | No | | The disc number. | | `created` | `string` | No | | Date the media was created. [ISO 8601] | -| `starred` | `string` | No | | Date the media was starred. [ISO 8601] | | `albumId` | `string` | No | | The corresponding album id | | `artistId` | `string` | No | | The corresponding artist id | -| `type` | `string` | No | | The generic type of media [music/podcast/audiobook/video]| +| `type` | `string` | No | | The generic type of media [music/podcast/audiobook/video] | | `mediaType` | `string` | No | **Yes** | The actual media type [song/album/artist] **Note**: If you support `musicBrainzId` you must support this field to ensure clients knows what the ID refers to. | +| `isVideo` | `boolean` | No | | Media is a video | +| `bpm` | `int` | No | **Yes** | The BPM of the song. | +| `comment` | `string` | No | **Yes** | The comment tag of the song. | +| `sortName` | `string` | No | **Yes** | The song sort name. | +| `musicBrainzId` | `string` | No | **Yes** | The track MusicBrainzID. | +| `isrc` | Array of `string` | No | **Yes** | The track ISRC(s). | +| `genres` | Array of [`ItemGenre`](../itemgenre) | No | **Yes** | The list of all genres of the song. | +| `artists` | Array of [`ArtistID3`](../artistid3) | No | **Yes** | The list of all song artists of the song. (Note: Only the required [`ArtistID3`](../artistid3) fields should be returned by default) | +| `displayArtist` | `string` | No | **Yes** | The single value display artist. | +| `albumArtists` | Array of [`ArtistID3`](../artistid3) | No | **Yes** | The list of all album artists of the song. (Note: Only the required [`ArtistID3`](../artistid3) fields should be returned by default) | +| `displayAlbumArtist` | `string` | No | **Yes** | The single value display album artist. | +| `contributors` | Array of [`Contributor`](../contributor) | No | **Yes** | The list of all contributor artists of the song. | +| `displayComposer` | `string` | No | **Yes** | The single value display composer. | +| `moods` | Array of `string` | No | **Yes** | The list of all moods of the song. | +| `explicitStatus` | `string` | No | **Yes** | Returns "explicit", "clean" or "". (For songs extracted from tags "ITUNESADVISORY": 1 = explicit, 2 = clean, MP4 "rtng": 1 or 4 = explicit, 2 = clean. See [`albumID3`](../albumid3) for albums) | +| `replayGain` | [`ReplayGain`](../replaygain) | No | **Yes** | The replaygain data of the song. | +| `genre` | `string` | No | | The media genre | +| `transcodedContentType` | `string` | No | | The transcoded mediaType if transcoding should happen. | +| `transcodedSuffix` | `string` | No | | The file suffix of the transcoded media. | +| `userRating` | `int` | No | | The user rating of the media [1-5] | +| `averageRating` | `number` | No | | The average rating of the media [1.0-5.0] | | `bookmarkPosition` | `long` | No | | The bookmark position in seconds | | `originalWidth` | `int` | No | | The video original Width | | `originalHeight` | `int` | No | | The video original Height | -| `played` | `string` | No | **Yes** | Date the album was last played. [ISO 8601]| -| `bpm` | `int` | No | **Yes** | The BPM of the song. | -| `comment` | `string` | No | **Yes** | The comment tag of the song. | -| `sortName` | `string` | No | **Yes** | The song sort name. | -| `musicBrainzId` | `string` | No | **Yes** | The track MusicBrainzID. | -| `isrc` | Array of `string` | No | **Yes** | The track ISRC(s). | -| `genres` | Array of [`ItemGenre`](../itemgenre) | No | **Yes** | The list of all genres of the song. | -| `artists` | Array of [`ArtistID3`](../artistid3) | No | **Yes** | The list of all song artists of the song. (Note: Only the required [`ArtistID3`](../artistid3) fields should be returned by default)| -| `displayArtist` | `string` | No | **Yes** | The single value display artist. | -| `albumArtists` | Array of [`ArtistID3`](../artistid3) | No | **Yes** | The list of all album artists of the song. (Note: Only the required [`ArtistID3`](../artistid3) fields should be returned by default)| -| `displayAlbumArtist` | `string` | No | **Yes** | The single value display album artist. | -| `contributors` | Array of [`Contributor`](../contributor) | No | **Yes** | The list of all contributor artists of the song. | -| `displayComposer` | `string` | No | **Yes** | The single value display composer. | -| `moods` | Array of `string` | No | **Yes** | The list of all moods of the song. | -| `replayGain` | [`ReplayGain`](../replaygain) | No | **Yes** | The replaygain data of the song. | -| `explicitStatus` | `string` | No | **Yes** | Returns "explicit", "clean" or "". (For songs extracted from tags "ITUNESADVISORY": 1 = explicit, 2 = clean, MP4 "rtng": 1 or 4 = explicit, 2 = clean. See [`albumID3`](../albumid3) for albums) | {{< alert color="warning" title="OpenSubsonic" >}} New fields are added: From 6933fa4bd75c1fa133469ed82f91085676f1cf8e Mon Sep 17 00:00:00 2001 From: Deluan Date: Wed, 11 Feb 2026 19:42:42 -0500 Subject: [PATCH 6/6] Add missing email field to User schema and doc table The email field is defined in the original Subsonic XSD and was already present in the doc examples, but was missing from both the OpenAPI schema and the doc table. --- content/en/docs/Responses/user.md | 1 + openapi/schemas/User.json | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/content/en/docs/Responses/user.md b/content/en/docs/Responses/user.md index 2cd4c620..d55e08b1 100644 --- a/content/en/docs/Responses/user.md +++ b/content/en/docs/Responses/user.md @@ -56,6 +56,7 @@ description: > | Field | Type | Req. | OpenS. | Details | | --------------------- | -------------- | ------- | ------ | -------------------------------------------- | | `username` | `string` | **Yes** | | Username | +| `email` | `string` | No | | The user's email address | | `scrobblingEnabled` | `boolean` | **Yes** | | Whether scrobling is enabled for the user | | `maxBitRate` | `int` | No | | | | `adminRole` | `boolean` | **Yes** | | Whether the user is an admin | diff --git a/openapi/schemas/User.json b/openapi/schemas/User.json index a6baba79..4423ff93 100644 --- a/openapi/schemas/User.json +++ b/openapi/schemas/User.json @@ -17,6 +17,10 @@ "type": "string", "description": "Username" }, + "email": { + "type": "string", + "description": "The user's email address" + }, "scrobblingEnabled": { "type": "boolean", "description": "Scrobbling enabled"