{"components":{"responses":{},"schemas":{"PlayToken":{"example":"UGxheVRva2Vu","format":"base64","title":"PlayToken","type":"string","x-struct":"Elixir.OnduWeb.Schemas.PlayToken","x-validate":null},"UpdatePlaylistItemsResponse":{"additionalProperties":false,"properties":{"added":{"items":{"$ref":"#/components/schemas/PlaylistItem"},"type":"array","x-struct":null,"x-validate":null},"moved":{"items":{"$ref":"#/components/schemas/PlaylistItem"},"type":"array","x-struct":null,"x-validate":null},"ok":{"example":true,"type":"boolean","x-struct":null,"x-validate":null},"removed":{"items":{"$ref":"#/components/schemas/PlaylistItemId"},"type":"array","x-struct":null,"x-validate":null}},"required":["ok","added","moved","removed"],"title":"UpdatePlaylistItemsResponse","type":"object","x-struct":"Elixir.OnduWeb.Schemas.UpdatePlaylistItemsResponse","x-validate":null},"UpdatePlaylistError":{"additionalProperties":false,"description":"A response containing validation errors keyed by field name","properties":{"fields":{"additionalProperties":{"$ref":"#/components/schemas/ValidationError"},"description":"Map of field names to their validation errors","example":{"name":{"message":"can't be blank"}},"type":"object","x-struct":null,"x-validate":null},"ok":{"example":false,"type":"boolean","x-struct":null,"x-validate":null}},"required":["fields"],"title":"UpdatePlaylistError","type":"object","x-struct":"Elixir.OnduWeb.Schemas.UpdatePlaylistError","x-validate":null},"AnnotationPage":{"additionalProperties":false,"properties":{"__subtype":{"default":"annotation","description":"Paginated entity type","enum":["annotation"],"type":"string","x-struct":null,"x-validate":null},"__type":{"default":"page","description":"Entity type","enum":["page"],"type":"string","x-struct":null,"x-validate":null},"entries":{"items":{"$ref":"#/components/schemas/Annotation"},"type":"array","x-struct":null,"x-validate":null},"pageNumber":{"example":1,"minimum":1,"type":"integer","x-struct":null,"x-validate":null},"pageSize":{"example":25,"minimum":1,"type":"integer","x-struct":null,"x-validate":null},"totalEntries":{"example":142,"minimum":0,"type":"integer","x-struct":null,"x-validate":null},"totalPages":{"example":6,"minimum":0,"type":"integer","x-struct":null,"x-validate":null}},"required":["__type","__subtype","entries","pageNumber","pageSize","totalEntries","totalPages"],"title":"AnnotationPage","type":"object","x-struct":"Elixir.OnduWeb.Schemas.AnnotationPage","x-validate":null},"UpdateSettingsRequest":{"additionalProperties":false,"description":"Application settings","properties":{"musicPath":{"example":"/music","type":"string","x-struct":null,"x-validate":null},"pollInterval":{"description":"How many minutes between scanning the library.","example":60,"type":"integer","x-struct":null,"x-validate":null},"scanType":{"enum":["full","quick"],"type":"string","x-struct":null,"x-validate":null},"stripSortPrefixes":{"items":{"type":"string","x-struct":null,"x-validate":null},"type":"array","x-struct":null,"x-validate":null}},"title":"UpdateSettingsRequest","type":"object","x-struct":"Elixir.OnduWeb.Schemas.UpdateSettingsRequest","x-validate":null},"Playlist":{"additionalProperties":false,"description":"A playlist (items not embedded, fetch separately)","properties":{"__type":{"default":"playlist","description":"Entity type","enum":["playlist"],"type":"string","x-struct":null,"x-validate":null},"id":{"$ref":"#/components/schemas/PlaylistId"},"insertedAt":{"format":"date-time","type":"string","x-struct":null,"x-validate":null},"isFolder":{"example":false,"type":"boolean","x-struct":null,"x-validate":null},"name":{"example":"My Favourite Tracks","type":"string","x-struct":null,"x-validate":null},"parentId":{"allOf":[{"$ref":"#/components/schemas/PlaylistId"}],"description":"The parent playlist id (if applicable)","nullable":true,"x-struct":null,"x-validate":null},"trackCount":{"description":"This contains the amount of tracks inside this playlist. If it is a folder it will always be 0.","example":42,"type":"integer","x-struct":null,"x-validate":null}},"required":["__type","id","name","isFolder","parentId","trackCount","insertedAt"],"title":"Playlist","type":"object","x-struct":"Elixir.OnduWeb.Schemas.Playlist","x-validate":null},"UpdateSettingsResponse":{"additionalProperties":false,"properties":{"ok":{"example":true,"type":"boolean","x-struct":null,"x-validate":null},"settings":{"$ref":"#/components/schemas/Settings"}},"required":["ok","settings"],"title":"UpdateSettingsResponse","type":"object","x-struct":"Elixir.OnduWeb.Schemas.UpdateSettingsResponse","x-validate":null},"UpdatePlaylistRequest":{"additionalProperties":false,"properties":{"name":{"minLength":1,"type":"string","x-struct":null,"x-validate":null},"parentId":{"$ref":"#/components/schemas/PlaylistId"}},"title":"UpdatePlaylistRequest","type":"object","x-struct":"Elixir.OnduWeb.Schemas.UpdatePlaylistRequest","x-validate":null},"UpdatePasswordResponse":{"additionalProperties":false,"description":"A successful password change just returns ok.","properties":{"ok":{"example":true,"type":"boolean","x-struct":null,"x-validate":null},"sessionToken":{"$ref":"#/components/schemas/SessionToken"}},"required":["ok","sessionToken"],"title":"UpdatePasswordResponse","type":"object","x-struct":"Elixir.OnduWeb.Schemas.UpdatePasswordResponse","x-validate":null},"ScanResponse":{"additionalProperties":false,"description":"Confirms asynchronous file scanner has started.","properties":{"ok":{"example":true,"type":"boolean","x-struct":null,"x-validate":null}},"required":["ok"],"title":"ScanResponse","type":"object","x-struct":"Elixir.OnduWeb.Schemas.ScanResponse","x-validate":null},"Notices":{"additionalProperties":false,"properties":{"notices":{"items":{"$ref":"#/components/schemas/Notice"},"type":"array","x-struct":null,"x-validate":null}},"required":["notices"],"title":"Notices","type":"object","x-struct":"Elixir.OnduWeb.Schemas.Notices","x-validate":null},"FlatTrack":{"additionalProperties":false,"description":"A flat representation of a track (without its artist/album embedded).","properties":{"__type":{"default":"track","description":"Entity type","enum":["track"],"type":"string","x-struct":null,"x-validate":null},"albumArtistId":{"$ref":"#/components/schemas/ArtistId"},"albumId":{"$ref":"#/components/schemas/AlbumId"},"artistId":{"$ref":"#/components/schemas/ArtistId"},"disc":{"example":1,"nullable":true,"type":"integer","x-struct":null,"x-validate":null},"downloadUrl":{"example":"https://example.com/download/...","type":"string","x-struct":null,"x-validate":null},"duration":{"example":123.45,"type":"number","x-struct":null,"x-validate":null},"id":{"$ref":"#/components/schemas/TrackId"},"insertedAt":{"format":"date-time","type":"string","x-struct":null,"x-validate":null},"lastPlayedAt":{"description":"When it was last played, null when never played","format":"date-time","nullable":true,"type":"string","x-struct":null,"x-validate":null},"loudness":{"allOf":[{"$ref":"#/components/schemas/Loudness"}],"description":"The measured loudness, null until measured (or when measuring failed)","nullable":true,"x-struct":null,"x-validate":null},"mimetype":{"example":"audio/mp3","type":"string","x-struct":null,"x-validate":null},"name":{"example":"The Beatles","type":"string","x-struct":null,"x-validate":null},"number":{"example":1,"nullable":true,"type":"integer","x-struct":null,"x-validate":null},"playCount":{"description":"How often it was played","example":3,"type":"integer","x-struct":null,"x-validate":null},"relativeFilePath":{"description":"This is the relative file path of this track inside your library.\n","example":"The Beatles/Revolver/01 Taxman.m4a","type":"string","x-struct":null,"x-validate":null},"streamUrl":{"example":"https://example.com/stream/...","type":"string","x-struct":null,"x-validate":null}},"required":["__type","id","artistId","albumArtistId","albumId","name","disc","number","duration","loudness","playCount","lastPlayedAt","mimetype","downloadUrl","streamUrl","insertedAt"],"title":"FlatTrack","type":"object","x-struct":"Elixir.OnduWeb.Schemas.FlatTrack","x-validate":null},"Loudness":{"additionalProperties":false,"description":"The measured loudness of a track or album (ITU-R BS.1770 / EBU R128), clients\ncan use this for volume normalization. To normalize to a target loudness apply a gain\nof `target - lufs` dB, and when boosting keep it below `-peak` dB to avoid\nclipping.\n","properties":{"lufs":{"description":"Integrated loudness in LUFS","example":-9.2,"type":"number","x-struct":null,"x-validate":null},"peak":{"description":"True peak in dBFS, null for digital silence","example":-0.3,"nullable":true,"type":"number","x-struct":null,"x-validate":null}},"required":["lufs","peak"],"title":"Loudness","type":"object","x-struct":"Elixir.OnduWeb.Schemas.Loudness","x-validate":null},"PutAnnotationsRequest":{"additionalProperties":false,"properties":{"entries":{"items":{"additionalProperties":false,"properties":{"data":{"additionalProperties":true,"description":"Replaces the data (at most 4KB as JSON), null removes the annotation.","nullable":true,"type":"object","x-struct":null,"x-validate":null},"entityId":{"format":"uuid","type":"string","x-struct":null,"x-validate":null}},"required":["entityId","data"],"type":"object","x-struct":null,"x-validate":null},"maxItems":500,"type":"array","x-struct":null,"x-validate":null}},"required":["entries"],"title":"PutAnnotationsRequest","type":"object","x-struct":"Elixir.OnduWeb.Schemas.PutAnnotationsRequest","x-validate":null},"FlatAlbum":{"additionalProperties":false,"description":"A flat representation of an album (without its tracks embedded).","properties":{"__type":{"default":"album","description":"Entity type","enum":["album"],"type":"string","x-struct":null,"x-validate":null},"artistId":{"$ref":"#/components/schemas/ArtistId"},"artwork":{"description":"Available variants of the artwork.","items":{"$ref":"#/components/schemas/ArtworkImage"},"type":"array","x-struct":null,"x-validate":null},"id":{"$ref":"#/components/schemas/AlbumId"},"insertedAt":{"format":"date-time","type":"string","x-struct":null,"x-validate":null},"isUnknown":{"example":false,"type":"boolean","x-struct":null,"x-validate":null},"loudness":{"allOf":[{"$ref":"#/components/schemas/Loudness"}],"description":"The loudness of the whole album, to use one gain for all tracks when the\nalbum is played in sequence. Approximated from the loudness of the tracks,\nnull until all tracks are measured.\n","nullable":true,"x-struct":null,"x-validate":null},"name":{"example":"With the Beatles","type":"string","x-struct":null,"x-validate":null},"releaseYear":{"example":2,"nullable":true,"type":"integer","x-struct":null,"x-validate":null},"slug":{"example":"with-the-beatles","type":"string","x-struct":null,"x-validate":null},"sortName":{"example":"With the Beatles","type":"string","x-struct":null,"x-validate":null},"trackCount":{"example":14,"type":"integer","x-struct":null,"x-validate":null}},"required":["__type","id","artistId","name","sortName","slug","artwork","releaseYear","loudness","trackCount","isUnknown","insertedAt"],"title":"FlatAlbum","type":"object","x-struct":"Elixir.OnduWeb.Schemas.FlatAlbum","x-validate":null},"SyncCursor":{"description":"Use the cursor in your next request to get changes that happened since this cursor.","example":"bm90IGEgcmVhbCBjdXJzb3I=","format":"base64","title":"SyncCursor","type":"string","x-struct":"Elixir.OnduWeb.Schemas.SyncCursor","x-validate":null},"Error":{"additionalProperties":false,"properties":{"error":{"example":"Unauthorized","type":"string","x-struct":null,"x-validate":null}},"required":["error"],"title":"Error","type":"object","x-struct":"Elixir.OnduWeb.Schemas.Error","x-validate":null},"PositionedItem":{"additionalProperties":false,"properties":{"itemId":{"$ref":"#/components/schemas/PlaylistItemId"},"position":{"$ref":"#/components/schemas/FractionalIndex"}},"required":["position","itemId"],"title":"PositionedItem","type":"object","x-struct":"Elixir.OnduWeb.Schemas.PositionedItem","x-validate":null},"LoginError":{"additionalProperties":false,"description":"A response containing validation errors keyed by field name","properties":{"fields":{"additionalProperties":{"$ref":"#/components/schemas/ValidationError"},"description":"Map of field names to their validation errors","example":{"name":{"message":"can't be blank"}},"type":"object","x-struct":null,"x-validate":null},"ok":{"example":false,"type":"boolean","x-struct":null,"x-validate":null}},"required":["fields"],"title":"LoginError","type":"object","x-struct":"Elixir.OnduWeb.Schemas.LoginError","x-validate":null},"UpdatePasswordError":{"additionalProperties":false,"description":"A response containing validation errors keyed by field name","properties":{"fields":{"additionalProperties":{"$ref":"#/components/schemas/ValidationError"},"description":"Map of field names to their validation errors","example":{"password":{"message":"can't be blank"}},"type":"object","x-struct":null,"x-validate":null},"ok":{"example":false,"type":"boolean","x-struct":null,"x-validate":null}},"required":["fields"],"title":"UpdatePasswordError","type":"object","x-struct":"Elixir.OnduWeb.Schemas.UpdatePasswordError","x-validate":null},"FractionalIndex":{"description":"The position of the item in the playlist using fractional indexing\nusing the default base-62 alphabet (`0-9A-Za-z`).\n","example":"a0","maxLength":100,"minLength":2,"pattern":"^[A-Za-z][0-9A-Za-z]*$","title":"FractionalIndex","type":"string","x-struct":"Elixir.OnduWeb.Schemas.FractionalIndex","x-validate":null},"PlaylistId":{"description":"The UUID for a specific Playlist.","example":"c93bfb8e-23fc-41d5-a582-72f823e094d1","format":"uuid","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$","title":"PlaylistId","type":"string","x-struct":"Elixir.OnduWeb.Schemas.PlaylistId","x-validate":null},"SignupError":{"additionalProperties":false,"description":"A response containing validation errors keyed by field name","properties":{"fields":{"additionalProperties":{"$ref":"#/components/schemas/ValidationError"},"description":"Map of field names to their validation errors","example":{"name":{"message":"can't be blank"}},"type":"object","x-struct":null,"x-validate":null},"ok":{"example":false,"type":"boolean","x-struct":null,"x-validate":null}},"required":["fields"],"title":"SignupError","type":"object","x-struct":"Elixir.OnduWeb.Schemas.SignupError","x-validate":null},"TranscodingPreset":{"additionalProperties":false,"properties":{"bitrate":{"example":192,"type":"integer","x-struct":null,"x-validate":null},"codec":{"example":"opus","type":"string","x-struct":null,"x-validate":null},"container":{"example":"ogg","type":"string","x-struct":null,"x-validate":null},"extension":{"example":"opus","type":"string","x-struct":null,"x-validate":null},"id":{"description":"The identifier for the preset","example":"default_ogg","type":"string","x-struct":null,"x-validate":null},"mimetype":{"example":"audio/ogg","type":"string","x-struct":null,"x-validate":null},"name":{"description":"Display name","example":"Default (192kbps)","type":"string","x-struct":null,"x-validate":null}},"required":["id","name","codec","container","mimetype","extension","bitrate"],"title":"TranscodingPreset","type":"object","x-struct":"Elixir.OnduWeb.Schemas.TranscodingPreset","x-validate":null},"CreatePlaylistRequest":{"additionalProperties":false,"properties":{"isFolder":{"default":false,"type":"boolean","x-struct":null,"x-validate":null},"name":{"minLength":1,"type":"string","x-struct":null,"x-validate":null},"parentId":{"$ref":"#/components/schemas/PlaylistId"}},"required":["name"],"title":"CreatePlaylistRequest","type":"object","x-struct":"Elixir.OnduWeb.Schemas.CreatePlaylistRequest","x-validate":null},"UpdatePlaylistItemsRequest":{"additionalProperties":false,"properties":{"add":{"items":{"$ref":"#/components/schemas/PositionedTrack"},"type":"array","x-struct":null,"x-validate":null},"move":{"items":{"$ref":"#/components/schemas/PositionedItem"},"type":"array","x-struct":null,"x-validate":null},"remove":{"items":{"$ref":"#/components/schemas/PlaylistItemId"},"type":"array","x-struct":null,"x-validate":null}},"title":"UpdatePlaylistItemsRequest","type":"object","x-struct":"Elixir.OnduWeb.Schemas.UpdatePlaylistItemsRequest","x-validate":null},"UserId":{"description":"The UUID for a specific User.","example":"52745d24-8c68-4550-b217-ce65440df47b","format":"uuid","title":"UserId","type":"string","x-struct":"Elixir.OnduWeb.Schemas.UserId","x-validate":null},"PlaylistItem":{"additionalProperties":false,"description":"An item inside a playlist","properties":{"__type":{"default":"playlistItem","description":"Entity type","enum":["playlistItem"],"type":"string","x-struct":null,"x-validate":null},"id":{"$ref":"#/components/schemas/PlaylistItemId"},"insertedAt":{"format":"date-time","type":"string","x-struct":null,"x-validate":null},"playlistId":{"$ref":"#/components/schemas/PlaylistId"},"position":{"$ref":"#/components/schemas/FractionalIndex"},"trackId":{"$ref":"#/components/schemas/TrackId"}},"required":["__type","id","position","playlistId","trackId","insertedAt"],"title":"PlaylistItem","type":"object","x-struct":"Elixir.OnduWeb.Schemas.PlaylistItem","x-validate":null},"UpdateSettingsError":{"additionalProperties":false,"description":"A response containing validation errors keyed by field name","properties":{"fields":{"additionalProperties":{"$ref":"#/components/schemas/ValidationError"},"description":"Map of field names to their validation errors","example":{"name":{"message":"can't be blank"}},"type":"object","x-struct":null,"x-validate":null},"ok":{"example":false,"type":"boolean","x-struct":null,"x-validate":null}},"required":["ok","fields"],"title":"UpdateSettingsError","type":"object","x-struct":"Elixir.OnduWeb.Schemas.UpdateSettingsError","x-validate":null},"UnknownTracksError":{"additionalProperties":false,"example":{"error":"unknown_tracks","trackIds":["t3"]},"properties":{"error":{"enum":["unknown_tracks"],"type":"string","x-struct":null,"x-validate":null},"ok":{"example":false,"type":"boolean","x-struct":null,"x-validate":null},"trackIds":{"items":{"type":"string","x-struct":null,"x-validate":null},"type":"array","x-struct":null,"x-validate":null}},"required":["error","trackIds"],"title":"UnknownTracksError","type":"object","x-struct":"Elixir.OnduWeb.Schemas.UpdatePlaylistItemsError.UnknownTracks","x-validate":null},"Annotation":{"additionalProperties":false,"properties":{"data":{"additionalProperties":true,"example":{"mbid":"..."},"type":"object","x-struct":null,"x-validate":null},"entityId":{"format":"uuid","type":"string","x-struct":null,"x-validate":null},"updatedAt":{"format":"date-time","type":"string","x-struct":null,"x-validate":null}},"required":["entityId","data","updatedAt"],"title":"Annotation","type":"object","x-struct":"Elixir.OnduWeb.Schemas.Annotation","x-validate":null},"PlaylistPage":{"additionalProperties":false,"properties":{"__subtype":{"default":"playlist","description":"Paginated entity type","enum":["playlist"],"type":"string","x-struct":null,"x-validate":null},"__type":{"default":"page","description":"Entity type","enum":["page"],"type":"string","x-struct":null,"x-validate":null},"entries":{"items":{"$ref":"#/components/schemas/Playlist"},"type":"array","x-struct":null,"x-validate":null},"pageNumber":{"example":1,"minimum":1,"type":"integer","x-struct":null,"x-validate":null},"pageSize":{"example":25,"minimum":1,"type":"integer","x-struct":null,"x-validate":null},"totalEntries":{"example":142,"minimum":0,"type":"integer","x-struct":null,"x-validate":null},"totalPages":{"example":6,"minimum":0,"type":"integer","x-struct":null,"x-validate":null}},"required":["__type","__subtype","entries","pageNumber","pageSize","totalEntries","totalPages"],"title":"PlaylistPage","type":"object","x-struct":"Elixir.OnduWeb.Schemas.PlaylistPage","x-validate":null},"PlayTokenResponse":{"additionalProperties":false,"description":"Returns a new `playToken` and `expiresIn` (in seconds) so the client knows when to get a new one.","properties":{"expiresIn":{"description":"Amount of seconds before this PlayToken will expire.","example":3600,"type":"integer","x-struct":null,"x-validate":null},"ok":{"example":true,"type":"boolean","x-struct":null,"x-validate":null},"playToken":{"$ref":"#/components/schemas/PlayToken"}},"required":["ok","expiresIn","playToken"],"title":"PlayTokenResponse","type":"object","x-struct":"Elixir.OnduWeb.Schemas.PlayTokenResponse","x-validate":null},"Artist":{"additionalProperties":false,"description":"An artist","properties":{"__type":{"default":"artist","description":"Entity type","enum":["artist"],"type":"string","x-struct":null,"x-validate":null},"albumCount":{"example":2,"type":"integer","x-struct":null,"x-validate":null},"artwork":{"description":"Available variants of the uploaded artwork, empty without artwork.","items":{"$ref":"#/components/schemas/ArtworkImage"},"type":"array","x-struct":null,"x-validate":null},"id":{"$ref":"#/components/schemas/ArtistId"},"insertedAt":{"format":"date-time","type":"string","x-struct":null,"x-validate":null},"name":{"example":"The Beatles","type":"string","x-struct":null,"x-validate":null},"slug":{"example":"the-beatles","type":"string","x-struct":null,"x-validate":null},"sortName":{"example":"Beatles","type":"string","x-struct":null,"x-validate":null}},"required":["__type","id","name","sortName","slug","albumCount","artwork","insertedAt"],"title":"Artist","type":"object","x-struct":"Elixir.OnduWeb.Schemas.Artist","x-validate":null},"PlaylistIsFolderError":{"additionalProperties":false,"example":{"error":"playlist_is_folder"},"properties":{"error":{"enum":["playlist_is_folder"],"type":"string","x-struct":null,"x-validate":null},"ok":{"example":false,"type":"boolean","x-struct":null,"x-validate":null}},"required":["error"],"title":"PlaylistIsFolderError","type":"object","x-struct":"Elixir.OnduWeb.Schemas.UpdatePlaylistItemsError.PlaylistIsFolder","x-validate":null},"TooManyOperationsError":{"additionalProperties":false,"example":{"error":"too_many_operations"},"properties":{"count":{"example":150,"type":"integer","x-struct":null,"x-validate":null},"error":{"enum":["too_many_operations"],"type":"string","x-struct":null,"x-validate":null},"limit":{"example":100,"type":"integer","x-struct":null,"x-validate":null},"ok":{"example":false,"type":"boolean","x-struct":null,"x-validate":null}},"required":["error"],"title":"TooManyOperationsError","type":"object","x-struct":"Elixir.OnduWeb.Schemas.UpdatePlaylistItemsError.TooManyOperations","x-validate":null},"RecordPlaysRequest":{"additionalProperties":false,"properties":{"plays":{"items":{"additionalProperties":false,"properties":{"id":{"description":"Generated by the client, should be idempotent so we can ignore\nplays that have already been stored and sent again.\n","format":"uuid","type":"string","x-struct":null,"x-validate":null},"playedAt":{"description":"When the track started playing.","format":"date-time","type":"string","x-struct":null,"x-validate":null},"trackId":{"$ref":"#/components/schemas/TrackId"}},"required":["id","trackId","playedAt"],"type":"object","x-struct":null,"x-validate":null},"maxItems":500,"type":"array","x-struct":null,"x-validate":null}},"required":["plays"],"title":"RecordPlaysRequest","type":"object","x-struct":"Elixir.OnduWeb.Schemas.RecordPlaysRequest","x-validate":null},"LoginResponse":{"additionalProperties":false,"description":"A successful login attempt returns currentUser and sessionToken","properties":{"currentUser":{"$ref":"#/components/schemas/User"},"ok":{"example":true,"type":"boolean","x-struct":null,"x-validate":null},"sessionToken":{"$ref":"#/components/schemas/SessionToken"}},"required":["ok","sessionToken","currentUser"],"title":"LoginResponse","type":"object","x-struct":"Elixir.OnduWeb.Schemas.LoginResponse","x-validate":null},"ServerInfo":{"additionalProperties":false,"properties":{"apiVersion":{"description":"Only changes when the API changes in a way that breaks existing clients","example":1,"type":"integer","x-struct":null,"x-validate":null},"defaultPreset":{"description":"The preset that will be used when none is specified","example":"default_ogg","type":"string","x-struct":null,"x-validate":null},"presets":{"description":"List of available transcoding presets","items":{"$ref":"#/components/schemas/TranscodingPreset"},"type":"array","x-struct":null,"x-validate":null},"version":{"description":"Version of the server","example":"1.3.0","type":"string","x-struct":null,"x-validate":null}},"required":["version","apiVersion","defaultPreset","presets"],"title":"ServerInfo","type":"object","x-struct":"Elixir.OnduWeb.Schemas.ServerInfo","x-validate":null},"TrackPage":{"additionalProperties":false,"properties":{"__subtype":{"default":"track","description":"Paginated entity type","enum":["track"],"type":"string","x-struct":null,"x-validate":null},"__type":{"default":"page","description":"Entity type","enum":["page"],"type":"string","x-struct":null,"x-validate":null},"entries":{"items":{"$ref":"#/components/schemas/Track"},"type":"array","x-struct":null,"x-validate":null},"pageNumber":{"example":1,"minimum":1,"type":"integer","x-struct":null,"x-validate":null},"pageSize":{"example":25,"minimum":1,"type":"integer","x-struct":null,"x-validate":null},"totalEntries":{"example":142,"minimum":0,"type":"integer","x-struct":null,"x-validate":null},"totalPages":{"example":6,"minimum":0,"type":"integer","x-struct":null,"x-validate":null}},"required":["__type","__subtype","entries","pageNumber","pageSize","totalEntries","totalPages"],"title":"TrackPage","type":"object","x-struct":"Elixir.OnduWeb.Schemas.TrackPage","x-validate":null},"CreatePlaylistError":{"additionalProperties":false,"description":"A response containing validation errors keyed by field name","properties":{"fields":{"additionalProperties":{"$ref":"#/components/schemas/ValidationError"},"description":"Map of field names to their validation errors","example":{"name":{"message":"can't be blank"}},"type":"object","x-struct":null,"x-validate":null},"ok":{"example":false,"type":"boolean","x-struct":null,"x-validate":null}},"required":["fields"],"title":"CreatePlaylistError","type":"object","x-struct":"Elixir.OnduWeb.Schemas.CreatePlaylistError","x-validate":null},"User":{"additionalProperties":false,"properties":{"id":{"$ref":"#/components/schemas/UserId"},"username":{"example":"admin","type":"string","x-struct":null,"x-validate":null}},"required":["id","username"],"title":"User","type":"object","x-struct":"Elixir.OnduWeb.Schemas.User","x-validate":null},"RecordPlaysResponse":{"additionalProperties":false,"properties":{"ok":{"example":true,"type":"boolean","x-struct":null,"x-validate":null}},"required":["ok"],"title":"RecordPlaysResponse","type":"object","x-struct":"Elixir.OnduWeb.Schemas.RecordPlaysResponse","x-validate":null},"AlbumIssues":{"additionalProperties":false,"description":"An album with one or more issues.","properties":{"__type":{"default":"albumIssues","enum":["albumIssues"],"type":"string","x-struct":null,"x-validate":null},"album":{"$ref":"#/components/schemas/FlatAlbum"},"artist":{"$ref":"#/components/schemas/Artist"},"issues":{"items":{"$ref":"#/components/schemas/Issue"},"type":"array","x-struct":null,"x-validate":null}},"required":["__type","album","artist","issues"],"title":"AlbumIssues","type":"object","x-struct":"Elixir.OnduWeb.Schemas.AlbumIssues","x-validate":null},"PositionedTrack":{"additionalProperties":false,"properties":{"position":{"$ref":"#/components/schemas/FractionalIndex"},"trackId":{"$ref":"#/components/schemas/TrackId"}},"required":["position","trackId"],"title":"PositionedTrack","type":"object","x-struct":"Elixir.OnduWeb.Schemas.PositionedTrack","x-validate":null},"LogoutResponse":{"additionalProperties":false,"description":"Successfully revoked `sessionToken`.","properties":{"ok":{"example":true,"type":"boolean","x-struct":null,"x-validate":null}},"required":["ok"],"title":"LogoutResponse","type":"object","x-struct":"Elixir.OnduWeb.Schemas.LogoutResponse","x-validate":null},"SignupRequest":{"additionalProperties":false,"properties":{"password":{"minLength":1,"type":"string","x-struct":null,"x-validate":null},"passwordConfirmation":{"minLength":1,"type":"string","x-struct":null,"x-validate":null},"username":{"minLength":1,"type":"string","x-struct":null,"x-validate":null}},"required":["username","password","passwordConfirmation"],"title":"SignupRequest","type":"object","x-struct":"Elixir.OnduWeb.Schemas.SignupRequest","x-validate":null},"ArtistPage":{"additionalProperties":false,"properties":{"__subtype":{"default":"artist","description":"Paginated entity type","enum":["artist"],"type":"string","x-struct":null,"x-validate":null},"__type":{"default":"page","description":"Entity type","enum":["page"],"type":"string","x-struct":null,"x-validate":null},"entries":{"items":{"$ref":"#/components/schemas/Artist"},"type":"array","x-struct":null,"x-validate":null},"pageNumber":{"example":1,"minimum":1,"type":"integer","x-struct":null,"x-validate":null},"pageSize":{"example":25,"minimum":1,"type":"integer","x-struct":null,"x-validate":null},"totalEntries":{"example":142,"minimum":0,"type":"integer","x-struct":null,"x-validate":null},"totalPages":{"example":6,"minimum":0,"type":"integer","x-struct":null,"x-validate":null}},"required":["__type","__subtype","entries","pageNumber","pageSize","totalEntries","totalPages"],"title":"ArtistPage","type":"object","x-struct":"Elixir.OnduWeb.Schemas.ArtistPage","x-validate":null},"AlbumPage":{"additionalProperties":false,"properties":{"__subtype":{"default":"album","description":"Paginated entity type","enum":["album"],"type":"string","x-struct":null,"x-validate":null},"__type":{"default":"page","description":"Entity type","enum":["page"],"type":"string","x-struct":null,"x-validate":null},"entries":{"items":{"$ref":"#/components/schemas/Album"},"type":"array","x-struct":null,"x-validate":null},"pageNumber":{"example":1,"minimum":1,"type":"integer","x-struct":null,"x-validate":null},"pageSize":{"example":25,"minimum":1,"type":"integer","x-struct":null,"x-validate":null},"totalEntries":{"example":142,"minimum":0,"type":"integer","x-struct":null,"x-validate":null},"totalPages":{"example":6,"minimum":0,"type":"integer","x-struct":null,"x-validate":null}},"required":["__type","__subtype","entries","pageNumber","pageSize","totalEntries","totalPages"],"title":"AlbumPage","type":"object","x-struct":"Elixir.OnduWeb.Schemas.AlbumPage","x-validate":null},"Notice":{"additionalProperties":false,"description":"A notice from the server, e.g. when the music path is unavailable. Clients\ncan show their own text for known codes, `message` is an English fallback\nfor codes they don't know.\n","properties":{"code":{"enum":["library_unavailable"],"type":"string","x-struct":null,"x-validate":null},"id":{"format":"uuid","type":"string","x-struct":null,"x-validate":null},"level":{"enum":["info","warning"],"type":"string","x-struct":null,"x-validate":null},"message":{"example":"No music was found in the music path.","type":"string","x-struct":null,"x-validate":null},"raisedAt":{"format":"date-time","type":"string","x-struct":null,"x-validate":null}},"required":["id","code","level","message","raisedAt"],"title":"Notice","type":"object","x-struct":"Elixir.OnduWeb.Schemas.Notice","x-validate":null},"Settings":{"additionalProperties":false,"description":"Application settings","properties":{"musicPath":{"example":"/music","type":"string","x-struct":null,"x-validate":null},"pollInterval":{"description":"How many minutes between scanning the library.","example":60,"type":"integer","x-struct":null,"x-validate":null},"scanType":{"enum":["full","quick"],"type":"string","x-struct":null,"x-validate":null},"stripSortPrefixes":{"items":{"type":"string","x-struct":null,"x-validate":null},"type":"array","x-struct":null,"x-validate":null}},"required":["musicPath","scanType","stripSortPrefixes","pollInterval"],"title":"Settings","type":"object","x-struct":"Elixir.OnduWeb.Schemas.Settings","x-validate":null},"LoginRequest":{"additionalProperties":false,"properties":{"password":{"minLength":1,"type":"string","x-struct":null,"x-validate":null},"username":{"minLength":1,"type":"string","x-struct":null,"x-validate":null}},"required":["username","password"],"title":"LoginRequest","type":"object","x-struct":"Elixir.OnduWeb.Schemas.LoginRequest","x-validate":null},"UnknownItemsError":{"additionalProperties":false,"example":{"error":"unknown_items","itemIds":["x9"]},"properties":{"error":{"enum":["unknown_items"],"type":"string","x-struct":null,"x-validate":null},"itemIds":{"items":{"type":"string","x-struct":null,"x-validate":null},"type":"array","x-struct":null,"x-validate":null},"ok":{"example":false,"type":"boolean","x-struct":null,"x-validate":null}},"required":["error","itemIds"],"title":"UnknownItemsError","type":"object","x-struct":"Elixir.OnduWeb.Schemas.UpdatePlaylistItemsError.UnknownItems","x-validate":null},"UpdatePlaylistItemsError":{"additionalProperties":false,"description":"Error response returned. The shape depends on `error`.","discriminator":{"mapping":{"duplicate_items":"#/components/schemas/DuplicateItemsError","invalid_positions":"#/components/schemas/InvalidPositionsError","move_remove_conflict":"#/components/schemas/MoveRemoveConflictError","playlist_is_folder":"#/components/schemas/PlaylistIsFolderError","too_many_operations":"#/components/schemas/TooManyOperationsError","unknown_items":"#/components/schemas/UnknownItemsError","unknown_tracks":"#/components/schemas/UnknownTracksError"},"propertyName":"error"},"oneOf":[{"$ref":"#/components/schemas/PlaylistIsFolderError"},{"$ref":"#/components/schemas/TooManyOperationsError"},{"$ref":"#/components/schemas/MoveRemoveConflictError"},{"$ref":"#/components/schemas/DuplicateItemsError"},{"$ref":"#/components/schemas/InvalidPositionsError"},{"$ref":"#/components/schemas/UnknownItemsError"},{"$ref":"#/components/schemas/UnknownTracksError"}],"title":"UpdatePlaylistItemsError","x-struct":"Elixir.OnduWeb.Schemas.UpdatePlaylistItemsError","x-validate":null},"PutAnnotationsResponse":{"additionalProperties":false,"properties":{"ok":{"example":true,"type":"boolean","x-struct":null,"x-validate":null},"skipped":{"description":"Entities that don't exist, so these entries were skipped.","items":{"format":"uuid","type":"string","x-struct":null,"x-validate":null},"type":"array","x-struct":null,"x-validate":null}},"required":["ok","skipped"],"title":"PutAnnotationsResponse","type":"object","x-struct":"Elixir.OnduWeb.Schemas.PutAnnotationsResponse","x-validate":null},"UpdatePasswordRequest":{"additionalProperties":false,"properties":{"currentPassword":{"minLength":1,"type":"string","x-struct":null,"x-validate":null},"password":{"minLength":1,"type":"string","x-struct":null,"x-validate":null},"passwordConfirmation":{"minLength":1,"type":"string","x-struct":null,"x-validate":null}},"required":["currentPassword","password","passwordConfirmation"],"title":"UpdatePasswordRequest","type":"object","x-struct":"Elixir.OnduWeb.Schemas.UpdatePasswordRequest","x-validate":null},"ArtworkImage":{"additionalProperties":false,"description":"A square version of the album artwork. Artwork is never upscaled so the\ndimensions can be smaller than the maximum size of that version.\n","properties":{"height":{"example":640,"type":"integer","x-struct":null,"x-validate":null},"url":{"example":"https://example.com/artwork/albums/7c388624-2362-45e2-ae94-ee9aa7a65cb6/4f1c2a9d8e7b6c5a/large.jpg","type":"string","x-struct":null,"x-validate":null},"width":{"example":640,"type":"integer","x-struct":null,"x-validate":null}},"required":["url","width","height"],"title":"ArtworkImage","type":"object","x-struct":"Elixir.OnduWeb.Schemas.ArtworkImage","x-validate":null},"DuplicateItemsError":{"additionalProperties":false,"description":"The same item is moved, or removed, more than once.","example":{"error":"duplicate_items","itemIds":["a1"]},"properties":{"error":{"enum":["duplicate_items"],"type":"string","x-struct":null,"x-validate":null},"itemIds":{"items":{"type":"string","x-struct":null,"x-validate":null},"type":"array","x-struct":null,"x-validate":null},"ok":{"example":false,"type":"boolean","x-struct":null,"x-validate":null}},"required":["error","itemIds"],"title":"DuplicateItemsError","type":"object","x-struct":"Elixir.OnduWeb.Schemas.UpdatePlaylistItemsError.DuplicateItems","x-validate":null},"Issue":{"additionalProperties":false,"description":"Missing or bad metadata that should be fixed in the source files. Which\n`details` are set depends on the `code`:\n\n- `artwork_missing`: no artwork found by any of the fetchers\n- `artwork_not_square`: the found artwork is not a perfect square\n- `artwork_low_res`: the found artwork is of low quality\n- `album_missing`: tracks without an album tag (\"Unknown Album\")\n- `release_year_missing`: the album has no release year\n- `track_number_missing`: `trackIds` of the tracks without a track number\n- `track_number_duplicate`: `numbers` used by more than one track on `disc`\n- `track_number_gap`: `numbers` missing on `disc`, possibly incomplete album?\n- `title_missing`: `trackIds` of the tracks without a title tag\n- `artist_missing`: the track has no artist at all (invisible in library)\n","properties":{"code":{"enum":["artwork_missing","artwork_not_square","artwork_low_res","album_missing","release_year_missing","track_number_missing","track_number_duplicate","track_number_gap","title_missing","artist_missing"],"type":"string","x-struct":null,"x-validate":null},"details":{"additionalProperties":false,"properties":{"disc":{"example":1,"type":"integer","x-struct":null,"x-validate":null},"height":{"example":571,"type":"integer","x-struct":null,"x-validate":null},"numbers":{"example":[5],"items":{"type":"integer","x-struct":null,"x-validate":null},"type":"array","x-struct":null,"x-validate":null},"trackIds":{"items":{"$ref":"#/components/schemas/TrackId"},"type":"array","x-struct":null,"x-validate":null},"width":{"example":640,"type":"integer","x-struct":null,"x-validate":null}},"type":"object","x-struct":null,"x-validate":null}},"required":["code","details"],"title":"Issue","type":"object","x-struct":"Elixir.OnduWeb.Schemas.Issue","x-validate":null},"Album":{"additionalProperties":false,"description":"An album","properties":{"__type":{"default":"album","description":"Entity type","enum":["album"],"type":"string","x-struct":null,"x-validate":null},"artistId":{"$ref":"#/components/schemas/ArtistId"},"artwork":{"description":"Available variants of the artwork.","items":{"$ref":"#/components/schemas/ArtworkImage"},"type":"array","x-struct":null,"x-validate":null},"id":{"$ref":"#/components/schemas/AlbumId"},"insertedAt":{"format":"date-time","type":"string","x-struct":null,"x-validate":null},"isUnknown":{"example":false,"type":"boolean","x-struct":null,"x-validate":null},"loudness":{"allOf":[{"$ref":"#/components/schemas/Loudness"}],"description":"The loudness of the whole album, to use one gain for all tracks when the\nalbum is played in sequence. Approximated from the loudness of the tracks,\nnull until all tracks are measured.\n","nullable":true,"x-struct":null,"x-validate":null},"name":{"example":"With the Beatles","type":"string","x-struct":null,"x-validate":null},"releaseYear":{"example":2,"nullable":true,"type":"integer","x-struct":null,"x-validate":null},"slug":{"example":"with-the-beatles","type":"string","x-struct":null,"x-validate":null},"sortName":{"example":"With the Beatles","type":"string","x-struct":null,"x-validate":null},"trackCount":{"example":14,"type":"integer","x-struct":null,"x-validate":null},"tracks":{"items":{"$ref":"#/components/schemas/FlatTrack"},"type":"array","x-struct":null,"x-validate":null}},"required":["tracks","__type","id","artistId","name","sortName","slug","artwork","releaseYear","loudness","trackCount","isUnknown","insertedAt"],"title":"Album","type":"object","x-struct":"Elixir.OnduWeb.Schemas.Album","x-validate":null},"AlbumId":{"description":"The UUID for a specific Album.","example":"7c388624-2362-45e2-ae94-ee9aa7a65cb6","format":"uuid","title":"AlbumId","type":"string","x-struct":"Elixir.OnduWeb.Schemas.AlbumId","x-validate":null},"TrackId":{"description":"The UUID for a specific Track.","example":"52cf997e-3acc-414e-b92c-4f32895a41d9","format":"uuid","title":"TrackId","type":"string","x-struct":"Elixir.OnduWeb.Schemas.TrackId","x-validate":null},"MoveRemoveConflictError":{"additionalProperties":false,"example":{"error":"move_remove_conflict","itemIds":["a1","b2"]},"properties":{"error":{"enum":["move_remove_conflict"],"type":"string","x-struct":null,"x-validate":null},"itemIds":{"items":{"type":"string","x-struct":null,"x-validate":null},"type":"array","x-struct":null,"x-validate":null},"ok":{"example":false,"type":"boolean","x-struct":null,"x-validate":null}},"required":["error","itemIds"],"title":"MoveRemoveConflictError","type":"object","x-struct":"Elixir.OnduWeb.Schemas.UpdatePlaylistItemsError.MoveRemoveConflict","x-validate":null},"IssuePage":{"additionalProperties":false,"properties":{"__subtype":{"default":"issues","description":"Paginated entity type","enum":["issues"],"type":"string","x-struct":null,"x-validate":null},"__type":{"default":"page","description":"Entity type","enum":["page"],"type":"string","x-struct":null,"x-validate":null},"entries":{"items":{"$ref":"#/components/schemas/IssueEntry"},"type":"array","x-struct":null,"x-validate":null},"pageNumber":{"example":1,"minimum":1,"type":"integer","x-struct":null,"x-validate":null},"pageSize":{"example":25,"minimum":1,"type":"integer","x-struct":null,"x-validate":null},"totalEntries":{"example":142,"minimum":0,"type":"integer","x-struct":null,"x-validate":null},"totalPages":{"example":6,"minimum":0,"type":"integer","x-struct":null,"x-validate":null}},"required":["__type","__subtype","entries","pageNumber","pageSize","totalEntries","totalPages"],"title":"IssuePage","type":"object","x-struct":"Elixir.OnduWeb.Schemas.IssuePage","x-validate":null},"IssueEntry":{"description":"An album or track with issues, the shape depends on `__type`.","discriminator":{"mapping":{"albumIssues":"#/components/schemas/AlbumIssues","trackIssues":"#/components/schemas/TrackIssues"},"propertyName":"__type"},"oneOf":[{"$ref":"#/components/schemas/AlbumIssues"},{"$ref":"#/components/schemas/TrackIssues"}],"title":"IssueEntry","x-struct":"Elixir.OnduWeb.Schemas.IssueEntry","x-validate":null},"TrackIssues":{"additionalProperties":false,"description":"A track with one or more issues","properties":{"__type":{"default":"trackIssues","enum":["trackIssues"],"type":"string","x-struct":null,"x-validate":null},"issues":{"items":{"$ref":"#/components/schemas/Issue"},"type":"array","x-struct":null,"x-validate":null},"track":{"additionalProperties":false,"properties":{"id":{"$ref":"#/components/schemas/TrackId"},"name":{"example":"01 Perth.m4a","type":"string","x-struct":null,"x-validate":null},"path":{"description":"Path of the file relative to the music path.","example":"Unknown Artist/Unknown Album/01 Perth.m4a","type":"string","x-struct":null,"x-validate":null}},"required":["id","name","path"],"type":"object","x-struct":null,"x-validate":null}},"required":["__type","track","issues"],"title":"TrackIssues","type":"object","x-struct":"Elixir.OnduWeb.Schemas.TrackIssues","x-validate":null},"SessionToken":{"example":"U2Vzc2lvblRva2Vu","format":"base64","title":"SessionToken","type":"string","x-struct":"Elixir.OnduWeb.Schemas.SessionToken","x-validate":null},"PlaylistItemId":{"description":"The UUID for a specific PlaylistItem.","example":"6d3e0561-6007-4e18-b1cb-2dd2d440272a","format":"uuid","title":"PlaylistItemId","type":"string","x-struct":"Elixir.OnduWeb.Schemas.PlaylistItemId","x-validate":null},"SyncDeletion":{"additionalProperties":false,"description":"Represents the deletion of an entity.\n","properties":{"entityId":{"format":"uuid","type":"string","x-struct":null,"x-validate":null},"entityType":{"enum":["artist","album","track","playlist","playlistItem"],"type":"string","x-struct":null,"x-validate":null}},"required":["entityId","entityType"],"title":"SyncDeletion","type":"object","x-struct":"Elixir.OnduWeb.Schemas.SyncDeletion","x-validate":null},"SyncResponse":{"additionalProperties":false,"description":"Contains cursor-paginated results for multiple entities.","properties":{"albums":{"items":{"$ref":"#/components/schemas/FlatAlbum"},"type":"array","x-struct":null,"x-validate":null},"artists":{"items":{"$ref":"#/components/schemas/Artist"},"type":"array","x-struct":null,"x-validate":null},"complete":{"description":"Indicates whether or not there are more items available to sync.","example":true,"type":"boolean","x-struct":null,"x-validate":null},"cursor":{"$ref":"#/components/schemas/SyncCursor"},"deletions":{"items":{"$ref":"#/components/schemas/SyncDeletion"},"type":"array","x-struct":null,"x-validate":null},"notices":{"description":"All active server notices (ignores cursor).","items":{"$ref":"#/components/schemas/Notice"},"type":"array","x-struct":null,"x-validate":null},"playlistItems":{"items":{"$ref":"#/components/schemas/PlaylistItem"},"type":"array","x-struct":null,"x-validate":null},"playlists":{"items":{"$ref":"#/components/schemas/Playlist"},"type":"array","x-struct":null,"x-validate":null},"tracks":{"items":{"$ref":"#/components/schemas/FlatTrack"},"type":"array","x-struct":null,"x-validate":null}},"required":["artists","albums","tracks","playlists","playlistItems","deletions","notices","cursor","complete"],"title":"SyncResponse","type":"object","x-struct":"Elixir.OnduWeb.Schemas.SyncResponse","x-validate":null},"Track":{"additionalProperties":false,"description":"A track with its artist and album embedded","properties":{"__type":{"default":"track","description":"Entity type","enum":["track"],"type":"string","x-struct":null,"x-validate":null},"album":{"$ref":"#/components/schemas/FlatAlbum"},"albumArtistId":{"$ref":"#/components/schemas/ArtistId"},"albumId":{"$ref":"#/components/schemas/AlbumId"},"artist":{"$ref":"#/components/schemas/Artist"},"artistId":{"$ref":"#/components/schemas/ArtistId"},"disc":{"example":1,"nullable":true,"type":"integer","x-struct":null,"x-validate":null},"downloadUrl":{"example":"https://example.com/download/...","type":"string","x-struct":null,"x-validate":null},"duration":{"example":123.45,"type":"number","x-struct":null,"x-validate":null},"id":{"$ref":"#/components/schemas/TrackId"},"insertedAt":{"format":"date-time","type":"string","x-struct":null,"x-validate":null},"lastPlayedAt":{"description":"When it was last played, null when never played","format":"date-time","nullable":true,"type":"string","x-struct":null,"x-validate":null},"loudness":{"allOf":[{"$ref":"#/components/schemas/Loudness"}],"description":"The measured loudness, null until measured (or when measuring failed)","nullable":true,"x-struct":null,"x-validate":null},"mimetype":{"example":"audio/mp3","type":"string","x-struct":null,"x-validate":null},"name":{"example":"The Beatles","type":"string","x-struct":null,"x-validate":null},"number":{"example":1,"nullable":true,"type":"integer","x-struct":null,"x-validate":null},"playCount":{"description":"How often it was played","example":3,"type":"integer","x-struct":null,"x-validate":null},"relativeFilePath":{"description":"This is the relative file path of this track inside your library.\n","example":"The Beatles/Revolver/01 Taxman.m4a","type":"string","x-struct":null,"x-validate":null},"streamUrl":{"example":"https://example.com/stream/...","type":"string","x-struct":null,"x-validate":null}},"required":["artist","album","__type","id","artistId","albumArtistId","albumId","name","disc","number","duration","loudness","playCount","lastPlayedAt","mimetype","downloadUrl","streamUrl","insertedAt"],"title":"Track","type":"object","x-struct":"Elixir.OnduWeb.Schemas.Track","x-validate":null},"ArtistId":{"description":"The UUID for a specific Artist.","example":"06e59d90-3e45-4b8f-93e2-8f7907c772cc","format":"uuid","title":"ArtistId","type":"string","x-struct":"Elixir.OnduWeb.Schemas.ArtistId","x-validate":null},"SearchResults":{"additionalProperties":false,"description":"Returns the top matching artists, albums and tracks.","properties":{"albums":{"items":{"$ref":"#/components/schemas/FlatAlbum"},"type":"array","x-struct":null,"x-validate":null},"artists":{"items":{"$ref":"#/components/schemas/Artist"},"type":"array","x-struct":null,"x-validate":null},"tracks":{"items":{"$ref":"#/components/schemas/Track"},"type":"array","x-struct":null,"x-validate":null}},"required":["artists","albums","tracks"],"title":"SearchResults","type":"object","x-struct":"Elixir.OnduWeb.Schemas.SearchResults","x-validate":null},"PlaylistItemPage":{"additionalProperties":false,"properties":{"__subtype":{"default":"playlistItem","description":"Paginated entity type","enum":["playlistItem"],"type":"string","x-struct":null,"x-validate":null},"__type":{"default":"page","description":"Entity type","enum":["page"],"type":"string","x-struct":null,"x-validate":null},"entries":{"items":{"$ref":"#/components/schemas/PlaylistItem"},"type":"array","x-struct":null,"x-validate":null},"pageNumber":{"example":1,"minimum":1,"type":"integer","x-struct":null,"x-validate":null},"pageSize":{"example":25,"minimum":1,"type":"integer","x-struct":null,"x-validate":null},"totalEntries":{"example":142,"minimum":0,"type":"integer","x-struct":null,"x-validate":null},"totalPages":{"example":6,"minimum":0,"type":"integer","x-struct":null,"x-validate":null}},"required":["__type","__subtype","entries","pageNumber","pageSize","totalEntries","totalPages"],"title":"PlaylistItemPage","type":"object","x-struct":"Elixir.OnduWeb.Schemas.PlaylistItemPage","x-validate":null},"ValidationError":{"additionalProperties":false,"description":"A validation error for a single field","properties":{"message":{"description":"Human-readable error message","example":"can't be blank","type":"string","x-struct":null,"x-validate":null}},"required":["message"],"title":"ValidationError","type":"object","x-struct":"Elixir.OnduWeb.Schemas.ChangesetError","x-validate":null},"SignupResponse":{"additionalProperties":false,"description":"A successful Signup attempt returns currentUser and sessionToken","properties":{"currentUser":{"$ref":"#/components/schemas/User"},"ok":{"example":true,"type":"boolean","x-struct":null,"x-validate":null},"sessionToken":{"$ref":"#/components/schemas/SessionToken"}},"required":["ok","sessionToken","currentUser"],"title":"SignupResponse","type":"object","x-struct":"Elixir.OnduWeb.Schemas.SignupResponse","x-validate":null},"InvalidPositionsError":{"additionalProperties":false,"example":{"error":"invalid_positions","positions":["z@p"]},"properties":{"error":{"enum":["invalid_positions"],"type":"string","x-struct":null,"x-validate":null},"ok":{"example":false,"type":"boolean","x-struct":null,"x-validate":null},"positions":{"items":{"type":"string","x-struct":null,"x-validate":null},"type":"array","x-struct":null,"x-validate":null}},"required":["error","positions"],"title":"InvalidPositionsError","type":"object","x-struct":"Elixir.OnduWeb.Schemas.UpdatePlaylistItemsError.InvalidPositions","x-validate":null}},"securitySchemes":{"playToken":{"in":"query","name":"token","type":"apiKey"},"sessionToken":{"scheme":"bearer","type":"http"}}},"externalDocs":{"description":"Setting up Ondu Server","url":"https://ondumusic.com/setup.html"},"info":{"description":"## Authentication\nAll requests require a bearer token in the `Authorization` header,\nhowever it is also possible to generate a `playToken` that temporarily\nlets you access track downloads/streams. This is mostly intended to be\nused by clients that cannot add the `Authorization` header to their\naudio player requests (like a native `<audio>` tag in HTML).\n\n## Versions\n`GET /api/info` returns the version of the server and of the API. The API\nversion only changes when the API changes in a way that breaks existing\nclients, additions (e.g. new endpoints, fields or error codes) do not\nchange it. Clients should ignore fields and values they don't know.\n","title":"Ondu Server API","version":"1.0.0-rc.5"},"openapi":"3.0.0","paths":{"/api/albums":{"get":{"callbacks":{},"operationId":"OnduWeb.LibraryController.albums","parameters":[{"description":"1-indexed page number","in":"query","name":"page","required":false,"schema":{"default":1,"minimum":1,"type":"integer","x-struct":null,"x-validate":null}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlbumPage"}}},"description":"Returns a paginated list of albums."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid authentication."}},"summary":"List albums","tags":["Albums"]}},"/api/albums/{album_id}":{"get":{"callbacks":{},"operationId":"OnduWeb.LibraryController.album","parameters":[{"description":"","in":"path","name":"album_id","required":true,"schema":{"$ref":"#/components/schemas/AlbumId"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Album"}}},"description":"Returns the requested `Album`."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid authentication."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Album not found"}},"summary":"Get a specific album","tags":["Albums"]}},"/api/annotations/{namespace}/{entity_type}":{"get":{"callbacks":{},"description":"Annotations are data stored by scripts using the API. The server itself does\nnothing with them and they are not part of sync.\n\nLists all annotations inside the a namespace for an entity type.\n","operationId":"OnduWeb.AnnotationController.index","parameters":[{"description":"A namespace can be used to group annotations, for example if you write a\nscript that needs to persist data it could be the name of your script.\n\n1 to 64 characters of `a-z`, `0-9`, `.`, `_` and `-`.\n","in":"path","name":"namespace","required":true,"schema":{"pattern":"^[a-z0-9._-]{1,64}$","type":"string","x-struct":null,"x-validate":null}},{"description":"","in":"path","name":"entity_type","required":true,"schema":{"enum":["albums","artists"],"type":"string","x-struct":null,"x-validate":null}},{"description":"1-indexed page number","in":"query","name":"page","required":false,"schema":{"default":1,"minimum":1,"type":"integer","x-struct":null,"x-validate":null}},{"description":"Defaults to 500.","in":"query","name":"page_size","required":false,"schema":{"maximum":1000,"minimum":1,"type":"integer","x-struct":null,"x-validate":null}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnnotationPage"}}},"description":"A page of annotations."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid authentication."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid namespace or entity type."}},"summary":"List annotations","tags":["Annotations"]},"put":{"callbacks":{},"description":"Writes up to 500 annotations to a namespace for an entity type. The data\nreplaces the current data of an entity, `null` removes it. Entries for\nentities that don't exist are skipped and returned.\n","operationId":"OnduWeb.AnnotationController.update","parameters":[{"description":"A namespace can be used to group annotations, for example if you write a\nscript that needs to persist data it could be the name of your script.\n\n1 to 64 characters of `a-z`, `0-9`, `.`, `_` and `-`.\n","in":"path","name":"namespace","required":true,"schema":{"pattern":"^[a-z0-9._-]{1,64}$","type":"string","x-struct":null,"x-validate":null}},{"description":"","in":"path","name":"entity_type","required":true,"schema":{"enum":["albums","artists"],"type":"string","x-struct":null,"x-validate":null}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PutAnnotationsRequest"}}},"description":"Annotations","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PutAnnotationsResponse"}}},"description":"The annotations were written."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid authentication."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid annotations."}},"summary":"Write annotations","tags":["Annotations"]}},"/api/artists":{"get":{"callbacks":{},"operationId":"OnduWeb.LibraryController.artists","parameters":[{"description":"1-indexed page number","in":"query","name":"page","required":false,"schema":{"default":1,"minimum":1,"type":"integer","x-struct":null,"x-validate":null}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArtistPage"}}},"description":"A paginated list of artists."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid authentication."}},"summary":"List artists","tags":["Artists"]}},"/api/artists/{artist_id}":{"get":{"callbacks":{},"operationId":"OnduWeb.LibraryController.artist","parameters":[{"description":"","in":"path","name":"artist_id","required":true,"schema":{"$ref":"#/components/schemas/ArtistId"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Artist"}}},"description":"Returns the requested Artist."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid authentication."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Artist not found."}},"summary":"Get a specific artist","tags":["Artists"]}},"/api/artists/{artist_id}/albums":{"get":{"callbacks":{},"operationId":"OnduWeb.LibraryController.artist_albums","parameters":[{"description":"1-indexed page number","in":"query","name":"page","required":false,"schema":{"default":1,"minimum":1,"type":"integer","x-struct":null,"x-validate":null}},{"description":"","in":"path","name":"artist_id","required":true,"schema":{"$ref":"#/components/schemas/ArtistId"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlbumPage"}}},"description":"Returns a paginated list of albums for the given artist."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid authentication."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Artist not found."}},"summary":"List albums for a specific artist","tags":["Albums"]}},"/api/artists/{artist_id}/albums/{album_id}":{"get":{"callbacks":{},"operationId":"OnduWeb.LibraryController.artist_album","parameters":[{"description":"","in":"path","name":"artist_id","required":true,"schema":{"$ref":"#/components/schemas/ArtistId"}},{"description":"","in":"path","name":"album_id","required":true,"schema":{"$ref":"#/components/schemas/AlbumId"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Album"}}},"description":"Returns the requested `Album`."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid authentication."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Album not found."}},"summary":"Get a specific album for a specific artist","tags":["Albums"]}},"/api/artists/{artist_id}/artwork":{"delete":{"callbacks":{},"operationId":"OnduWeb.ArtistArtworkController.delete","parameters":[{"description":"","in":"path","name":"artist_id","required":true,"schema":{"$ref":"#/components/schemas/ArtistId"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Artist"}}},"description":"The artist without artwork."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid authentication."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Artist not found."}},"summary":"Removes the artwork from an artist","tags":["Artists"]},"put":{"callbacks":{},"description":"Adds or replaces the artwork for the artist. Images keep their aspect ratio\n(the shortest side of each variant matches its size), so clients can crop\nthem however they show artists. Images can be at most 25MB and 10000 pixels.\n","operationId":"OnduWeb.ArtistArtworkController.update","parameters":[{"description":"","in":"path","name":"artist_id","required":true,"schema":{"$ref":"#/components/schemas/ArtistId"}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"properties":{"file":{"format":"binary","type":"string","x-struct":null,"x-validate":null}},"required":["file"],"type":"object","x-struct":null,"x-validate":null}}},"description":"The image","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Artist"}}},"description":"The artist with its new artwork."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid authentication."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Artist not found."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not an image (invalid_image), or too large (too_large)."}},"summary":"Upload artwork for an artist","tags":["Artists"]}},"/api/auth/login":{"post":{"callbacks":{},"operationId":"OnduWeb.AuthController.login","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginRequest"}}},"description":"Login params","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginResponse"}}},"description":"Succesful login attempt."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Failed to authenticate."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginError"}}},"description":"Validation failed."},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginError"}}},"description":"Too many failed login attempts."}},"security":[],"summary":"Login","tags":["Auth"]}},"/api/auth/me":{"get":{"callbacks":{},"operationId":"OnduWeb.AuthController.current_user","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/User"}}},"description":"The authenticated user's profile."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid authentication."}},"summary":"Get current user","tags":["Auth"]}},"/api/auth/playtoken":{"get":{"callbacks":{},"description":"PlayTokens only work for streaming audio to allow authentication for audio\nplayers where you can't override the request headers. In most cases I would\ntry to stick to regular authentication headers, if possible.\n","operationId":"OnduWeb.AuthController.play_token","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlayTokenResponse"}}},"description":"Successfully generated a new PlayToken."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid authentication."}},"summary":"Create a PlayToken","tags":["Auth"]}},"/api/auth/session":{"delete":{"callbacks":{},"description":"This only revokes the current `sessionToken` for the logged-in user.\n","operationId":"OnduWeb.AuthController.logout","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LogoutResponse"}}},"description":"Revoked the current `sessionToken`."}},"summary":"Logout","tags":["Auth"]}},"/api/auth/signup":{"post":{"callbacks":{},"description":"This only works if there is no user present yet, during onboarding. For the\ntime being this is designed as a single-user application.\n","operationId":"OnduWeb.AuthController.signup","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignupRequest"}}},"description":"Signup params","required":false},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignupResponse"}}},"description":"Successful signup returns `currentUser` and `sessionToken`. "},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Signup has been disabled."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignupError"}}},"description":"Validation failed."}},"security":[],"summary":"Signup","tags":["Auth"]}},"/api/info":{"get":{"callbacks":{},"description":"The version can be used to show which version of the server is running, or\nto check if it supports a feature. The API version only changes when the API\nchanges in a way that breaks existing clients.\n","operationId":"OnduWeb.InfoController.info","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServerInfo"}}},"description":"Server information."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid authentication."}},"summary":"Server information","tags":["Info"]}},"/api/issues":{"get":{"callbacks":{},"description":"Albums and tracks with missing or bad metadata, e.g. missing tags or\nnon-square artwork. Tracks that are not linked to an artist or album are\nlisted first, followed by albums ordered by artist.\n","operationId":"OnduWeb.IssueController.issues","parameters":[{"description":"1-indexed page number","in":"query","name":"page","required":false,"schema":{"default":1,"minimum":1,"type":"integer","x-struct":null,"x-validate":null}},{"description":"Only include entries with this specific issue.","in":"query","name":"code","required":false,"schema":{"enum":["artwork_missing","artwork_not_square","artwork_low_res","album_missing","release_year_missing","track_number_missing","track_number_duplicate","track_number_gap","title_missing","artist_missing"],"type":"string","x-struct":null,"x-validate":null}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssuePage"}}},"description":"A paginated list of issues."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid authentication."}},"summary":"List albums and tracks with potential metadata issues","tags":["Issues"]}},"/api/notices/{notice_id}/dismiss":{"post":{"callbacks":{},"description":"Dismisses the notice for all clients, returns a list of remaining notices.","operationId":"OnduWeb.NoticeController.dismiss","parameters":[{"description":"","in":"path","name":"notice_id","required":true,"schema":{"format":"uuid","type":"string","x-struct":null,"x-validate":null}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Notices"}}},"description":"The remaining notices."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid authentication."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Notice not found (or no longer active)."}},"summary":"Dismiss a notice","tags":["Notices"]}},"/api/playlists":{"get":{"callbacks":{},"operationId":"OnduWeb.PlaylistController.playlists","parameters":[{"description":"1-indexed page number","in":"query","name":"page","required":false,"schema":{"default":1,"minimum":1,"type":"integer","x-struct":null,"x-validate":null}},{"description":"","in":"query","name":"parent_id","required":false,"schema":{"$ref":"#/components/schemas/PlaylistId"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlaylistPage"}}},"description":"Returns a paginated list of playlists"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid authentication."}},"summary":"List playlists","tags":["Playlists"]},"post":{"callbacks":{},"operationId":"OnduWeb.PlaylistController.create_playlist","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePlaylistRequest"}}},"description":"Playlist params","required":false},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Playlist"}}},"description":"Successfully created a new playlist."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid authentication."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePlaylistError"}}},"description":"Validation failed."}},"summary":"Create playlist","tags":["Playlists"]}},"/api/playlists/{playlist_id}":{"delete":{"callbacks":{},"operationId":"OnduWeb.PlaylistController.delete_playlist","parameters":[{"description":"","in":"path","name":"playlist_id","required":true,"schema":{"$ref":"#/components/schemas/PlaylistId"}}],"responses":{"204":{"description":"Successfully deleted the playlist."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid authentication."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Playlist not found."}},"summary":"Delete playlist","tags":["Playlists"]},"get":{"callbacks":{},"operationId":"OnduWeb.PlaylistController.playlist","parameters":[{"description":"","in":"path","name":"playlist_id","required":true,"schema":{"$ref":"#/components/schemas/PlaylistId"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Playlist"}}},"description":"Playlist"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid authentication."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Playlist not found."}},"summary":"Get a specific playlist","tags":["Playlists"]},"patch":{"callbacks":{},"operationId":"OnduWeb.PlaylistController.update_playlist","parameters":[{"description":"","in":"path","name":"playlist_id","required":true,"schema":{"$ref":"#/components/schemas/PlaylistId"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePlaylistRequest"}}},"description":"Playlist params","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Playlist"}}},"description":"Successfully updated the playlist."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid authentication."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Playlist not found."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePlaylistError"}}},"description":"Validation failed."}},"summary":"Update playlist","tags":["Playlists"]}},"/api/playlists/{playlist_id}/items":{"get":{"callbacks":{},"operationId":"OnduWeb.PlaylistController.playlist_items","parameters":[{"description":"1-indexed page number","in":"query","name":"page","required":false,"schema":{"default":1,"minimum":1,"type":"integer","x-struct":null,"x-validate":null}},{"description":"","in":"path","name":"playlist_id","required":true,"schema":{"$ref":"#/components/schemas/PlaylistId"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlaylistItemPage"}}},"description":"Returns a list of items for the given playlist."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid authentication."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Playlist not found."}},"summary":"List playlist items","tags":["Playlists"]},"patch":{"callbacks":{},"operationId":"OnduWeb.PlaylistController.update_playlist_items","parameters":[{"description":"","in":"path","name":"playlist_id","required":true,"schema":{"$ref":"#/components/schemas/PlaylistId"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePlaylistItemsRequest"}}},"description":"Operations","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePlaylistItemsResponse"}}},"description":"Successfully updated the playlist items."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid authentication."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Playlist not found."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePlaylistItemsError"}}},"description":"Validation failed."}},"summary":"Update playlist items","tags":["Playlists"]}},"/api/plays":{"post":{"callbacks":{},"description":"\nWe recommend only counting plays for tracks that were played at least half\nof its duration (with a cap of 4 minutes for very long tracks) and generally\ndiscourage counting tracks that with a duration of 30s or less.\n\nIt will ignore plays that have been submitted before (based on the idempotent\nclient generated id) or for tracks that don't exist.\n","operationId":"OnduWeb.PlayController.record_plays","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordPlaysRequest"}}},"description":"Plays","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordPlaysResponse"}}},"description":"The plays were stored."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid authentication."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid plays, or too many."}},"summary":"Record plays","tags":["Tracks"]}},"/api/scan":{"post":{"callbacks":{},"operationId":"OnduWeb.LibraryController.scan","parameters":[],"responses":{"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanResponse"}}},"description":"Started an asynchronous file scan operation."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid authentication."}},"summary":"Scan for changes in your library","tags":["Scan"]}},"/api/search":{"get":{"callbacks":{},"operationId":"OnduWeb.SearchController.search","parameters":[{"description":"A search term to use across artists, albums and tracks.","in":"query","name":"query","required":true,"schema":{"type":"string","x-struct":null,"x-validate":null}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResults"}}},"description":"Returns a list of search results (artists, albums, tracks)."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid authentication."}},"summary":"Search for artists, albums or tracks","tags":["Search"]}},"/api/settings":{"get":{"callbacks":{},"operationId":"OnduWeb.SettingsController.show","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Settings"}}},"description":"Returns the current library settings."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid authentication."}},"summary":"Get library settings","tags":["Settings"]},"patch":{"callbacks":{},"operationId":"OnduWeb.SettingsController.update","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSettingsRequest"}}},"description":"Operations","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSettingsResponse"}}},"description":"Successfully updated the library settings."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid authentication."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSettingsError"}}},"description":"Validation failed."}},"summary":"Update library settings","tags":["Settings"]}},"/api/sync":{"get":{"callbacks":{},"description":"This generally helps provide the best experience for end-users by syncing\nthe metadata to be available offline and use local database techniques when\ndisplaying, sorting, searching, etc. in the library.\n\nThe initial sync can take a couple of requests before it is completed,\ndepending on the size of your library. But if you store the last returned\n`cursor` from then on sync requests should only return new changes.\n\nIf you want to also sync the actual tracks this is something you would have\nto manage in your application by building a download queue and keeping track\nof the download status etc.\n","operationId":"OnduWeb.SyncController.sync","parameters":[{"description":"Cursor from previous sync response to get only changes since then.","in":"query","name":"cursor","required":false,"schema":{"type":"string","x-struct":null,"x-validate":null}},{"description":"Version of the entity data your client understands.\n\nPick a number and bump it when your client starts using new fields it\nwould have ignored before. The server will then send all entities again.\n","in":"query","name":"schemaVersion","required":false,"schema":{"type":"integer","x-struct":null,"x-validate":null}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncResponse"}}},"description":"Returns a cursor-paginated list of entities from the library."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid cursor."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid authentication."}},"summary":"Sync the entire library (metadata).","tags":["Sync"]}},"/api/tracks":{"get":{"callbacks":{},"description":"Lists tracks with optional filtering and pagination.\n\n## Random sort and pagination\n\nWhen `sort_by=random`, the server uses the provided `random_seed` to\nmaintain consistent ordering across paginated requests. This should be a\nnon-negative integer.\n\nFor `sort_by=default` (or omitted), `random_seed` is ignored.\n","operationId":"OnduWeb.LibraryController.tracks","parameters":[{"description":"1-indexed page number","in":"query","name":"page","required":false,"schema":{"default":1,"minimum":1,"type":"integer","x-struct":null,"x-validate":null}},{"description":"","in":"query","name":"artist_id","required":false,"schema":{"$ref":"#/components/schemas/ArtistId"}},{"description":"","in":"query","name":"album_id","required":false,"schema":{"$ref":"#/components/schemas/AlbumId"}},{"description":"A search query to filter tracks by.","in":"query","name":"query","required":false,"schema":{"type":"string","x-struct":null,"x-validate":null}},{"description":"Sort order for results.\n\n- `default`: sort by artist, album, disc, then track number.\n- `random`: randomized order, stable across pages when `random_seed` is reused.\n","in":"query","name":"sort_by","required":false,"schema":{"default":"default","enum":["default","random"],"type":"string","x-struct":null,"x-validate":null}},{"description":"Seed for randomized sorting. Required when `sort_by=random`.\n","in":"query","name":"random_seed","required":false,"schema":{"type":"integer","x-struct":null,"x-validate":null}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrackPage"}}},"description":"Returns a paginated list of tracks."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid authentication."}},"summary":"List tracks","tags":["Tracks"]}},"/api/tracks/{track_id}":{"get":{"callbacks":{},"operationId":"OnduWeb.LibraryController.track","parameters":[{"description":"","in":"path","name":"track_id","required":true,"schema":{"$ref":"#/components/schemas/TrackId"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Track"}}},"description":"Returns the requested track."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid authentication."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Track not found"}},"summary":"Get a specific track","tags":["Tracks"]}},"/api/user/password":{"patch":{"callbacks":{},"operationId":"OnduWeb.UserController.update_password","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePasswordRequest"}}},"description":"Password params","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePasswordResponse"}}},"description":"Succesfully updated password."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Failed to authenticate."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePasswordError"}}},"description":"Validation failed."}},"summary":"Update your password","tags":["Auth"]}},"/download/{track_id}":{"get":{"callbacks":{},"operationId":"OnduWeb.StreamController.download","parameters":[{"description":"","in":"path","name":"track_id","required":true,"schema":{"$ref":"#/components/schemas/TrackId"}},{"description":"Enable live transcoding for this track.","example":"1","in":"query","name":"transcode","required":false,"schema":{"default":"0","enum":["1","0"],"type":"string","x-struct":null,"x-validate":null}},{"description":"Which transcoding preset to use.","example":"default_ogg","in":"query","name":"preset","required":false,"schema":{"default":"default_ogg","enum":["default_ogg","mobile_ogg"],"type":"string","x-struct":null,"x-validate":null}},{"description":"Byte range to return, e.g. `bytes=0-1023` for the first 1024 bytes, or `bytes=1024-` for everything from byte 1024 onward. When present, the server responds with 206 Partial Content instead of 200.","example":"bytes=0-1023","in":"header","name":"range","required":false,"schema":{"type":"string","x-struct":null,"x-validate":null}}],"responses":{"200":{"content":{"application/octet-stream":{"schema":{"format":"binary","type":"string","x-struct":null,"x-validate":null}}},"description":"Returns the file contents for the given track.","headers":{"content-type":{"description":"The actual MIME type of the file (e.g. audio/mp3)","schema":{"type":"string","x-struct":null,"x-validate":null},"style":"simple"}}},"206":{"content":{"application/octet-stream":{"schema":{"format":"binary","type":"string","x-struct":null,"x-validate":null}}},"description":"Returns partial file contents of the given track according to the Range request.","headers":{"content-type":{"description":"The actual MIME type of the file (e.g. audio/mp3)","schema":{"type":"string","x-struct":null,"x-validate":null},"style":"simple"}}},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unknown preset."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid authentication."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Track not found."},"416":{"content":{"text/plain":{"schema":{"type":"string","x-struct":null,"x-validate":null}}},"description":"The requested range starts beyond the end of the file."}},"security":[{"sessionToken":[]},{"playToken":[]}],"summary":"Download a specific track","tags":["Tracks"]}},"/stream/{track_id}":{"get":{"callbacks":{},"operationId":"OnduWeb.StreamController.stream","parameters":[{"description":"","in":"path","name":"track_id","required":true,"schema":{"$ref":"#/components/schemas/TrackId"}},{"description":"Enable live transcoding for this track.","example":"1","in":"query","name":"transcode","required":false,"schema":{"default":"0","enum":["1","0"],"type":"string","x-struct":null,"x-validate":null}},{"description":"Which transcoding preset to use.","example":"default_ogg","in":"query","name":"preset","required":false,"schema":{"default":"default_ogg","enum":["default_ogg","mobile_ogg"],"type":"string","x-struct":null,"x-validate":null}},{"description":"Byte range to return, e.g. `bytes=0-1023` for the first 1024 bytes, or `bytes=1024-` for everything from byte 1024 onward. When present, the server responds with 206 Partial Content instead of 200.","example":"bytes=0-1023","in":"header","name":"range","required":false,"schema":{"type":"string","x-struct":null,"x-validate":null}}],"responses":{"200":{"content":{"application/octet-stream":{"schema":{"format":"binary","type":"string","x-struct":null,"x-validate":null}}},"description":"Returns the file contents for the given track.","headers":{"content-type":{"description":"The actual MIME type of the file (e.g. audio/mp3)","schema":{"type":"string","x-struct":null,"x-validate":null},"style":"simple"}}},"206":{"content":{"application/octet-stream":{"schema":{"format":"binary","type":"string","x-struct":null,"x-validate":null}}},"description":"Returns partial file contents of the given track according to the Range request.","headers":{"content-type":{"description":"The actual MIME type of the file (e.g. audio/mp3)","schema":{"type":"string","x-struct":null,"x-validate":null},"style":"simple"}}},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unknown preset."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid authentication."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Track not found."},"416":{"content":{"text/plain":{"schema":{"type":"string","x-struct":null,"x-validate":null}}},"description":"The requested range starts beyond the end of the file."}},"security":[{"sessionToken":[]},{"playToken":[]}],"summary":"Stream a specific track","tags":["Tracks"]}}},"security":[{"sessionToken":[]}],"servers":[{"url":"/","variables":{}}],"tags":[{"description":"Browse artists","name":"Artists"},{"description":"Browse albums","name":"Albums"},{"description":"Browse tracks","name":"Tracks"},{"description":"Authentication and session management","name":"Auth"},{"description":"Server information","name":"Info"},{"description":"Notices from the server","name":"Notices"},{"description":"Annotations for artists, albums","name":"Annotations"},{"description":"Library synchronization","name":"Sync"},{"description":"Library file scanning","name":"Scan"},{"description":"Search across the library","name":"Search"},{"description":"Find potential issues with library","name":"Issues"},{"description":"Manage library settings","name":"Settings"},{"description":"Create and manage playlists","name":"Playlists"}]}
