openapi: 3.1.0
info:
  title: OpenMusic API
  version: 1.0.0
  description: Open standard for music service communication
  license:
    name: AGPL-3.0

servers:
  - url: http://localhost:8080/api
    description: Development server
  - url: https://api.example.com/api
    description: Production server

tags:
  - name: Info
  - name: Songs
  - name: Albums
  - name: Artists
  - name: Playlists
  - name: Stations
  - name: Search

paths:
  /:
    get:
      tags: [Info]
      summary: Get API info
      operationId: getInfo
      parameters:
        - $ref: "#/components/parameters/Lang"
      responses:
        "200":
          description: API info
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InfoResponse"
        "500":
          $ref: "#/components/responses/Error"

  /songs:
    get:
      tags: [Songs]
      summary: Get or list songs
      operationId: getSongs
      parameters:
        - $ref: "#/components/parameters/Lang"
        - $ref: "#/components/parameters/Ids"
        - $ref: "#/components/parameters/OmmIds"
        - $ref: "#/components/parameters/Isrc"
        - $ref: "#/components/parameters/IncludeAll"
        - $ref: "#/components/parameters/View"
        - $ref: "#/components/parameters/ViewSongs"
        - $ref: "#/components/parameters/ViewAlbums"
        - $ref: "#/components/parameters/ViewArtists"
        - $ref: "#/components/parameters/Limit"
        - $ref: "#/components/parameters/Offset"
        - $ref: "#/components/parameters/SortSongs"
        - $ref: "#/components/parameters/FilterGenres"
        - $ref: "#/components/parameters/LimitAlbums"
        - $ref: "#/components/parameters/LimitArtists"
      responses:
        "200":
          description: Matching songs or song list
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SongListResponse"
        "400":
          $ref: "#/components/responses/Error"

  /songs/{id}:
    get:
      tags: [Songs]
      summary: Get song
      operationId: getSong
      parameters:
        - $ref: "#/components/parameters/Lang"
        - $ref: "#/components/parameters/SongId"
        - $ref: "#/components/parameters/IncludeAll"
        - $ref: "#/components/parameters/View"
        - $ref: "#/components/parameters/ViewSongs"
        - $ref: "#/components/parameters/ViewAlbums"
        - $ref: "#/components/parameters/ViewArtists"
        - $ref: "#/components/parameters/LimitAlbums"
        - $ref: "#/components/parameters/LimitArtists"
      responses:
        "200":
          description: Song
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SongResponse"
        "404":
          $ref: "#/components/responses/Error"

  /songs/{id}/rel/albums:
    get:
      tags: [Songs]
      summary: Get related albums for a song
      operationId: getSongAlbums
      parameters:
        - $ref: "#/components/parameters/Lang"
        - $ref: "#/components/parameters/SongId"
        - $ref: "#/components/parameters/IncludeAll"
        - $ref: "#/components/parameters/View"
        - $ref: "#/components/parameters/ViewAlbums"
        - $ref: "#/components/parameters/ViewArtists"
        - $ref: "#/components/parameters/LimitArtists"
      responses:
        "200":
          description: Related albums
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AlbumListResponse"
        "404":
          $ref: "#/components/responses/Error"

  /songs/{id}/rel/artists:
    get:
      tags: [Songs]
      summary: Get related artists for a song
      operationId: getSongArtists
      parameters:
        - $ref: "#/components/parameters/Lang"
        - $ref: "#/components/parameters/SongId"
        - $ref: "#/components/parameters/IncludeAll"
        - $ref: "#/components/parameters/View"
        - $ref: "#/components/parameters/ViewArtists"
        - $ref: "#/components/parameters/ViewAlbums"
        - $ref: "#/components/parameters/LimitAlbums"
      responses:
        "200":
          description: Related artists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ArtistListResponse"
        "404":
          $ref: "#/components/responses/Error"

  /songs/{id}/rel/lyrics:
    get:
      tags: [Songs]
      summary: Get lyrics for a song
      operationId: getSongLyrics
      parameters:
        - $ref: "#/components/parameters/Lang"
        - $ref: "#/components/parameters/SongId"
      responses:
        "200":
          description: Lyrics
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/LyricsResponse"
        "404":
          $ref: "#/components/responses/Error"

  /albums:
    get:
      tags: [Albums]
      summary: Get or list albums
      operationId: getAlbums
      parameters:
        - $ref: "#/components/parameters/Lang"
        - $ref: "#/components/parameters/Ids"
        - $ref: "#/components/parameters/OmmIds"
        - $ref: "#/components/parameters/Upc"
        - $ref: "#/components/parameters/IncludeAll"
        - $ref: "#/components/parameters/View"
        - $ref: "#/components/parameters/ViewAlbums"
        - $ref: "#/components/parameters/ViewArtists"
        - $ref: "#/components/parameters/ViewSongs"
        - $ref: "#/components/parameters/Limit"
        - $ref: "#/components/parameters/Offset"
        - $ref: "#/components/parameters/SortAlbums"
        - $ref: "#/components/parameters/FilterGenres"
        - $ref: "#/components/parameters/LimitArtists"
        - $ref: "#/components/parameters/LimitTracks"
      responses:
        "200":
          description: Matching albums or album list
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AlbumListResponse"
        "400":
          $ref: "#/components/responses/Error"

  /albums/{id}:
    get:
      tags: [Albums]
      summary: Get album
      operationId: getAlbum
      parameters:
        - $ref: "#/components/parameters/Lang"
        - $ref: "#/components/parameters/AlbumId"
        - $ref: "#/components/parameters/IncludeAll"
        - $ref: "#/components/parameters/View"
        - $ref: "#/components/parameters/ViewAlbums"
        - $ref: "#/components/parameters/ViewArtists"
        - $ref: "#/components/parameters/ViewSongs"
        - $ref: "#/components/parameters/LimitArtists"
        - $ref: "#/components/parameters/LimitTracks"
      responses:
        "200":
          description: Album
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AlbumResponse"
        "404":
          $ref: "#/components/responses/Error"

  /albums/{id}/rel/tracks:
    get:
      tags: [Albums]
      summary: Get tracks for an album
      operationId: getAlbumTracks
      parameters:
        - $ref: "#/components/parameters/Lang"
        - $ref: "#/components/parameters/AlbumId"
        - $ref: "#/components/parameters/IncludeAll"
        - $ref: "#/components/parameters/View"
        - $ref: "#/components/parameters/ViewSongs"
        - $ref: "#/components/parameters/ViewAlbums"
        - $ref: "#/components/parameters/ViewArtists"
        - $ref: "#/components/parameters/LimitAlbums"
        - $ref: "#/components/parameters/LimitArtists"
      responses:
        "200":
          description: Album tracks
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SongListResponse"
        "404":
          $ref: "#/components/responses/Error"

  /albums/{id}/rel/artists:
    get:
      tags: [Albums]
      summary: Get artists for an album
      operationId: getAlbumArtists
      parameters:
        - $ref: "#/components/parameters/Lang"
        - $ref: "#/components/parameters/AlbumId"
        - $ref: "#/components/parameters/IncludeAll"
        - $ref: "#/components/parameters/View"
        - $ref: "#/components/parameters/ViewArtists"
        - $ref: "#/components/parameters/ViewAlbums"
        - $ref: "#/components/parameters/LimitAlbums"
      responses:
        "200":
          description: Album artists
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ArtistListResponse"
        "404":
          $ref: "#/components/responses/Error"

  /artists:
    get:
      tags: [Artists]
      summary: Get or list artists
      operationId: getArtists
      parameters:
        - $ref: "#/components/parameters/Lang"
        - $ref: "#/components/parameters/Ids"
        - $ref: "#/components/parameters/OmmIds"
        - $ref: "#/components/parameters/IncludeAll"
        - $ref: "#/components/parameters/View"
        - $ref: "#/components/parameters/ViewArtists"
        - $ref: "#/components/parameters/ViewAlbums"
        - $ref: "#/components/parameters/ViewSongs"
        - $ref: "#/components/parameters/Limit"
        - $ref: "#/components/parameters/Offset"
        - $ref: "#/components/parameters/SortArtists"
        - $ref: "#/components/parameters/FilterGenres"
        - $ref: "#/components/parameters/LimitAlbums"
        - $ref: "#/components/parameters/LimitSongs"
      responses:
        "200":
          description: Matching artists or artist list
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ArtistListResponse"
        "400":
          $ref: "#/components/responses/Error"

  /artists/{id}:
    get:
      tags: [Artists]
      summary: Get artist
      operationId: getArtist
      parameters:
        - $ref: "#/components/parameters/Lang"
        - $ref: "#/components/parameters/ArtistId"
        - $ref: "#/components/parameters/IncludeAll"
        - $ref: "#/components/parameters/View"
        - $ref: "#/components/parameters/ViewArtists"
        - $ref: "#/components/parameters/ViewAlbums"
        - $ref: "#/components/parameters/ViewSongs"
        - $ref: "#/components/parameters/LimitAlbums"
        - $ref: "#/components/parameters/LimitSongs"
      responses:
        "200":
          description: Artist
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ArtistResponse"
        "404":
          $ref: "#/components/responses/Error"

  /artists/{id}/rel/albums:
    get:
      tags: [Artists]
      summary: Get albums for an artist
      operationId: getArtistAlbums
      parameters:
        - $ref: "#/components/parameters/Lang"
        - $ref: "#/components/parameters/ArtistId"
        - $ref: "#/components/parameters/IncludeAll"
        - $ref: "#/components/parameters/View"
        - $ref: "#/components/parameters/ViewAlbums"
        - $ref: "#/components/parameters/ViewArtists"
        - $ref: "#/components/parameters/Limit"
        - $ref: "#/components/parameters/Offset"
        - $ref: "#/components/parameters/SortArtistAlbums"
        - $ref: "#/components/parameters/LimitArtists"
      responses:
        "200":
          description: Artist albums
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AlbumListResponse"
        "404":
          $ref: "#/components/responses/Error"

  /artists/{id}/rel/songs:
    get:
      tags: [Artists]
      summary: Get songs for an artist
      operationId: getArtistSongs
      parameters:
        - $ref: "#/components/parameters/Lang"
        - $ref: "#/components/parameters/ArtistId"
        - $ref: "#/components/parameters/IncludeAll"
        - $ref: "#/components/parameters/View"
        - $ref: "#/components/parameters/ViewSongs"
        - $ref: "#/components/parameters/ViewAlbums"
        - $ref: "#/components/parameters/ViewArtists"
        - $ref: "#/components/parameters/Limit"
        - $ref: "#/components/parameters/Offset"
        - $ref: "#/components/parameters/SortSongs"
        - $ref: "#/components/parameters/LimitAlbums"
        - $ref: "#/components/parameters/LimitArtists"
      responses:
        "200":
          description: Artist songs
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SongListResponse"
        "404":
          $ref: "#/components/responses/Error"

  /playlists:
    get:
      tags: [Playlists]
      summary: Get or list playlists
      operationId: getPlaylists
      parameters:
        - $ref: "#/components/parameters/Lang"
        - $ref: "#/components/parameters/Ids"
        - $ref: "#/components/parameters/IncludeAll"
        - $ref: "#/components/parameters/View"
        - $ref: "#/components/parameters/ViewPlaylists"
        - $ref: "#/components/parameters/ViewSongs"
        - $ref: "#/components/parameters/Limit"
        - $ref: "#/components/parameters/Offset"
        - $ref: "#/components/parameters/SortPlaylists"
        - $ref: "#/components/parameters/FilterGenres"
        - $ref: "#/components/parameters/LimitTracks"
      responses:
        "200":
          description: Matching playlists or playlist list
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PlaylistListResponse"
        "400":
          $ref: "#/components/responses/Error"

  /playlists/{id}:
    get:
      tags: [Playlists]
      summary: Get playlist
      operationId: getPlaylist
      parameters:
        - $ref: "#/components/parameters/Lang"
        - $ref: "#/components/parameters/PlaylistId"
        - $ref: "#/components/parameters/IncludeAll"
        - $ref: "#/components/parameters/View"
        - $ref: "#/components/parameters/ViewPlaylists"
        - $ref: "#/components/parameters/ViewSongs"
        - $ref: "#/components/parameters/LimitTracks"
      responses:
        "200":
          description: Playlist
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PlaylistResponse"
        "404":
          $ref: "#/components/responses/Error"

  /playlists/{id}/rel/tracks:
    get:
      tags: [Playlists]
      summary: Get tracks for a playlist
      operationId: getPlaylistTracks
      parameters:
        - $ref: "#/components/parameters/Lang"
        - $ref: "#/components/parameters/PlaylistId"
        - $ref: "#/components/parameters/IncludeAll"
        - $ref: "#/components/parameters/View"
        - $ref: "#/components/parameters/ViewSongs"
        - $ref: "#/components/parameters/ViewAlbums"
        - $ref: "#/components/parameters/ViewArtists"
        - $ref: "#/components/parameters/LimitAlbums"
        - $ref: "#/components/parameters/LimitArtists"
      responses:
        "200":
          description: Playlist tracks
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SongListResponse"
        "404":
          $ref: "#/components/responses/Error"

  /stations/artist/{id}:
    get:
      tags: [Stations]
      summary: Get artist station
      operationId: getArtistStation
      parameters:
        - $ref: "#/components/parameters/Lang"
        - $ref: "#/components/parameters/ArtistId"
        - $ref: "#/components/parameters/IncludeAll"
        - $ref: "#/components/parameters/View"
        - $ref: "#/components/parameters/ViewStations"
        - $ref: "#/components/parameters/ViewSongs"
        - $ref: "#/components/parameters/LimitTracks"
      responses:
        "200":
          description: Artist station
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/StationResponse"
        "404":
          $ref: "#/components/responses/Error"

  /stations/artist/{id}/rel/tracks:
    get:
      tags: [Stations]
      summary: Get tracks for an artist station
      operationId: getArtistStationTracks
      parameters:
        - $ref: "#/components/parameters/Lang"
        - $ref: "#/components/parameters/ArtistId"
        - $ref: "#/components/parameters/IncludeAll"
        - $ref: "#/components/parameters/View"
        - $ref: "#/components/parameters/ViewSongs"
        - $ref: "#/components/parameters/ViewAlbums"
        - $ref: "#/components/parameters/ViewArtists"
        - $ref: "#/components/parameters/Limit"
        - $ref: "#/components/parameters/Offset"
        - $ref: "#/components/parameters/SortSongs"
        - $ref: "#/components/parameters/LimitAlbums"
        - $ref: "#/components/parameters/LimitArtists"
      responses:
        "200":
          description: Station tracks
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SongListResponse"
        "404":
          $ref: "#/components/responses/Error"

  /stations/genre/{genre}:
    get:
      tags: [Stations]
      summary: Get genre station
      operationId: getGenreStation
      parameters:
        - $ref: "#/components/parameters/Lang"
        - $ref: "#/components/parameters/GenrePath"
        - $ref: "#/components/parameters/IncludeAll"
        - $ref: "#/components/parameters/View"
        - $ref: "#/components/parameters/ViewStations"
        - $ref: "#/components/parameters/ViewSongs"
        - $ref: "#/components/parameters/LimitTracks"
      responses:
        "200":
          description: Genre station
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/StationResponse"
        "404":
          $ref: "#/components/responses/Error"

  /stations/genre/{genre}/rel/tracks:
    get:
      tags: [Stations]
      summary: Get tracks for a genre station
      operationId: getGenreStationTracks
      parameters:
        - $ref: "#/components/parameters/Lang"
        - $ref: "#/components/parameters/GenrePath"
        - $ref: "#/components/parameters/IncludeAll"
        - $ref: "#/components/parameters/View"
        - $ref: "#/components/parameters/ViewSongs"
        - $ref: "#/components/parameters/ViewAlbums"
        - $ref: "#/components/parameters/ViewArtists"
        - $ref: "#/components/parameters/Limit"
        - $ref: "#/components/parameters/Offset"
        - $ref: "#/components/parameters/SortSongs"
        - $ref: "#/components/parameters/LimitAlbums"
        - $ref: "#/components/parameters/LimitArtists"
      responses:
        "200":
          description: Station tracks
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SongListResponse"
        "404":
          $ref: "#/components/responses/Error"

  /stations/popular:
    get:
      tags: [Stations]
      summary: Get popular station
      operationId: getPopularStation
      parameters:
        - $ref: "#/components/parameters/Lang"
        - $ref: "#/components/parameters/IncludeAll"
        - $ref: "#/components/parameters/View"
        - $ref: "#/components/parameters/ViewStations"
        - $ref: "#/components/parameters/ViewSongs"
        - $ref: "#/components/parameters/LimitTracks"
      responses:
        "200":
          description: Popular station
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/StationResponse"
        "404":
          $ref: "#/components/responses/Error"

  /stations/popular/rel/tracks:
    get:
      tags: [Stations]
      summary: Get tracks for the popular station
      operationId: getPopularStationTracks
      parameters:
        - $ref: "#/components/parameters/Lang"
        - $ref: "#/components/parameters/IncludeAll"
        - $ref: "#/components/parameters/View"
        - $ref: "#/components/parameters/ViewSongs"
        - $ref: "#/components/parameters/ViewAlbums"
        - $ref: "#/components/parameters/ViewArtists"
        - $ref: "#/components/parameters/Limit"
        - $ref: "#/components/parameters/Offset"
        - $ref: "#/components/parameters/SortSongs"
        - $ref: "#/components/parameters/LimitAlbums"
        - $ref: "#/components/parameters/LimitArtists"
      responses:
        "200":
          description: Station tracks
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SongListResponse"
        "404":
          $ref: "#/components/responses/Error"

  /search:
    get:
      tags: [Search]
      summary: Search top results
      operationId: searchTop
      parameters:
        - $ref: "#/components/parameters/Lang"
        - $ref: "#/components/parameters/SearchTerm"
        - $ref: "#/components/parameters/IncludeSearchBuckets"
        - $ref: "#/components/parameters/View"
        - $ref: "#/components/parameters/ViewSongs"
        - $ref: "#/components/parameters/ViewAlbums"
        - $ref: "#/components/parameters/ViewArtists"
        - $ref: "#/components/parameters/ViewPlaylists"
        - $ref: "#/components/parameters/ViewStations"
        - $ref: "#/components/parameters/LimitSongs"
        - $ref: "#/components/parameters/LimitAlbums"
        - $ref: "#/components/parameters/LimitArtists"
        - $ref: "#/components/parameters/LimitTracks"
      responses:
        "200":
          description: Search buckets for included resource types
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SearchResponse"
        "400":
          $ref: "#/components/responses/Error"

  /search/songs:
    get:
      tags: [Search]
      summary: Search songs
      operationId: searchSongs
      parameters:
        - $ref: "#/components/parameters/Lang"
        - $ref: "#/components/parameters/SearchTerm"
        - $ref: "#/components/parameters/IncludeAll"
        - $ref: "#/components/parameters/View"
        - $ref: "#/components/parameters/ViewSongs"
        - $ref: "#/components/parameters/ViewAlbums"
        - $ref: "#/components/parameters/ViewArtists"
        - $ref: "#/components/parameters/Limit"
        - $ref: "#/components/parameters/Offset"
        - $ref: "#/components/parameters/FilterGenres"
        - $ref: "#/components/parameters/LimitAlbums"
        - $ref: "#/components/parameters/LimitArtists"
      responses:
        "200":
          description: Song search results
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SongListResponse"
        "400":
          $ref: "#/components/responses/Error"

  /search/albums:
    get:
      tags: [Search]
      summary: Search albums
      operationId: searchAlbums
      parameters:
        - $ref: "#/components/parameters/Lang"
        - $ref: "#/components/parameters/SearchTerm"
        - $ref: "#/components/parameters/IncludeAll"
        - $ref: "#/components/parameters/View"
        - $ref: "#/components/parameters/ViewAlbums"
        - $ref: "#/components/parameters/ViewArtists"
        - $ref: "#/components/parameters/ViewSongs"
        - $ref: "#/components/parameters/Limit"
        - $ref: "#/components/parameters/Offset"
        - $ref: "#/components/parameters/FilterGenres"
        - $ref: "#/components/parameters/LimitArtists"
        - $ref: "#/components/parameters/LimitTracks"
      responses:
        "200":
          description: Album search results
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AlbumListResponse"
        "400":
          $ref: "#/components/responses/Error"

  /search/artists:
    get:
      tags: [Search]
      summary: Search artists
      operationId: searchArtists
      parameters:
        - $ref: "#/components/parameters/Lang"
        - $ref: "#/components/parameters/SearchTerm"
        - $ref: "#/components/parameters/IncludeAll"
        - $ref: "#/components/parameters/View"
        - $ref: "#/components/parameters/ViewArtists"
        - $ref: "#/components/parameters/ViewAlbums"
        - $ref: "#/components/parameters/ViewSongs"
        - $ref: "#/components/parameters/Limit"
        - $ref: "#/components/parameters/Offset"
        - $ref: "#/components/parameters/FilterGenres"
        - $ref: "#/components/parameters/LimitAlbums"
        - $ref: "#/components/parameters/LimitSongs"
      responses:
        "200":
          description: Artist search results
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ArtistListResponse"
        "400":
          $ref: "#/components/responses/Error"

  /search/playlists:
    get:
      tags: [Search]
      summary: Search playlists
      operationId: searchPlaylists
      parameters:
        - $ref: "#/components/parameters/Lang"
        - $ref: "#/components/parameters/SearchTerm"
        - $ref: "#/components/parameters/IncludeAll"
        - $ref: "#/components/parameters/View"
        - $ref: "#/components/parameters/ViewPlaylists"
        - $ref: "#/components/parameters/ViewSongs"
        - $ref: "#/components/parameters/Limit"
        - $ref: "#/components/parameters/Offset"
        - $ref: "#/components/parameters/FilterGenres"
        - $ref: "#/components/parameters/LimitTracks"
      responses:
        "200":
          description: Playlist search results
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PlaylistListResponse"
        "400":
          $ref: "#/components/responses/Error"

components:
  responses:
    Error:
      description: Error response
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"

  parameters:
    Lang:
      name: lang
      in: query
      description: Preferred locale string such as en-US. Implementations may ignore localization, but en-US is the recommended default and fallback.
      schema:
        type: string
        default: en-US
        examples:
          - en-US
          - de-CH

    Ids:
      name: ids
      in: query
      description: Comma-separated resource IDs.
      schema:
        type: string
        examples:
          - "id1,id2,id3"

    OmmIds:
      name: omm_ids
      in: query
      description: Comma-separated OpenMusicMetadata IDs (generally CUID2 strings).
      schema:
        type: string
        examples:
          - "tz4a98xxat96iws9zmbrgj3a,ab12cd34ef56gh78ijklmn"

    Isrc:
      name: isrc
      in: query
      description: Comma-separated ISRC values.
      schema:
        type: string
        examples:
          - "USRC17607839,GBARL0600786"

    Upc:
      name: upc
      in: query
      description: Comma-separated UPC values.
      schema:
        type: string
        examples:
          - "602547673951,888430877625"

    SearchTerm:
      name: term
      in: query
      required: true
      description: Search term.
      schema:
        type: string

    IncludeAll:
      name: include
      in: query
      description: >
        Comma-separated relationships to include. Includes are only one level deep.
        Valid values depend on the endpoint.
      schema:
        type: string
        examples:
          - "artists,albums"
          - "tracks"
          - "songs,albums"

    IncludeSearchBuckets:
      name: include
      in: query
      description: >
        Comma-separated search buckets to return.
        Supported values: top, songs, artists, albums, stations, playlists.
      schema:
        type: string
        examples:
          - "top"
          - "top,songs,artists"
          - "albums,playlists"

    View:
      name: view
      in: query
      description: Apply the same view to the main resource and included relationships.
      schema:
        $ref: "#/components/schemas/ViewMode"

    ViewSongs:
      name: view[songs]
      in: query
      description: View mode for songs.
      schema:
        $ref: "#/components/schemas/ViewMode"

    ViewAlbums:
      name: view[albums]
      in: query
      description: View mode for albums.
      schema:
        $ref: "#/components/schemas/ViewMode"

    ViewArtists:
      name: view[artists]
      in: query
      description: View mode for artists.
      schema:
        $ref: "#/components/schemas/ViewMode"

    ViewPlaylists:
      name: view[playlists]
      in: query
      description: View mode for playlists.
      schema:
        $ref: "#/components/schemas/ViewMode"

    ViewStations:
      name: view[stations]
      in: query
      description: View mode for stations.
      schema:
        $ref: "#/components/schemas/ViewMode"

    Limit:
      name: limit
      in: query
      description: Page size.
      schema:
        type: integer
        minimum: 1
        maximum: 25
        default: 25

    Offset:
      name: offset
      in: query
      description: Number of items to skip.
      schema:
        type: integer
        minimum: 0
        default: 0

    LimitSongs:
      name: limit[songs]
      in: query
      description: Limit included songs.
      schema:
        type: integer
        minimum: 1
        maximum: 25

    LimitAlbums:
      name: limit[albums]
      in: query
      description: Limit included albums.
      schema:
        type: integer
        minimum: 1
        maximum: 25

    LimitArtists:
      name: limit[artists]
      in: query
      description: Limit included artists.
      schema:
        type: integer
        minimum: 1
        maximum: 25

    LimitTracks:
      name: limit[tracks]
      in: query
      description: Limit included tracks.
      schema:
        type: integer
        minimum: 1
        maximum: 25

    FilterGenres:
      name: filter[genres]
      in: query
      description: Comma-separated genres filter.
      schema:
        type: string
        examples:
          - "pop"
          - "pop,rock"

    SortSongs:
      name: sort
      in: query
      description: Sort songs. Prefix with `-` for descending.
      schema:
        type: string
        enum:
          [name, -name, date_released, -date_released, date_added, -date_added]

    SortAlbums:
      name: sort
      in: query
      description: Sort albums. Prefix with `-` for descending.
      schema:
        type: string
        enum:
          [name, -name, date_released, -date_released, date_added, -date_added]

    SortArtistAlbums:
      name: sort
      in: query
      description: Sort artist albums. Prefix with `-` for descending.
      schema:
        type: string
        enum:
          [name, -name, date_released, -date_released, date_added, -date_added]

    SortArtists:
      name: sort
      in: query
      description: Sort artists. Prefix with `-` for descending.
      schema:
        type: string
        enum: [name, -name, date_added, -date_added]

    SortPlaylists:
      name: sort
      in: query
      description: Sort playlists. Prefix with `-` for descending.
      schema:
        type: string
        enum: [name, -name, date_added, -date_added]

    SongId:
      name: id
      in: path
      required: true
      schema:
        type: string

    AlbumId:
      name: id
      in: path
      required: true
      schema:
        type: string

    ArtistId:
      name: id
      in: path
      required: true
      schema:
        type: string

    PlaylistId:
      name: id
      in: path
      required: true
      schema:
        type: string

    GenrePath:
      name: genre
      in: path
      required: true
      schema:
        type: string

  schemas:
    ViewMode:
      type: string
      enum: [minimal]

    ResourceBase:
      type: object
      required: [id, type]
      properties:
        id:
          type: string
        type:
          type: string

    Meta:
      type: object
      required: [omm_id]
      properties:
        omm_id:
          type: [string, "null"]

    Lyrics:
      type: object
      required: [text, language]
      properties:
        text:
          type: string
        language:
          type: [string, "null"]

    File:
      type: object
      required: [download_url, lossless, mime_type, codec, bitrate, stream_url]
      properties:
        download_url:
          type: string
          format: uri
        lossless:
          type: boolean
        mime_type:
          type: string
          description: "example: audio/mpeg"
        codec:
          type: [string, "null"]
          description: "example: mp3"
        bitrate:
          type: [integer, "null"]
          description: Average or target bitrate in bps.
        stream_url:
          type: [string, "null"]
          format: uri

    SongAttributes:
      type: object
      required:
        - name
        - album_name
        - artist_name
        - isrc
        - artwork_url
        - track_number
        - disc_number
        - genres
        - release_date
      properties:
        name:
          type: string
        album_name:
          type: [string, "null"]
        artist_name:
          type: [string, "null"]
        isrc:
          type: [string, "null"]
        artwork_url:
          type: [string, "null"]
          format: uri
        track_number:
          type: [integer, "null"]
        disc_number:
          type: [integer, "null"]
        genres:
          type: array
          items:
            type: string
        release_date:
          type: [string, "null"]
          format: date

    AlbumAttributes:
      type: object
      required:
        - name
        - artist_name
        - upc
        - artwork_url
        - track_count
        - genres
        - release_date
      properties:
        name:
          type: string
        artist_name:
          type: [string, "null"]
        upc:
          type: [string, "null"]
        artwork_url:
          type: [string, "null"]
          format: uri
        track_count:
          type: [integer, "null"]
        genres:
          type: array
          items:
            type: string
        release_date:
          type: [string, "null"]
          format: date

    ArtistAttributes:
      type: object
      required:
        - name
        - artwork_url
        - genres
      properties:
        name:
          type: string
        artwork_url:
          type: [string, "null"]
          format: uri
        genres:
          type: array
          items:
            type: string

    PlaylistAttributes:
      type: object
      required:
        - name
        - curator_name
        - description
        - artwork_url
        - genres
      properties:
        name:
          type: string
        curator_name:
          type: string
          description: Who created the playlist?
        description:
          type: [string, "null"]
        artwork_url:
          type: [string, "null"]
          format: uri
        genres:
          type: array
          items:
            type: string

    StationSeedArtist:
      type: object
      required: [kind, artist]
      properties:
        kind:
          type: string
          const: artist
        artist:
          $ref: "#/components/schemas/ArtistBase"

    StationSeedGenre:
      type: object
      required: [kind, genre]
      properties:
        kind:
          type: string
          const: genre
        genre:
          type: string

    StationSeedPopular:
      type: object
      required: [kind]
      properties:
        kind:
          type: string
          const: popular

    StationSeed:
      oneOf:
        - $ref: "#/components/schemas/StationSeedArtist"
        - $ref: "#/components/schemas/StationSeedGenre"
        - $ref: "#/components/schemas/StationSeedPopular"

    StationAttributes:
      type: object
      required:
        - name
        - seed
        - description
        - artwork_url
        - genres
      properties:
        name:
          type: string
        seed:
          $ref: "#/components/schemas/StationSeed"
        description:
          type: [string, "null"]
        artwork_url:
          type: [string, "null"]
          format: uri
        genres:
          type: array
          items:
            type: string

    SongInstance:
      type: object
      required: [duration_in_ms, files, has_lyrics]
      properties:
        duration_in_ms:
          type: integer
        files:
          type: array
          items:
            $ref: "#/components/schemas/File"
        has_lyrics:
          type: boolean

    SongBase:
      allOf:
        - $ref: "#/components/schemas/ResourceBase"
        - type: object
          required: [type, meta, instance]
          properties:
            type:
              type: string
              const: songs
            meta:
              $ref: "#/components/schemas/Meta"
            instance:
              $ref: "#/components/schemas/SongInstance"
            relationships:
              $ref: "#/components/schemas/SongRelationships"

    Song:
      allOf:
        - $ref: "#/components/schemas/SongBase"
        - type: object
          required: [attributes]
          properties:
            attributes:
              $ref: "#/components/schemas/SongAttributes"

    AlbumBase:
      allOf:
        - $ref: "#/components/schemas/ResourceBase"
        - type: object
          required: [type, meta]
          properties:
            type:
              type: string
              const: albums
            meta:
              $ref: "#/components/schemas/Meta"
            relationships:
              $ref: "#/components/schemas/AlbumRelationships"

    Album:
      allOf:
        - $ref: "#/components/schemas/AlbumBase"
        - type: object
          required: [attributes]
          properties:
            attributes:
              $ref: "#/components/schemas/AlbumAttributes"

    ArtistBase:
      allOf:
        - $ref: "#/components/schemas/ResourceBase"
        - type: object
          required: [type, meta]
          properties:
            type:
              type: string
              const: artists
            meta:
              $ref: "#/components/schemas/Meta"
            relationships:
              $ref: "#/components/schemas/ArtistRelationships"

    Artist:
      allOf:
        - $ref: "#/components/schemas/ArtistBase"
        - type: object
          required: [attributes]
          properties:
            attributes:
              $ref: "#/components/schemas/ArtistAttributes"

    PlaylistBase:
      allOf:
        - $ref: "#/components/schemas/ResourceBase"
        - type: object
          required: [type]
          properties:
            type:
              type: string
              const: playlists
            relationships:
              $ref: "#/components/schemas/PlaylistRelationships"

    Playlist:
      allOf:
        - $ref: "#/components/schemas/PlaylistBase"
        - type: object
          required: [attributes]
          properties:
            attributes:
              $ref: "#/components/schemas/PlaylistAttributes"

    StationBase:
      allOf:
        - $ref: "#/components/schemas/ResourceBase"
        - type: object
          required: [type]
          properties:
            type:
              type: string
              const: stations
            relationships:
              $ref: "#/components/schemas/StationRelationships"

    Station:
      allOf:
        - $ref: "#/components/schemas/StationBase"
        - type: object
          required: [attributes]
          properties:
            attributes:
              $ref: "#/components/schemas/StationAttributes"

    SongResource:
      oneOf:
        - $ref: "#/components/schemas/SongBase"
        - $ref: "#/components/schemas/Song"

    AlbumResource:
      oneOf:
        - $ref: "#/components/schemas/AlbumBase"
        - $ref: "#/components/schemas/Album"

    ArtistResource:
      oneOf:
        - $ref: "#/components/schemas/ArtistBase"
        - $ref: "#/components/schemas/Artist"

    PlaylistResource:
      oneOf:
        - $ref: "#/components/schemas/PlaylistBase"
        - $ref: "#/components/schemas/Playlist"

    StationResource:
      oneOf:
        - $ref: "#/components/schemas/StationBase"
        - $ref: "#/components/schemas/Station"

    AnyResource:
      oneOf:
        - $ref: "#/components/schemas/SongBase"
        - $ref: "#/components/schemas/Song"
        - $ref: "#/components/schemas/AlbumBase"
        - $ref: "#/components/schemas/Album"
        - $ref: "#/components/schemas/ArtistBase"
        - $ref: "#/components/schemas/Artist"
        - $ref: "#/components/schemas/PlaylistBase"
        - $ref: "#/components/schemas/Playlist"
        - $ref: "#/components/schemas/StationBase"
        - $ref: "#/components/schemas/Station"

    SongRelationships:
      type: object
      properties:
        albums:
          type: array
          items:
            $ref: "#/components/schemas/AlbumResource"
        artists:
          type: array
          items:
            $ref: "#/components/schemas/ArtistResource"
        lyrics:
          $ref: "#/components/schemas/Lyrics"

    AlbumRelationships:
      type: object
      properties:
        tracks:
          type: array
          items:
            $ref: "#/components/schemas/SongResource"
        artists:
          type: array
          items:
            $ref: "#/components/schemas/ArtistResource"

    ArtistRelationships:
      type: object
      properties:
        albums:
          type: array
          items:
            $ref: "#/components/schemas/AlbumResource"
        songs:
          type: array
          items:
            $ref: "#/components/schemas/SongResource"

    PlaylistRelationships:
      type: object
      properties:
        tracks:
          type: array
          items:
            $ref: "#/components/schemas/SongResource"

    StationRelationships:
      type: object
      properties:
        tracks:
          type: array
          items:
            $ref: "#/components/schemas/SongResource"

    SingleResourceResponse_Song:
      type: object
      required: [data]
      properties:
        data:
          $ref: "#/components/schemas/SongResource"

    SingleResourceResponse_Album:
      type: object
      required: [data]
      properties:
        data:
          $ref: "#/components/schemas/AlbumResource"

    SingleResourceResponse_Artist:
      type: object
      required: [data]
      properties:
        data:
          $ref: "#/components/schemas/ArtistResource"

    SingleResourceResponse_Playlist:
      type: object
      required: [data]
      properties:
        data:
          $ref: "#/components/schemas/PlaylistResource"

    SingleResourceResponse_Station:
      type: object
      required: [data]
      properties:
        data:
          $ref: "#/components/schemas/StationResource"

    SingleResourceResponse_Lyrics:
      type: object
      required: [data]
      properties:
        data:
          $ref: "#/components/schemas/Lyrics"

    ListResourceResponse_Song:
      type: object
      required: [data, meta]
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/SongResource"
        meta:
          $ref: "#/components/schemas/ListMeta"

    ListResourceResponse_Album:
      type: object
      required: [data, meta]
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/AlbumResource"
        meta:
          $ref: "#/components/schemas/ListMeta"

    ListResourceResponse_Artist:
      type: object
      required: [data, meta]
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/ArtistResource"
        meta:
          $ref: "#/components/schemas/ListMeta"

    ListResourceResponse_Playlist:
      type: object
      required: [data, meta]
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/PlaylistResource"
        meta:
          $ref: "#/components/schemas/ListMeta"

    ListResourceResponse_Station:
      type: object
      required: [data, meta]
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/StationResource"
        meta:
          $ref: "#/components/schemas/ListMeta"

    ListMeta:
      type: object
      required: [limit, offset, has_next_page]
      properties:
        limit:
          type: integer
        offset:
          type: integer
        has_next_page:
          type: boolean

    SearchData:
      type: object
      properties:
        top:
          type: array
          items:
            $ref: "#/components/schemas/AnyResource"
        songs:
          type: array
          items:
            $ref: "#/components/schemas/SongResource"
        artists:
          type: array
          items:
            $ref: "#/components/schemas/ArtistResource"
        albums:
          type: array
          items:
            $ref: "#/components/schemas/AlbumResource"
        stations:
          type: array
          items:
            $ref: "#/components/schemas/StationResource"
        playlists:
          type: array
          items:
            $ref: "#/components/schemas/PlaylistResource"

    SearchResponse:
      type: object
      required: [data]
      properties:
        data:
          $ref: "#/components/schemas/SearchData"

    Info:
      type: object
      required: [branding, openmusic]
      properties:
        branding:
          type: object
          required: [name, email, logo, short_name, theme, homepage]
          properties:
            name:
              type: string
            email:
              type: string
              format: email
            logo:
              type: [string, "null"]
              format: uri
            short_name:
              type: [string, "null"]
            theme:
              type: [string, "null"]
            homepage:
              type: [string, "null"]
              format: uri
        openmusic:
          type: object
          required: [version, capabilities]
          properties:
            version:
              type: string
            capabilities:
              type: object
              required:
                - info
                - search
                - song
                - download
                - stream
                - albums
                - artists
                - playlists
                - stations
                - sort
                - lyrics
              properties:
                info:
                  type: boolean
                  const: true
                search:
                  type: boolean
                  const: true
                song:
                  type: boolean
                  const: true
                  description: Search and get songs
                download:
                  type: boolean
                  const: true
                stream:
                  type: boolean
                  description: Allow streaming
                albums:
                  type: boolean
                  description: Search and get albums
                artists:
                  type: boolean
                  description: Search and get artists
                playlists:
                  type: boolean
                  description: Search and get playlists
                stations:
                  type: boolean
                  description: Search and get stations
                sort:
                  type: boolean
                  description: Sort by date_released, date_added or name
                lyrics:
                  type: boolean

    SingleResourceResponse_Info:
      type: object
      required: [data]
      properties:
        data:
          $ref: "#/components/schemas/Info"

    ErrorObject:
      type: object
      required: [code, title, message, trace_id]
      properties:
        code:
          type: integer
        title:
          type: string
        message:
          type: string
        trace_id:
          type: [string, "null"]

    ErrorResponse:
      type: object
      required: [error]
      properties:
        error:
          $ref: "#/components/schemas/ErrorObject"

    SongResponse:
      $ref: "#/components/schemas/SingleResourceResponse_Song"

    SongListResponse:
      $ref: "#/components/schemas/ListResourceResponse_Song"

    AlbumResponse:
      $ref: "#/components/schemas/SingleResourceResponse_Album"

    AlbumListResponse:
      $ref: "#/components/schemas/ListResourceResponse_Album"

    ArtistResponse:
      $ref: "#/components/schemas/SingleResourceResponse_Artist"

    ArtistListResponse:
      $ref: "#/components/schemas/ListResourceResponse_Artist"

    PlaylistResponse:
      $ref: "#/components/schemas/SingleResourceResponse_Playlist"

    PlaylistListResponse:
      $ref: "#/components/schemas/ListResourceResponse_Playlist"

    StationResponse:
      $ref: "#/components/schemas/SingleResourceResponse_Station"

    LyricsResponse:
      $ref: "#/components/schemas/SingleResourceResponse_Lyrics"

    InfoResponse:
      $ref: "#/components/schemas/SingleResourceResponse_Info"
