{ "swagger": "2.0", "info": { "description": "API for the MusicServer application", "title": "MusicServer API", "termsOfService": "http://sanplex.xyz/terms/", "contact": { "name": "Sebastian Olsson", "email": "zarnor91@gmail.com" }, "license": { "name": "MIT", "url": "http://opensource.org/licenses/MIT" }, "version": "1.0" }, "basePath": "/", "paths": { "/api/v1/songs/{uuid}": { "get": { "description": "Returns information about a song", "produces": [ "application/json" ], "tags": [ "library" ], "summary": "Get song", "parameters": [ { "type": "string", "description": "Song UUID", "name": "uuid", "in": "path", "required": true } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/backend.Song" } }, "400": { "description": "invalid uuid", "schema": { "type": "string" } }, "404": { "description": "not found", "schema": { "type": "string" } } } } }, "/api/v1/songs/{uuid}/file": { "get": { "description": "Returns the audio file of a song. Supports Range requests.", "produces": [ "audio/mpeg" ], "tags": [ "library" ], "summary": "Stream song", "parameters": [ { "type": "string", "description": "Song UUID", "name": "uuid", "in": "path", "required": true } ], "responses": { "200": { "description": "OK", "schema": { "type": "file" } }, "206": { "description": "Partial Content", "schema": { "type": "file" } }, "400": { "description": "invalid uuid", "schema": { "type": "string" } }, "404": { "description": "not found", "schema": { "type": "string" } }, "423": { "description": "Syncing is in progress", "schema": { "type": "string" } } } } }, "/api/v1/soundtracks": { "get": { "description": "Returns all soundtracks with their UUIDs, sorted by name", "produces": [ "application/json" ], "tags": [ "library" ], "summary": "List soundtracks", "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { "$ref": "#/definitions/backend.Soundtrack" } } } } } }, "/api/v1/soundtracks/{uuid}": { "get": { "description": "Returns a soundtrack with its songs", "produces": [ "application/json" ], "tags": [ "library" ], "summary": "Get soundtrack", "parameters": [ { "type": "string", "description": "Soundtrack UUID", "name": "uuid", "in": "path", "required": true } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/backend.SoundtrackWithSongList" } }, "400": { "description": "invalid uuid", "schema": { "type": "string" } }, "404": { "description": "not found", "schema": { "type": "string" } } } } }, "/api/v1/statistics/songs/least-played": { "get": { "description": "Returns the top N least played songs with their soundtrack info", "produces": [ "application/json" ], "tags": [ "statistics" ], "summary": "Get least played songs", "parameters": [ { "type": "integer", "description": "Number of results (default: 10, max: 100)", "name": "limit", "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { "$ref": "#/definitions/backend.SongInfoForStats" } } }, "400": { "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { "type": "string" } } }, "500": { "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { "type": "string" } } } } } }, "/api/v1/statistics/songs/most-played": { "get": { "description": "Returns the top N most played songs with their soundtrack info", "produces": [ "application/json" ], "tags": [ "statistics" ], "summary": "Get most played songs", "parameters": [ { "type": "integer", "description": "Number of results (default: 10, max: 100)", "name": "limit", "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { "$ref": "#/definitions/backend.SongInfoForStats" } } }, "400": { "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { "type": "string" } } }, "500": { "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { "type": "string" } } } } } }, "/api/v1/statistics/soundtracks/last-played": { "get": { "description": "Returns the most recently played soundtracks with their songs", "produces": [ "application/json" ], "tags": [ "statistics" ], "summary": "Get last played soundtracks", "parameters": [ { "type": "integer", "description": "Number of results (default: 10, max: 100)", "name": "limit", "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { "$ref": "#/definitions/backend.SoundtrackWithSongs" } } }, "400": { "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { "type": "string" } } }, "500": { "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { "type": "string" } } } } } }, "/api/v1/statistics/soundtracks/least-played": { "get": { "description": "Returns the top N least played soundtracks with their songs", "produces": [ "application/json" ], "tags": [ "statistics" ], "summary": "Get least played soundtracks", "parameters": [ { "type": "integer", "description": "Number of results (default: 10, max: 100)", "name": "limit", "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { "$ref": "#/definitions/backend.SoundtrackWithSongs" } } }, "400": { "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { "type": "string" } } }, "500": { "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { "type": "string" } } } } } }, "/api/v1/statistics/soundtracks/most-played": { "get": { "description": "Returns the top N most played soundtracks with their songs", "produces": [ "application/json" ], "tags": [ "statistics" ], "summary": "Get most played soundtracks", "parameters": [ { "type": "integer", "description": "Number of results (default: 10, max: 100)", "name": "limit", "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { "$ref": "#/definitions/backend.SoundtrackWithSongs" } } }, "400": { "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { "type": "string" } } }, "500": { "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { "type": "string" } } } } } }, "/api/v1/statistics/soundtracks/never-played": { "get": { "description": "Returns all soundtracks that have never been played", "produces": [ "application/json" ], "tags": [ "statistics" ], "summary": "Get never played soundtracks", "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { "$ref": "#/definitions/backend.SoundtrackWithSongs" } } }, "500": { "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { "type": "string" } } } } } }, "/api/v1/statistics/soundtracks/oldest-played": { "get": { "description": "Returns the least recently played soundtracks with their songs", "produces": [ "application/json" ], "tags": [ "statistics" ], "summary": "Get oldest played soundtracks", "parameters": [ { "type": "integer", "description": "Number of results (default: 10, max: 100)", "name": "limit", "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { "$ref": "#/definitions/backend.SoundtrackWithSongs" } } }, "400": { "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { "type": "string" } } }, "500": { "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { "type": "string" } } } } } }, "/api/v1/statistics/summary": { "get": { "description": "Returns overall play statistics", "produces": [ "application/json" ], "tags": [ "statistics" ], "summary": "Get statistics summary", "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/backend.StatisticsSummary" } }, "500": { "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { "type": "string" } } } } } }, "/api/v1/token": { "post": { "description": "Returns a new session token for API access. Requires the API password when one is configured.", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "auth" ], "summary": "Create session token", "parameters": [ { "description": "Password and client type", "name": "request", "in": "body", "required": true, "schema": { "$ref": "#/definitions/server.TokenRequest" } } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/server.TokenResponse" } }, "400": { "description": "Bad Request", "schema": { "type": "object", "additionalProperties": { "type": "string" } } }, "401": { "description": "Unauthorized", "schema": { "type": "object", "additionalProperties": { "type": "string" } } }, "429": { "description": "Too Many Requests", "schema": { "type": "object", "additionalProperties": { "type": "string" } } }, "500": { "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { "type": "string" } } } } }, "delete": { "description": "Deletes the current session token", "produces": [ "application/json" ], "tags": [ "auth" ], "summary": "Invalidate session token", "parameters": [ { "type": "string", "description": "Bearer token", "name": "Authorization", "in": "header", "required": true } ], "responses": { "200": { "description": "OK", "schema": { "type": "object", "additionalProperties": { "type": "string" } } }, "401": { "description": "Unauthorized", "schema": { "type": "object", "additionalProperties": { "type": "string" } } }, "500": { "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { "type": "string" } } } } } }, "/api/v1/token/cleanup": { "post": { "description": "Removes all expired session tokens from the database", "produces": [ "application/json" ], "tags": [ "auth" ], "summary": "Cleanup expired sessions", "parameters": [ { "type": "string", "description": "Bearer token", "name": "Authorization", "in": "header", "required": true } ], "responses": { "200": { "description": "OK", "schema": { "type": "object", "additionalProperties": { "type": "string" } } }, "401": { "description": "Unauthorized", "schema": { "type": "object", "additionalProperties": { "type": "string" } } }, "500": { "description": "Internal Server Error", "schema": { "type": "object", "additionalProperties": { "type": "string" } } } } } }, "/character": { "get": { "description": "Returns the image for a specific character", "produces": [ "image/png", "image/jpeg" ], "tags": [ "characters" ], "summary": "Get character image", "parameters": [ { "type": "string", "description": "Character file name", "name": "name", "in": "query", "required": true } ], "responses": { "200": { "description": "OK", "schema": { "type": "file" } }, "400": { "description": "invalid name", "schema": { "type": "string" } }, "404": { "description": "not found", "schema": { "type": "string" } } } } }, "/characters": { "get": { "description": "Returns a list of all available characters", "produces": [ "application/json" ], "tags": [ "characters" ], "summary": "Get list of characters", "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { "type": "string" } } } } } }, "/download": { "get": { "description": "Returns the latest version of the client application", "produces": [ "application/json" ], "tags": [ "download" ], "summary": "Check for latest version", "responses": { "200": { "description": "OK", "schema": { "type": "string" } }, "502": { "description": "upstream service unavailable", "schema": { "type": "string" } } } } }, "/download/linux": { "get": { "description": "Redirects to download the latest Linux version", "tags": [ "download" ], "summary": "Download latest Linux version", "responses": { "302": { "description": "Found", "schema": { "type": "string" } }, "404": { "description": "not found", "schema": { "type": "string" } }, "502": { "description": "upstream service unavailable", "schema": { "type": "string" } } } } }, "/download/list": { "get": { "description": "Lists all assets available for the latest version", "produces": [ "application/json" ], "tags": [ "download" ], "summary": "List assets of latest version", "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { "type": "string" } } }, "502": { "description": "upstream service unavailable", "schema": { "type": "string" } } } } }, "/download/windows": { "get": { "description": "Redirects to download the latest Windows version", "tags": [ "download" ], "summary": "Download latest Windows version", "responses": { "302": { "description": "Found", "schema": { "type": "string" } }, "404": { "description": "not found", "schema": { "type": "string" } }, "502": { "description": "upstream service unavailable", "schema": { "type": "string" } } } } }, "/health": { "get": { "description": "Returns the health status of the server", "produces": [ "application/json" ], "tags": [ "health" ], "summary": "Check server health", "responses": { "200": { "description": "OK", "schema": { "type": "object", "additionalProperties": { "type": "string" } } } } } }, "/music": { "get": { "description": "Returns the song at the given position in the queue", "produces": [ "audio/mpeg" ], "tags": [ "music" ], "summary": "Get a specific song", "parameters": [ { "type": "integer", "description": "Song number in the queue", "name": "song", "in": "query", "required": true } ], "responses": { "200": { "description": "OK", "schema": { "type": "file" } }, "206": { "description": "Partial Content", "schema": { "type": "file" } }, "400": { "description": "song must be a number", "schema": { "type": "string" } }, "404": { "description": "Not Found", "schema": { "type": "string" } }, "423": { "description": "Syncing is in progress", "schema": { "type": "string" } } } } }, "/music/addPlayed": { "get": { "description": "Marks the current song as played", "tags": [ "music" ], "summary": "Add latest to played", "responses": { "200": { "description": "OK" }, "423": { "description": "Syncing is in progress", "schema": { "type": "string" } } } } }, "/music/addQue": { "get": { "description": "Adds the latest song to the queue", "tags": [ "music" ], "summary": "Add latest to queue", "responses": { "200": { "description": "OK" }, "423": { "description": "Syncing is in progress", "schema": { "type": "string" } } } } }, "/music/all/order": { "get": { "description": "Returns a list of all soundtracks in order", "produces": [ "application/json" ], "tags": [ "music" ], "summary": "Get all soundtracks", "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { "type": "string" } } }, "423": { "description": "Syncing is in progress", "schema": { "type": "string" } } } } }, "/music/all/random": { "get": { "description": "Returns a list of all soundtracks in random order", "produces": [ "application/json" ], "tags": [ "music" ], "summary": "Get all soundtracks random", "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { "type": "string" } } }, "423": { "description": "Syncing is in progress", "schema": { "type": "string" } } } } }, "/music/info": { "get": { "description": "Returns information about the current song", "produces": [ "application/json" ], "tags": [ "music" ], "summary": "Get current song info", "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/backend.SongInfo" } } } } }, "/music/list": { "get": { "description": "Returns a list of played songs", "produces": [ "application/json" ], "tags": [ "music" ], "summary": "Get played songs list", "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { "$ref": "#/definitions/backend.SongInfo" } } } } } }, "/music/next": { "get": { "description": "Returns the next song in the queue", "produces": [ "audio/mpeg" ], "tags": [ "music" ], "summary": "Get next song", "responses": { "200": { "description": "OK", "schema": { "type": "file" } }, "404": { "description": "Not Found", "schema": { "type": "string" } }, "423": { "description": "Syncing is in progress", "schema": { "type": "string" } } } } }, "/music/played": { "put": { "description": "Marks the song at the given queue position as played", "tags": [ "music" ], "summary": "Mark song as played", "parameters": [ { "type": "integer", "description": "Song number in the queue", "name": "song", "in": "query", "required": true } ], "responses": { "200": { "description": "OK" }, "400": { "description": "Bad Request", "schema": { "type": "string" } }, "423": { "description": "Syncing is in progress", "schema": { "type": "string" } } } } }, "/music/previous": { "get": { "description": "Returns the previous song in the queue", "produces": [ "audio/mpeg" ], "tags": [ "music" ], "summary": "Get previous song", "responses": { "200": { "description": "OK", "schema": { "type": "file" } }, "404": { "description": "Not Found", "schema": { "type": "string" } }, "423": { "description": "Syncing is in progress", "schema": { "type": "string" } } } } }, "/music/rand": { "get": { "description": "Returns a random song", "produces": [ "audio/mpeg" ], "tags": [ "music" ], "summary": "Get random song", "responses": { "200": { "description": "OK", "schema": { "type": "file" } }, "404": { "description": "Not Found", "schema": { "type": "string" } }, "423": { "description": "Syncing is in progress", "schema": { "type": "string" } } } } }, "/music/rand/classic": { "get": { "description": "Returns a random song where every song has the same chance", "produces": [ "audio/mpeg" ], "tags": [ "music" ], "summary": "Get random classic song", "responses": { "200": { "description": "OK", "schema": { "type": "file" } }, "404": { "description": "Not Found", "schema": { "type": "string" } }, "423": { "description": "Syncing is in progress", "schema": { "type": "string" } } } } }, "/music/rand/low": { "get": { "description": "Returns a random song, favouring soundtracks that have been played less", "produces": [ "audio/mpeg" ], "tags": [ "music" ], "summary": "Get random song with low chance", "responses": { "200": { "description": "OK", "schema": { "type": "file" } }, "404": { "description": "Not Found", "schema": { "type": "string" } }, "423": { "description": "Syncing is in progress", "schema": { "type": "string" } } } } }, "/music/reset": { "get": { "description": "Resets the music state", "tags": [ "music" ], "summary": "Reset music state", "responses": { "200": { "description": "OK" }, "423": { "description": "Syncing is in progress", "schema": { "type": "string" } } } } }, "/music/soundTest": { "get": { "description": "Returns the sound check song", "produces": [ "audio/mpeg" ], "tags": [ "music" ], "summary": "Get sound check song", "responses": { "200": { "description": "OK", "schema": { "type": "file" } }, "404": { "description": "Not Found", "schema": { "type": "string" } }, "423": { "description": "Syncing is in progress", "schema": { "type": "string" } } } } }, "/sync": { "post": { "description": "Starts syncing soundtracks that have changed", "produces": [ "application/json" ], "tags": [ "sync" ], "summary": "Sync soundtracks with only changes", "responses": { "200": { "description": "Start syncing soundtracks", "schema": { "type": "string" } }, "423": { "description": "Syncing is in progress", "schema": { "type": "string" } } } } }, "/sync/full": { "post": { "description": "Starts a full sync of all soundtracks", "produces": [ "application/json" ], "tags": [ "sync" ], "summary": "Sync all soundtracks fully", "responses": { "200": { "description": "Start syncing soundtracks full", "schema": { "type": "string" } }, "423": { "description": "Syncing is in progress", "schema": { "type": "string" } } } } }, "/sync/progress": { "get": { "description": "Returns the progress of the running sync, or the result of the last sync", "produces": [ "application/json" ], "tags": [ "sync" ], "summary": "Get sync progress", "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/backend.SyncResponse" } } } } }, "/sync/reset": { "post": { "description": "Resets the soundtracks database by deleting all soundtracks and songs", "produces": [ "application/json" ], "tags": [ "sync" ], "summary": "Reset soundtracks database", "responses": { "200": { "description": "Soundtracks and songs are deleted from the database", "schema": { "type": "string" } }, "423": { "description": "Syncing is in progress", "schema": { "type": "string" } } } } }, "/version": { "get": { "description": "get latest version info", "produces": [ "application/json" ], "tags": [ "version" ], "summary": "Getting the latest version of the backend", "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/backend.VersionData" } } } } }, "/version/history": { "get": { "description": "get version history", "produces": [ "application/json" ], "tags": [ "version" ], "summary": "Getting the version history of the backend", "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { "$ref": "#/definitions/backend.VersionData" } } } } } } }, "definitions": { "backend.Song": { "type": "object", "properties": { "file_name": { "type": "string" }, "name": { "type": "string" }, "soundtrack_name": { "type": "string" }, "soundtrack_uuid": { "type": "string" }, "times_played": { "type": "integer" }, "uuid": { "type": "string" } } }, "backend.SongInfo": { "type": "object", "properties": { "CurrentlyPlaying": { "type": "boolean" }, "Song": { "type": "string" }, "SongNo": { "type": "integer" }, "SongPlayed": { "type": "integer" }, "SongUuid": { "type": "string" }, "Soundtrack": { "type": "string" }, "SoundtrackPlayed": { "type": "integer" }, "SoundtrackUuid": { "type": "string" } } }, "backend.SongInfoForStats": { "type": "object", "properties": { "file_name": { "type": "string" }, "path": { "type": "string" }, "song_name": { "type": "string" }, "song_uuid": { "type": "string" }, "soundtrack_id": { "type": "integer" }, "soundtrack_name": { "type": "string" }, "soundtrack_uuid": { "type": "string" }, "times_played": { "type": "integer" } } }, "backend.Soundtrack": { "type": "object", "properties": { "added": { "type": "string" }, "last_played": { "type": "string" }, "name": { "type": "string" }, "times_played": { "type": "integer" }, "uuid": { "type": "string" } } }, "backend.SoundtrackWithSongList": { "type": "object", "properties": { "added": { "type": "string" }, "last_played": { "type": "string" }, "name": { "type": "string" }, "songs": { "type": "array", "items": { "$ref": "#/definitions/backend.Song" } }, "times_played": { "type": "integer" }, "uuid": { "type": "string" } } }, "backend.SoundtrackWithSongs": { "type": "object", "properties": { "songs": { "type": "array", "items": { "$ref": "#/definitions/backend.SongInfoForStats" } }, "soundtrack_id": { "type": "integer" }, "soundtrack_last_played": { "type": "string" }, "soundtrack_name": { "type": "string" }, "soundtrack_played": { "type": "integer" }, "soundtrack_uuid": { "type": "string" } } }, "backend.StatisticsSummary": { "type": "object", "properties": { "avg_soundtrack_plays": { "type": "number" }, "max_soundtrack_plays": { "type": "integer" }, "min_soundtrack_plays": { "type": "integer" }, "never_played_soundtracks": { "type": "integer" }, "played_soundtracks": { "type": "integer" }, "total_soundtrack_plays": { "type": "integer" }, "total_soundtracks": { "type": "integer" } } }, "backend.SyncResponse": { "type": "object", "properties": { "catched_errors": { "type": "array", "items": { "type": "string" } }, "soundtracks_added": { "type": "array", "items": { "type": "string" } }, "soundtracks_changed_content": { "type": "array", "items": { "type": "string" } }, "soundtracks_changed_title": { "type": "object", "additionalProperties": { "type": "string" } }, "soundtracks_re_added": { "type": "array", "items": { "type": "string" } }, "soundtracks_removed": { "type": "array", "items": { "type": "string" } }, "total_time": { "type": "string" } } }, "backend.VersionData": { "type": "object", "properties": { "changelog": { "type": "array", "items": { "type": "string" }, "example": [ "[\"Initial release\"", "\"Bug fixes\"]" ] }, "version": { "type": "string", "example": "1.0.0" } } }, "server.TokenRequest": { "type": "object", "properties": { "client_type": { "description": "Optional: \"web\", \"mobile\", \"api\"", "type": "string" }, "password": { "description": "API password, required when API_PASSWORD is set", "type": "string" } } }, "server.TokenResponse": { "type": "object", "properties": { "client_type": { "type": "string" }, "expires_at": { "type": "string" }, "token": { "type": "string" } } } } }