openapi: 3.0.0
paths:
  /:
    get:
      operationId: AppController_getLandingPage
      parameters: []
      responses:
        "200":
          description: Renders a short overview page and links to documentation
          content:
            application/json:
              schema:
                type: string
      summary: Landing page with interactive route explorer
      tags: &a1
        - Root
  /routes:
    get:
      operationId: AppController_getRoutes
      parameters: []
      responses:
        "200":
          description: JSON object containing all available routes organized by module
      summary: Get all available API routes
      tags: *a1
  /changelog:
    get:
      operationId: AppController_getChangelog
      parameters: []
      responses:
        "200":
          description: Returns the project CHANGELOG in Markdown format
          content:
            application/json:
              schema:
                type: string
      summary: Project changelog (Markdown)
      tags: *a1
  /health:
    get:
      operationId: AppController_getHealth
      parameters: []
      responses:
        "200":
          description: Returns health status including database connectivity
      summary: Health check endpoint with critical system status
      tags: *a1
  /health/ready:
    get:
      operationId: AppController_getReadiness
      parameters: []
      responses:
        "200":
          description: Service is ready
        "503":
          description: Service is not ready
      summary: Readiness check (database required)
      tags: *a1
  /status:
    get:
      operationId: OpsController_getStatus
      parameters: []
      responses:
        "200":
          description: Service is alive
      summary: Lightweight liveness check
      tags: &a2
        - Ops
  /config/public:
    get:
      operationId: OpsController_getPublicConfig
      parameters: []
      responses:
        "200":
          description: Public config
      summary: Public runtime configuration (non-secret)
      tags: *a2
  /rate-limits:
    get:
      operationId: OpsController_getRateLimits
      parameters: []
      responses:
        "200":
          description: Rate limit policy
      summary: Rate limit policy information
      tags: *a2
  /docs/openapi:
    get:
      operationId: OpsController_getOpenApiAlias
      parameters: []
      responses:
        "302":
          description: Redirect to /openapi.json
      summary: Alias to OpenAPI JSON spec
      tags: *a2
  /cache/stats:
    get:
      operationId: OpsController_getCacheStats[0]
      parameters: []
      responses:
        "200":
          description: Cache statistics
      security:
        - bearer: []
      summary: Get in-memory cache stats
      tags: *a2
  /api/v2/cache/stats:
    get:
      operationId: OpsController_getCacheStats[1]
      parameters: []
      responses:
        "200":
          description: Cache statistics
      security:
        - bearer: []
      summary: Get in-memory cache stats
      tags: *a2
  /cache/clear:
    post:
      operationId: OpsController_clearCaches
      parameters: []
      responses:
        "200":
          description: Cache cleared
      security:
        - bearer: []
      summary: Clear in-memory caches
      tags: *a2
  /analytics/overview:
    get:
      operationId: OpsController_getAnalyticsOverview[0]
      parameters:
        - name: days
          required: true
          in: query
          schema:
            type: string
        - name: limit
          required: true
          in: query
          schema:
            type: string
      responses:
        "200":
          description: Analytics overview
      security:
        - bearer: []
      summary: Get API analytics overview (traffic share, latency, and auth session
        longevity)
      tags: *a2
  /api/v2/analytics/overview:
    get:
      operationId: OpsController_getAnalyticsOverview[1]
      parameters:
        - name: days
          required: true
          in: query
          schema:
            type: string
        - name: limit
          required: true
          in: query
          schema:
            type: string
      responses:
        "200":
          description: Analytics overview
      security:
        - bearer: []
      summary: Get API analytics overview (traffic share, latency, and auth session
        longevity)
      tags: *a2
  /analytics/routes:
    get:
      operationId: OpsController_getRouteAnalytics[0]
      parameters:
        - name: days
          required: true
          in: query
          schema:
            type: string
        - name: limit
          required: true
          in: query
          schema:
            type: string
      responses:
        "200":
          description: Per-route analytics usage
      security:
        - bearer: []
      summary: Get per-route analytics usage including request totals, percentages,
        and latency
      tags: *a2
  /api/v2/analytics/routes:
    get:
      operationId: OpsController_getRouteAnalytics[1]
      parameters:
        - name: days
          required: true
          in: query
          schema:
            type: string
        - name: limit
          required: true
          in: query
          schema:
            type: string
      responses:
        "200":
          description: Per-route analytics usage
      security:
        - bearer: []
      summary: Get per-route analytics usage including request totals, percentages,
        and latency
      tags: *a2
  /metrics:
    get:
      operationId: OpsController_getMetrics
      parameters: []
      responses:
        "200":
          description: Prometheus metrics payload
          content:
            text/plain:
              schema:
                type: string
      summary: Prometheus-style metrics
      tags: *a2
  /api/spotify/search/tracks:
    get:
      operationId: SpotifyController_searchTracks
      parameters:
        - name: query
          required: true
          in: query
          description: Search query string
          schema:
            type: string
        - name: limit
          required: false
          in: query
          description: Number of results to return (default 10)
          schema:
            type: number
      responses:
        "200":
          description: ""
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/TrackDto"
      summary: Search for tracks on Spotify
      tags: &a3
        - Spotify
  /api/spotify/recommendations:
    get:
      operationId: SpotifyController_getRecommendations
      parameters:
        - name: seed_tracks
          required: false
          in: query
          description: Comma-separated Spotify track IDs
          schema:
            example: 4iV5W9uYEdYUVa79Axb7Rh,0VjIjW4GlUZ9YafUnjvTv7
            type: string
        - name: seed_artists
          required: false
          in: query
          description: Comma-separated Spotify artist IDs
          schema:
            example: 4Z8W4fKeB5YxbusRsdQVPb
            type: string
        - name: seed_genres
          required: false
          in: query
          description: Comma-separated genre names
          schema:
            example: rock,pop,indie
            type: string
        - name: limit
          required: false
          in: query
          description: Number of recommendations (1-100)
          schema:
            default: 20
            type: number
        - name: market
          required: false
          in: query
          description: Market code (ISO 3166-1 alpha-2)
          schema:
            type: string
        - name: target_danceability
          required: false
          in: query
          description: Target danceability (0.0-1.0)
          schema:
            type: number
        - name: target_popularity
          required: false
          in: query
          description: Target popularity (0-100)
          schema:
            type: number
      responses:
        "200":
          description: ""
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RecommendationResponseDto"
      summary: Get Spotify recommendations using seeds
      tags: *a3
  /api/spotify/recommendations/from-search:
    post:
      operationId: SpotifyController_getRecommendationsFromSearch
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/RecommendationsFromSearchRequestDto"
      responses:
        "200":
          description: ""
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RecommendationResponseDto"
      summary: Search for a track and get recommendations seeded from it
      tags: *a3
  /api/spotify/recommendations/spice-up:
    post:
      operationId: SpotifyController_spiceUpPlaylist
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SpiceUpRequestDto"
      responses:
        "200":
          description: ""
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SpiceUpResponseDto"
      summary: Generate recommendations to spice up a playlist
      tags: *a3
  /api/spotify/recommendations/spice-up/unified:
    post:
      operationId: SpotifyController_spiceUpPlaylistUnified
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UnifiedSpiceUpRequestDto"
      responses:
        "200":
          description: ""
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UnifiedSpiceUpResponseDto"
      summary: Generate recommendations using multiple platforms (Spotify, Last.fm,
        Deezer)
      tags: *a3
  /api/spotify/playlists/import:
    post:
      operationId: SpotifyController_importPlaylist
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ImportSpotifyPlaylistRequestDto"
      responses:
        "200":
          description: Translates Spotify tracks to Deezer/native matches and creates the
            native playlist
      security:
        - bearer: []
      summary: Import a Spotify playlist into a native playlist without backend
        Spotify OAuth session
      tags: *a3
  /auth/register:
    post:
      operationId: AuthController_register[0]
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/RegisterDto"
      responses:
        "201":
          description: The user has been successfully created.
      summary: Register a new user
      tags: &a4
        - auth
  /api/auth/register:
    post:
      operationId: AuthController_register[1]
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/RegisterDto"
      responses:
        "201":
          description: The user has been successfully created.
      summary: Register a new user
      tags: *a4
  /api/v2/auth/register:
    post:
      operationId: AuthController_register[2]
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/RegisterDto"
      responses:
        "201":
          description: The user has been successfully created.
      summary: Register a new user
      tags: *a4
  /auth/login:
    post:
      operationId: AuthController_login[0]
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/LoginDto"
      responses:
        "200":
          description: User successfully logged in.
      summary: Log in a user
      tags: *a4
  /api/auth/login:
    post:
      operationId: AuthController_login[1]
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/LoginDto"
      responses:
        "200":
          description: User successfully logged in.
      summary: Log in a user
      tags: *a4
  /api/v2/auth/login:
    post:
      operationId: AuthController_login[2]
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/LoginDto"
      responses:
        "200":
          description: User successfully logged in.
      summary: Log in a user
      tags: *a4
  /auth/token:
    post:
      operationId: AuthController_issueServiceToken[0]
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/IssueServiceTokenDto"
      responses:
        "200":
          description: Returns a scoped bearer token for service endpoints.
      summary: Issue a short-lived bearer token for scoped service access using
        UNIVERSAL_KEY
      tags: *a4
  /api/auth/token:
    post:
      operationId: AuthController_issueServiceToken[1]
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/IssueServiceTokenDto"
      responses:
        "200":
          description: Returns a scoped bearer token for service endpoints.
      summary: Issue a short-lived bearer token for scoped service access using
        UNIVERSAL_KEY
      tags: *a4
  /api/v2/auth/token:
    post:
      operationId: AuthController_issueServiceToken[2]
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/IssueServiceTokenDto"
      responses:
        "200":
          description: Returns a scoped bearer token for service endpoints.
      summary: Issue a short-lived bearer token for scoped service access using
        UNIVERSAL_KEY
      tags: *a4
  /auth/spotify:
    get:
      operationId: AuthController_startSpotifyLogin[0]
      parameters:
        - name: frontend_redirect_uri
          required: false
          in: query
          description: Optional frontend URL to redirect to after successful callback.
            HTTP(S) origins must match AUTH_FRONTEND_ORIGINS. Native app schemes
            must match AUTH_FRONTEND_NATIVE_SCHEMES.
          schema:
            type: string
      responses:
        "302":
          description: Redirects to Spotify authorize UI
      summary: Start Spotify OAuth2 Authorization Code + PKCE flow
      tags: *a4
  /api/auth/spotify:
    get:
      operationId: AuthController_startSpotifyLogin[1]
      parameters:
        - name: frontend_redirect_uri
          required: false
          in: query
          description: Optional frontend URL to redirect to after successful callback.
            HTTP(S) origins must match AUTH_FRONTEND_ORIGINS. Native app schemes
            must match AUTH_FRONTEND_NATIVE_SCHEMES.
          schema:
            type: string
      responses:
        "302":
          description: Redirects to Spotify authorize UI
      summary: Start Spotify OAuth2 Authorization Code + PKCE flow
      tags: *a4
  /api/v2/auth/spotify:
    get:
      operationId: AuthController_startSpotifyLogin[2]
      parameters:
        - name: frontend_redirect_uri
          required: false
          in: query
          description: Optional frontend URL to redirect to after successful callback.
            HTTP(S) origins must match AUTH_FRONTEND_ORIGINS. Native app schemes
            must match AUTH_FRONTEND_NATIVE_SCHEMES.
          schema:
            type: string
      responses:
        "302":
          description: Redirects to Spotify authorize UI
      summary: Start Spotify OAuth2 Authorization Code + PKCE flow
      tags: *a4
  /auth/spotify/callback:
    get:
      operationId: AuthController_handleSpotifyCallback[0]
      parameters: []
      responses:
        "200":
          description: Returns auth payload or redirects to frontend_redirect_uri
      summary: Handle Spotify callback, exchange code for tokens, and issue app JWT
      tags: *a4
  /api/auth/spotify/callback:
    get:
      operationId: AuthController_handleSpotifyCallback[1]
      parameters: []
      responses:
        "200":
          description: Returns auth payload or redirects to frontend_redirect_uri
      summary: Handle Spotify callback, exchange code for tokens, and issue app JWT
      tags: *a4
  /api/v2/auth/spotify/callback:
    get:
      operationId: AuthController_handleSpotifyCallback[2]
      parameters: []
      responses:
        "200":
          description: Returns auth payload or redirects to frontend_redirect_uri
      summary: Handle Spotify callback, exchange code for tokens, and issue app JWT
      tags: *a4
  /auth/debug-cookies:
    get:
      operationId: AuthController_debugCookieTransmission[0]
      parameters: []
      responses:
        "200":
          description: Returns cookie key diagnostics for OAuth callback troubleshooting.
      summary: Inspect cookies received by the auth endpoints
      tags: *a4
  /api/auth/debug-cookies:
    get:
      operationId: AuthController_debugCookieTransmission[1]
      parameters: []
      responses:
        "200":
          description: Returns cookie key diagnostics for OAuth callback troubleshooting.
      summary: Inspect cookies received by the auth endpoints
      tags: *a4
  /api/v2/auth/debug-cookies:
    get:
      operationId: AuthController_debugCookieTransmission[2]
      parameters: []
      responses:
        "200":
          description: Returns cookie key diagnostics for OAuth callback troubleshooting.
      summary: Inspect cookies received by the auth endpoints
      tags: *a4
  /auth/spotify/refresh:
    post:
      operationId: AuthController_refreshSpotifySession[0]
      parameters: []
      requestBody:
        required: false
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SpotifyRefreshDto"
      responses:
        "200":
          description: Session refreshed successfully
      summary: Refresh app JWT and refresh Spotify access token if needed
      tags: *a4
  /api/auth/spotify/refresh:
    post:
      operationId: AuthController_refreshSpotifySession[1]
      parameters: []
      requestBody:
        required: false
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SpotifyRefreshDto"
      responses:
        "200":
          description: Session refreshed successfully
      summary: Refresh app JWT and refresh Spotify access token if needed
      tags: *a4
  /api/v2/auth/spotify/refresh:
    post:
      operationId: AuthController_refreshSpotifySession[2]
      parameters: []
      requestBody:
        required: false
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SpotifyRefreshDto"
      responses:
        "200":
          description: Session refreshed successfully
      summary: Refresh app JWT and refresh Spotify access token if needed
      tags: *a4
  /auth/me:
    get:
      operationId: AuthController_getProfile[0]
      parameters: []
      responses:
        "200":
          description: Return current user info
      security:
        - bearer: []
      summary: Get current user info
      tags: *a4
  /api/auth/me:
    get:
      operationId: AuthController_getProfile[1]
      parameters: []
      responses:
        "200":
          description: Return current user info
      security:
        - bearer: []
      summary: Get current user info
      tags: *a4
  /api/v2/auth/me:
    get:
      operationId: AuthController_getProfile[2]
      parameters: []
      responses:
        "200":
          description: Return current user info
      security:
        - bearer: []
      summary: Get current user info
      tags: *a4
  /auth/refresh:
    get:
      operationId: AuthController_refresh[0]
      parameters: []
      responses:
        "200":
          description: Token refreshed successfully.
      security:
        - bearer: []
      summary: Refresh the current JWT token
      tags: *a4
  /api/auth/refresh:
    get:
      operationId: AuthController_refresh[1]
      parameters: []
      responses:
        "200":
          description: Token refreshed successfully.
      security:
        - bearer: []
      summary: Refresh the current JWT token
      tags: *a4
  /api/v2/auth/refresh:
    get:
      operationId: AuthController_refresh[2]
      parameters: []
      responses:
        "200":
          description: Token refreshed successfully.
      security:
        - bearer: []
      summary: Refresh the current JWT token
      tags: *a4
  /auth/spotify/debug:
    get:
      operationId: AuthController_getSpotifyDebugEvents[0]
      parameters:
        - name: trace_id
          required: false
          in: query
          description: Optional trace id to filter events.
          schema:
            type: string
        - name: limit
          required: false
          in: query
          description: Optional max number of events to return (1-500).
          schema:
            type: string
      responses:
        "200":
          description: Returns recent in-memory auth diagnostic events.
      summary: Inspect recent sanitized Spotify auth debug events (requires
        AUTH_DEBUG_LOGS).
      tags: *a4
  /api/auth/spotify/debug:
    get:
      operationId: AuthController_getSpotifyDebugEvents[1]
      parameters:
        - name: trace_id
          required: false
          in: query
          description: Optional trace id to filter events.
          schema:
            type: string
        - name: limit
          required: false
          in: query
          description: Optional max number of events to return (1-500).
          schema:
            type: string
      responses:
        "200":
          description: Returns recent in-memory auth diagnostic events.
      summary: Inspect recent sanitized Spotify auth debug events (requires
        AUTH_DEBUG_LOGS).
      tags: *a4
  /api/v2/auth/spotify/debug:
    get:
      operationId: AuthController_getSpotifyDebugEvents[2]
      parameters:
        - name: trace_id
          required: false
          in: query
          description: Optional trace id to filter events.
          schema:
            type: string
        - name: limit
          required: false
          in: query
          description: Optional max number of events to return (1-500).
          schema:
            type: string
      responses:
        "200":
          description: Returns recent in-memory auth diagnostic events.
      summary: Inspect recent sanitized Spotify auth debug events (requires
        AUTH_DEBUG_LOGS).
      tags: *a4
  /api/music/search/tracks:
    get:
      operationId: DeezerController_searchTracks
      parameters:
        - name: query
          required: true
          in: query
          description: Search query string
          schema:
            type: string
        - name: limit
          required: false
          in: query
          description: Number of results to return (max 25)
          schema:
            type: number
      responses:
        "200":
          description: Raw response from Deezer search API
      summary: Search for tracks on Deezer
      tags: &a5
        - Deezer
  /api/music/genres:
    get:
      operationId: DeezerController_getGenresEnglish
      parameters: []
      responses:
        "200":
          description: List of Deezer genres in English
      summary: Get Deezer genres (English)
      tags: *a5
  /api/music/releases/latest:
    get:
      operationId: DeezerController_getLatestReleases
      parameters:
        - name: limit
          required: false
          in: query
          description: "Number of releases to return (default: 25, max: 100)"
          schema:
            type: number
      responses:
        "200":
          description: Latest releases from Deezer editorial API
      summary: Get latest releases on Deezer
      tags: *a5
  /api/music/playlists/popular:
    get:
      operationId: DeezerController_getPopularPlaylists
      parameters:
        - name: limit
          required: false
          in: query
          description: "Number of playlists to return (default: 25, max: 100)"
          schema:
            type: number
      responses:
        "200":
          description: Popular playlists from Deezer charts
      summary: Get most popular playlists on Deezer
      tags: *a5
  /api/music/playlists/by-genre:
    get:
      operationId: DeezerController_getPlaylistsByGenre
      parameters:
        - name: genre
          required: true
          in: query
          description: Genre name (e.g., Pop, Rock, Hip Hop)
          schema:
            type: string
        - name: limit
          required: false
          in: query
          description: "Number of playlists to return (default: 25, max: 100)"
          schema:
            type: number
      responses:
        "200":
          description: Playlists matching the genre, using Deezer playlist search
      summary: Get playlists by genre (best-effort search)
      tags: *a5
  /api/music/playlists/by-genre-id:
    get:
      operationId: DeezerController_getPlaylistsByGenreId
      parameters:
        - name: genreId
          required: true
          in: query
          description: Deezer genre ID (e.g., 132 for Pop)
          schema:
            type: number
        - name: limit
          required: false
          in: query
          description: "Number of playlists to return (default: 25, max: 100)"
          schema:
            type: number
      responses:
        "200":
          description: Playlists matching the genre ID, resolved to a genre name
      summary: Get playlists by genre ID (best-effort search)
      tags: *a5
  /api/music/playlists/{id}:
    get:
      operationId: DeezerController_getPlaylistTracks
      parameters:
        - name: id
          required: true
          in: path
          description: Deezer playlist ID
          schema:
            example: 908622995
            type: string
      responses:
        "200":
          description: Array of detailed track objects in playlist order
      summary: Get all tracks from a Deezer playlist in playlist order
      tags: *a5
  /api/music/track/find-id:
    get:
      operationId: DeezerController_findTrackId
      parameters:
        - name: name
          required: true
          in: query
          description: Track title
          schema:
            type: string
        - name: artist
          required: false
          in: query
          description: Artist name to improve accuracy
          schema:
            type: string
      responses:
        "200":
          description: ""
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/FindTrackIdResponseDto"
      summary: Find a Deezer track ID by name and artist
      tags: *a5
  /api/music/tracks/convert:
    post:
      operationId: DeezerController_convertTracksToDeezerIds
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ConvertToDeezerRequestDto"
      responses:
        "200":
          description: ""
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ConvertToDeezerResponseDto"
      summary: Convert an array of tracks to Deezer track IDs
      tags: *a5
  /api/music/artist/{artistName}/tracks:
    get:
      operationId: DeezerController_getArtistTracks
      parameters:
        - name: artistName
          required: true
          in: path
          description: Artist name (URL-encoded)
          schema:
            example: Radiohead
            type: string
        - name: limit
          required: false
          in: query
          description: "Maximum number of tracks to return (default: 100)"
          schema:
            type: number
      responses:
        "200":
          description: Array of detailed track objects sorted by popularity
        "400":
          description: Artist not found or invalid request
      summary: Get all tracks from an artist sorted by popularity
      tags: *a5
  /api/music/album/{albumName}/tracks:
    get:
      operationId: DeezerController_getAlbumTracks
      parameters:
        - name: albumName
          required: true
          in: path
          description: Album name (URL-encoded)
          schema:
            example: OK Computer
            type: string
        - name: artist
          required: true
          in: query
          description: Artist name
          schema:
            type: string
      responses:
        "200":
          description: Array of detailed track objects in track order
        "400":
          description: Album not found or invalid request
      summary: Get all tracks from an album in track order
      tags: *a5
  /api/track/preview:
    post:
      description: Accepts a track ID (number), search query (string), or track
        object. Returns a 1200x600px PNG image with album cover and track
        details in darkfloor theme.
      operationId: PreviewController_generatePreview
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PreviewRequestDto"
      responses:
        "200":
          description: PNG image buffer
          content:
            image/png:
              schema:
                type: string
                format: binary
        "400":
          description: Error generating preview - returns JSON error instead of image
      summary: Generate a social media preview image for a track
      tags: &a6
        - Preview Images
  /api/track/{id}/preview:
    get:
      operationId: PreviewController_generatePreviewFromId
      parameters:
        - name: id
          required: true
          in: path
          description: Track ID or Deezer track URL/URI
          schema:
            type: string
      responses:
        "200":
          description: PNG image buffer
          content:
            image/png:
              schema:
                type: string
                format: binary
      summary: Generate preview image from track ID (GET endpoint)
      tags: *a6
  /api/preview/test:
    get:
      description: Diagnostic endpoint to verify canvas library is working. Returns a
        simple colored test image.
      operationId: PreviewController_testCanvas
      parameters: []
      responses:
        "200":
          description: PNG test image
          content:
            image/png:
              schema:
                type: string
                format: binary
      summary: Test canvas library - generates a simple test image
      tags: *a6
  /api/preview/default:
    get:
      description: Returns a 1200x600px PNG image with the default darkfloor.org
        branding and a darker social-preview treatment for OG/meta usage.
      operationId: PreviewController_generateDefaultPreview
      parameters: []
      responses:
        "200":
          description: PNG image buffer
          content:
            image/png:
              schema:
                type: string
                format: binary
      summary: Generate default darkfloor.org preview image
      tags: *a6
  /api/preview:
    get:
      description: >-
        GET endpoint that accepts a query parameter for easier OG generation.
        Extracts the search query from ?q= parameter and generates a track
        preview image. Falls back to default image if query is missing or track
        not found.


        **Important:** The query parameter must be properly URL-encoded. Use
        `encodeURIComponent()` on the client side. Examples:

        - ✅ Works: `?q=isobel%20bj%C3%B6rk` (properly encoded)

        - ✅ Works: Use `--data-urlencode` with curl

        - ❌ Fails: `?q=isobel+björk` (unencoded special characters are rejected
        by NestJS before reaching this handler)
      operationId: PreviewController_generatePreviewFromQuery
      parameters:
        - name: q
          required: false
          in: query
          description: Search query (e.g., "artist song")
          allowEmptyValue: true
          schema:
            type: string
      responses:
        "200":
          description: PNG image buffer
          content:
            image/png:
              schema:
                type: string
                format: binary
      summary: Generate preview image from query parameter (for OG/meta tags)
      tags: *a6
  /music/stream:
    get:
      operationId: MusicStreamingController_streamMusic
      parameters:
        - name: key
          required: true
          in: query
          description: API key (UNIVERSAL_KEY)
          schema:
            type: string
        - name: id
          required: false
          in: query
          description: Deezer track ID
          schema:
            type: string
        - name: q
          required: false
          in: query
          description: Search query if ID is not provided
          schema:
            type: string
        - name: offset
          required: false
          in: query
          description: Search offset (0-999)
          schema:
            type: number
        - name: prefetch_ids
          required: false
          in: query
          description: Optional comma-separated Deezer track IDs to prefetch in the
            background and keep on disk.
          schema:
            example:
              - "3135556"
              - "1109731"
            type: array
            items:
              type: string
        - name: kbps
          required: false
          in: query
          description: Bitrate in kbps (1-320)
          schema:
            type: number
        - name: link
          required: false
          in: query
          description: Return a Deezer link instead of streaming
          schema:
            type: boolean
        - name: file
          required: false
          in: query
          description: Return as attachment download
          schema:
            type: boolean
      responses:
        "200":
          description: Stream begins or link provided.
        "400":
          description: Invalid request parameters.
        "401":
          description: Invalid or missing API key.
        "404":
          description: No results found.
        "500":
          description: Server error during streaming or download.
      summary: Stream music
      tags: &a7
        - music
  /music/stream/capabilities:
    get:
      operationId: MusicStreamingController_getStreamCapabilities
      parameters: []
      responses:
        "200":
          description: Streaming capabilities payload
          content:
            application/json:
              schema:
                type: object
                properties:
                  requiresApiKey:
                    type: boolean
                    example: true
                  supportsRange:
                    type: boolean
                    example: true
                  lossyKbps:
                    type: array
                    items:
                      type: integer
                      enum:
                        - 128
                        - 192
                        - 256
                        - 320
                    example:
                      - 128
                      - 192
                      - 256
                      - 320
                  losslessFormats:
                    type: array
                    items:
                      type: string
                      enum:
                        - flac
                    example:
                      - flac
                  defaultGuestKbps:
                    type: integer
                    example: 128
                  defaultAuthenticatedKbps:
                    type: integer
                    example: 256
      summary: Get streaming capabilities and supported parameters
      tags: *a7
  /music/stream/direct:
    get:
      description: Streams music directly from Deezer without filesystem operations.
        Ideal for Vercel and other serverless platforms. Supports HTTP range
        requests for seeking.
      operationId: MusicStreamingController_streamMusicDirect
      parameters:
        - name: key
          required: true
          in: query
          description: API key (UNIVERSAL_KEY)
          schema:
            type: string
        - name: id
          required: false
          in: query
          description: Deezer track ID
          schema:
            type: string
        - name: q
          required: false
          in: query
          description: Search query if ID is not provided
          schema:
            type: string
        - name: offset
          required: false
          in: query
          description: Search offset (0-999)
          schema:
            type: number
        - name: prefetch_ids
          required: false
          in: query
          description: Optional comma-separated Deezer track IDs to prefetch in the
            background and keep on disk.
          schema:
            example:
              - "3135556"
              - "1109731"
            type: array
            items:
              type: string
        - name: kbps
          required: false
          in: query
          description: "Lossy bitrate only. Supported values: 128, 192, 256, 320. Ignored
            when format=flac."
          schema:
            enum:
              - 128
              - 192
              - 256
              - 320
            type: number
        - name: format
          required: false
          in: query
          description: "Lossless format. Supported value: flac. If present, this is
            authoritative and kbps is ignored."
          schema:
            enum:
              - flac
            type: string
      responses:
        "200":
          description: Audio stream begins
          content:
            audio/mpeg:
              schema:
                type: string
                format: binary
            audio/flac:
              schema:
                type: string
                format: binary
        "400":
          description: Invalid request parameters
        "401":
          description: Unauthorized - invalid API key
        "500":
          description: Server error during streaming
        "503":
          description: Requested stream quality or format is temporarily unavailable
      summary: Stream music directly from source (serverless-friendly)
      tags: *a7
  /music/health:
    get:
      operationId: MusicStreamingController_healthCheck
      parameters: []
      responses:
        "200":
          description: Service is healthy
      summary: Health check endpoint
      tags: *a7
  /music/search:
    get:
      operationId: MusicStreamingController_searchMusic
      parameters:
        - name: q
          required: true
          in: query
          schema:
            type: string
        - name: offset
          required: false
          in: query
          description: "Result offset for pagination (default: 0)"
          schema:
            type: number
      responses:
        "200":
          description: Search results from Deezer.
        "500":
          description: Error during the search operation.
      summary: Search music on Deezer
      tags: *a7
  /music/cleanup:
    get:
      operationId: MusicStreamingController_cleanupDownloadFolder
      parameters: []
      responses:
        "200":
          description: Cleanup successful.
        "500":
          description: Error during the cleanup operation.
      summary: Clean up download folder
      tags: *a7
  /music/tracks/batch:
    get:
      operationId: MusicStreamingController_getBatchTrackMetadata
      parameters:
        - name: ids
          required: true
          in: query
          description: Comma-separated Deezer track IDs
          schema:
            type: string
      responses:
        "200":
          description: Array of track metadata
        "400":
          description: Invalid track IDs
      summary: Get metadata for multiple tracks
      tags: *a7
  /music/tracks/{id}/metadata:
    get:
      operationId: MusicStreamingController_getTrackMetadata
      parameters:
        - name: id
          required: true
          in: path
          description: Deezer track ID
          schema:
            example: "3135556"
            type: string
      responses:
        "200":
          description: Track metadata
        "404":
          description: Track not found
      summary: Get metadata for a single Deezer track
      tags: *a7
  /music/search/advanced:
    get:
      operationId: MusicStreamingController_advancedSearch
      parameters:
        - name: q
          required: true
          in: query
          description: Search query
          schema:
            type: string
        - name: artist
          required: false
          in: query
          description: Filter by artist
          schema:
            type: string
        - name: album
          required: false
          in: query
          description: Filter by album
          schema:
            type: string
        - name: durationMin
          required: false
          in: query
          description: Minimum duration in seconds
          schema:
            type: number
        - name: durationMax
          required: false
          in: query
          description: Maximum duration in seconds
          schema:
            type: number
        - name: offset
          required: false
          in: query
          description: Pagination offset
          schema:
            type: number
        - name: limit
          required: false
          in: query
          description: Results limit
          schema:
            type: number
      responses:
        "200":
          description: Filtered search results
      summary: Advanced search with filters
      tags: *a7
  /music/stream-static:
    get:
      operationId: MusicStreamingController_streamStaticMusic
      parameters:
        - name: id
          required: true
          in: query
          schema:
            type: number
        - name: range
          required: false
          in: query
          description: Percentage range of the song to stream, e.g., "0-20" or "20-40".
          schema:
            type: string
      responses:
        "200":
          description: Streaming of the music file started.
        "400":
          description: Invalid ID or ID out of range.
        "500":
          description: Error during streaming.
      summary: Stream static music file
      tags: *a7
  /music/artist/{artistName}:
    get:
      operationId: MusicStreamingController_getArtistSongs
      parameters:
        - name: artistName
          required: true
          in: path
          description: Artist name (URL-encoded)
          schema:
            example: Radiohead
            type: string
        - name: limit
          required: false
          in: query
          description: "Maximum number of tracks to return (default: 100)"
          schema:
            type: number
      responses:
        "200":
          description: Array of detailed track objects sorted by popularity (rank)
        "400":
          description: Artist not found or invalid request
      summary: Get all songs from a particular artist sorted by popularity
      tags: *a7
  /music/album/{albumName}:
    get:
      operationId: MusicStreamingController_getAlbumSongs
      parameters:
        - name: albumName
          required: true
          in: path
          description: Album name (URL-encoded)
          schema:
            example: OK Computer
            type: string
        - name: artist
          required: true
          in: query
          description: Artist name
          schema:
            type: string
      responses:
        "200":
          description: Array of detailed track objects in track order (by track_position)
        "400":
          description: Album not found or invalid request
      summary: Get all songs from an album in track order
      tags: *a7
  /music/favorites/{trackId}:
    post:
      operationId: FavoritesController_addFavorite
      parameters:
        - name: trackId
          required: true
          in: path
          description: Deezer track ID
          schema:
            type: string
      responses:
        "201":
          description: Track added to favorites
        "401":
          description: Unauthorized
        "404":
          description: Track not found
        "409":
          description: Track already in favorites
      security: &a8
        - bearer: []
      summary: Add a track to favorites
      tags: &a9
        - favorites
    delete:
      operationId: FavoritesController_removeFavorite
      parameters:
        - name: trackId
          required: true
          in: path
          description: Deezer track ID
          schema:
            type: string
      responses:
        "204":
          description: Track removed from favorites
        "401":
          description: Unauthorized
        "404":
          description: Favorite not found
      security: *a8
      summary: Remove a track from favorites
      tags: *a9
  /music/favorites:
    get:
      operationId: FavoritesController_getFavorites
      parameters:
        - name: limit
          required: false
          in: query
          description: "Limit results (default: 50)"
          schema:
            type: number
        - name: offset
          required: false
          in: query
          description: "Offset for pagination (default: 0)"
          schema:
            type: number
      responses:
        "200":
          description: List of favorite tracks
        "401":
          description: Unauthorized
      security: *a8
      summary: Get all favorite tracks
      tags: *a9
  /music/favorites/check/{trackId}:
    get:
      operationId: FavoritesController_checkFavorite
      parameters:
        - name: trackId
          required: true
          in: path
          description: Deezer track ID
          schema:
            type: string
      responses:
        "200":
          description: "Returns { isFavorite: boolean }"
        "401":
          description: Unauthorized
      security: *a8
      summary: Check if a track is in favorites
      tags: *a9
  /music/favorites/count:
    get:
      operationId: FavoritesController_getFavoriteCount
      parameters: []
      responses:
        "200":
          description: "Returns { count: number }"
        "401":
          description: Unauthorized
      security: *a8
      summary: Get total count of favorite tracks
      tags: *a9
  /music/favorites/batch-check:
    post:
      operationId: FavoritesController_batchCheckFavorites
      parameters:
        - name: trackIds
          required: true
          in: query
          schema:
            type: string
      responses:
        "200":
          description: Returns object with track IDs as keys and boolean values
        "401":
          description: Unauthorized
      security: *a8
      summary: Batch check if tracks are favorited
      tags: *a9
  /music/history:
    get:
      operationId: ListeningHistoryController_getHistory
      parameters:
        - name: limit
          required: false
          in: query
          description: "Limit results (default: 50)"
          schema:
            type: number
        - name: offset
          required: false
          in: query
          description: "Offset for pagination (default: 0)"
          schema:
            type: number
      responses:
        "200":
          description: Listening history
        "401":
          description: Unauthorized
      security: &a10
        - bearer: []
      summary: Get listening history
      tags: &a11
        - listening-history
    delete:
      operationId: ListeningHistoryController_clearHistory
      parameters: []
      responses:
        "204":
          description: Listening history cleared
        "401":
          description: Unauthorized
      security: *a10
      summary: Clear listening history
      tags: *a11
  /music/history/recent:
    get:
      operationId: ListeningHistoryController_getRecentlyPlayed
      parameters:
        - name: limit
          required: false
          in: query
          description: "Limit results (default: 20)"
          schema:
            type: number
      responses:
        "200":
          description: Recently played tracks
        "401":
          description: Unauthorized
      security: *a10
      summary: Get recently played tracks (unique)
      tags: *a11
  /music/history/stats:
    get:
      operationId: ListeningHistoryController_getStats
      parameters:
        - name: days
          required: false
          in: query
          description: "Number of days to include in stats (default: 30)"
          schema:
            type: number
      responses:
        "200":
          description: Listening statistics
        "401":
          description: Unauthorized
      security: *a10
      summary: Get listening statistics
      tags: *a11
  /music/playlists:
    post:
      operationId: PlaylistController_createPlaylist
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreatePlaylistDto"
      responses:
        "201":
          description: Playlist created successfully
        "401":
          description: Unauthorized
      security: &a12
        - bearer: []
      summary: Create a new playlist
      tags: &a13
        - playlists
    get:
      operationId: PlaylistController_getUserPlaylists
      parameters: []
      responses:
        "200":
          description: List of playlists
        "401":
          description: Unauthorized
      security: *a12
      summary: Get all playlists for the authenticated user
      tags: *a13
  /music/playlists/import/spotify:
    post:
      operationId: PlaylistController_importSpotifyPlaylist
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ImportSpotifyPlaylistDto"
      responses:
        "201":
          description: Playlist imported successfully
        "400":
          description: Invalid playlist ID or import limit exceeded
        "401":
          description: Unauthorized
        "403":
          description: Spotify playlist is private or unavailable
        "404":
          description: Spotify playlist not found
        "412":
          description: Spotify app profile is incomplete for the current user
        "429":
          description: Spotify or Deezer rate limited
        "502":
          description: Upstream Spotify or Deezer fetch/conversion failure
      security: *a12
      summary: Import a public Spotify playlist into a native Starchild playlist
      tags: *a13
  /music/playlists/{playlistId}:
    get:
      operationId: PlaylistController_getPlaylist
      parameters:
        - name: playlistId
          required: true
          in: path
          description: Playlist ID
          schema:
            type: string
      responses:
        "200":
          description: Playlist details
        "401":
          description: Unauthorized
        "403":
          description: Forbidden - playlist is private
        "404":
          description: Playlist not found
      security: *a12
      summary: Get a specific playlist by ID
      tags: *a13
    put:
      operationId: PlaylistController_updatePlaylist
      parameters:
        - name: playlistId
          required: true
          in: path
          description: Playlist ID
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpdatePlaylistDto"
      responses:
        "200":
          description: Playlist updated successfully
        "401":
          description: Unauthorized
        "403":
          description: Forbidden - not playlist owner
        "404":
          description: Playlist not found
      security: *a12
      summary: Update a playlist
      tags: *a13
    delete:
      operationId: PlaylistController_deletePlaylist
      parameters:
        - name: playlistId
          required: true
          in: path
          description: Playlist ID
          schema:
            type: string
      responses:
        "204":
          description: Playlist deleted successfully
        "401":
          description: Unauthorized
        "403":
          description: Forbidden - not playlist owner
        "404":
          description: Playlist not found
      security: *a12
      summary: Delete a playlist
      tags: *a13
  /music/playlists/{playlistId}/tracks:
    post:
      operationId: PlaylistController_addTrack
      parameters:
        - name: playlistId
          required: true
          in: path
          description: Playlist ID
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/AddToPlaylistDto"
      responses:
        "201":
          description: Track added to playlist
        "400":
          description: Track already in playlist
        "401":
          description: Unauthorized
        "403":
          description: Forbidden - not playlist owner
        "404":
          description: Playlist or track not found
      security: *a12
      summary: Add a track to a playlist
      tags: *a13
  /music/playlists/{playlistId}/tracks/{trackId}:
    delete:
      operationId: PlaylistController_removeTrack
      parameters:
        - name: playlistId
          required: true
          in: path
          description: Playlist ID
          schema:
            type: string
        - name: trackId
          required: true
          in: path
          description: Deezer track ID
          schema:
            type: string
      responses:
        "200":
          description: Track removed from playlist
        "401":
          description: Unauthorized
        "403":
          description: Forbidden - not playlist owner
        "404":
          description: Playlist or track not found
      security: *a12
      summary: Remove a track from a playlist
      tags: *a13
  /music/playlists/{playlistId}/tracks/reorder:
    put:
      operationId: PlaylistController_reorderTrack
      parameters:
        - name: playlistId
          required: true
          in: path
          description: Playlist ID
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ReorderPlaylistDto"
      responses:
        "200":
          description: Track reordered successfully
        "400":
          description: Invalid position
        "401":
          description: Unauthorized
        "403":
          description: Forbidden - not playlist owner
        "404":
          description: Playlist or track not found
      security: *a12
      summary: Reorder a track in a playlist
      tags: *a13
  /music/convert/playlist:
    post:
      description: Takes an array of song names and converts them to either Spotify or
        Deezer format. Returns full track data from the target platform for each
        song.
      operationId: PlaylistConversionController_convertPlaylist
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PlaylistConversionRequestDto"
      responses:
        "200":
          description: Conversion results with full track data from target platform
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PlaylistConversionResponseDto"
        "400":
          description: Invalid request
      summary: Convert playlist songs between Spotify and Deezer
      tags:
        - playlist-conversion
  /api/lastfm/track/info:
    get:
      operationId: LastfmController_getTrackInfo
      parameters:
        - name: artist
          required: true
          in: query
          description: Artist name
          schema:
            type: string
        - name: track
          required: true
          in: query
          description: Track name
          schema:
            type: string
        - name: mbid
          required: false
          in: query
          description: MusicBrainz ID
          schema:
            type: string
      responses:
        "200":
          description: Track information object
      summary: Get detailed information for a track
      tags: &a14
        - Last.fm
  /api/lastfm/artist/info:
    get:
      operationId: LastfmController_getArtistInfo
      parameters:
        - name: artist
          required: true
          in: query
          description: Artist name
          schema:
            type: string
        - name: mbid
          required: false
          in: query
          description: MusicBrainz ID
          schema:
            type: string
      responses:
        "200":
          description: Artist information object
      summary: Get detailed information for an artist
      tags: *a14
  /api/lastfm/track/search:
    get:
      operationId: LastfmController_searchTracks
      parameters:
        - name: query
          required: true
          in: query
          description: Search query
          schema:
            type: string
        - name: limit
          required: false
          in: query
          description: Number of results per page
          schema:
            type: number
        - name: page
          required: false
          in: query
          description: Page number
          schema:
            type: number
      responses:
        "200":
          description: Last.fm search result object
      summary: Search for tracks on Last.fm
      tags: *a14
  /api/lastfm/artist/search:
    get:
      operationId: LastfmController_searchArtists
      parameters:
        - name: query
          required: true
          in: query
          description: Search query
          schema:
            type: string
        - name: limit
          required: false
          in: query
          description: Number of results per page
          schema:
            type: number
        - name: page
          required: false
          in: query
          description: Page number
          schema:
            type: number
      responses:
        "200":
          description: Last.fm search result object
      summary: Search for artists on Last.fm
      tags: *a14
  /api/lastfm/artist/top-tracks:
    get:
      operationId: LastfmController_getArtistTopTracks
      parameters:
        - name: artist
          required: true
          in: query
          description: Artist name
          schema:
            type: string
        - name: limit
          required: false
          in: query
          description: Number of tracks to return
          schema:
            type: number
        - name: page
          required: false
          in: query
          description: Page number
          schema:
            type: number
      responses:
        "200":
          description: Top tracks response from Last.fm
      summary: Get top tracks for an artist
      tags: *a14
  /api/lastfm/track/similar:
    get:
      operationId: LastfmController_getSimilarTracks
      parameters:
        - name: artist
          required: true
          in: query
          description: Artist name
          schema:
            type: string
        - name: track
          required: true
          in: query
          description: Track name
          schema:
            type: string
        - name: limit
          required: false
          in: query
          description: Number of similar tracks to return
          schema:
            type: number
      responses:
        "200":
          description: Similar tracks response from Last.fm
      summary: Get similar tracks for a given track
      tags: *a14
  /api/lastfm/recommendations/spice-up:
    post:
      operationId: LastfmController_spiceUpPlaylist
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/LastfmSpiceUpRequestDto"
      responses:
        "200":
          description: ""
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/LastfmSpiceUpResponseDto"
      summary: Generate recommendations using Last.fm similarity data
      tags: *a14
  /api/lastfm/recommendations/spice-up-with-deezer:
    post:
      operationId: LastfmController_spiceUpPlaylistWithDeezer
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/LastfmSpiceUpWithDeezerRequestDto"
      responses:
        "200":
          description: ""
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/LastfmSpiceUpWithDeezerResponseDto"
      summary: Generate Last.fm recommendations and convert them to Deezer track IDs
      tags: *a14
  /api/health:
    get:
      description: Returns detailed information about the server status, including
        database connectivity, external services configuration, memory usage,
        and system information.
      operationId: HealthController_getHealth
      parameters: []
      responses:
        "200":
          description: Health check information
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    enum:
                      - ok
                      - degraded
                      - unhealthy
                  timestamp:
                    type: string
                    format: date-time
                  version:
                    type: string
                  environment:
                    type: object
                  uptime:
                    type: object
                  memory:
                    type: object
                  services:
                    type: object
                  config:
                    type: object
      summary: Comprehensive health check endpoint
      tags:
        - Health
  /spotify/search:
    get:
      operationId: LegacySpotifyController_search
      parameters:
        - name: q
          required: true
          in: query
          description: Search query
          schema:
            type: string
        - name: type
          required: true
          in: query
          description: "Search type: track, playlist, album, artist"
          schema:
            type: string
        - name: limit
          required: false
          in: query
          description: Results limit (max 50)
          schema:
            type: number
      responses:
        "200":
          description: Search results
      security:
        - bearer: []
      summary: Legacy Spotify search (V1 compatible route)
      tags: &a15
        - Legacy Spotify
  /spotify/auth/url:
    get:
      operationId: LegacySpotifyController_getAuthUrl
      parameters:
        - name: state
          required: false
          in: query
          description: CSRF state
          schema:
            type: string
      responses:
        "200":
          description: ""
      security:
        - bearer: []
      summary: Get Spotify OAuth authorization URL
      tags: *a15
  /spotify/auth/callback:
    post:
      operationId: LegacySpotifyController_handleCallback
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SpotifyAuthCallbackDto"
      responses:
        "201":
          description: ""
      security:
        - bearer: []
      summary: Handle Spotify OAuth callback
      tags: *a15
  /spotify/auth/disconnect:
    delete:
      operationId: LegacySpotifyController_disconnect
      parameters: []
      responses:
        "200":
          description: ""
      security:
        - bearer: []
      summary: Disconnect Spotify account
      tags: *a15
  /spotify/auth/status:
    get:
      operationId: LegacySpotifyController_getConnectionStatus
      parameters: []
      responses:
        "200":
          description: ""
      security:
        - bearer: []
      summary: Check Spotify connection status
      tags: *a15
  /spotify/playlists:
    get:
      operationId: LegacySpotifyController_getUserPlaylists
      parameters:
        - name: limit
          required: false
          in: query
          description: Results limit (max 50)
          schema:
            type: number
      responses:
        "200":
          description: ""
      security:
        - bearer: []
      summary: Get user playlists from Spotify
      tags: *a15
  /spotify/playlists/{playlistId}:
    get:
      operationId: LegacySpotifyController_getPlaylist
      parameters:
        - name: playlistId
          required: true
          in: path
          description: Spotify playlist ID
          schema:
            type: string
      responses:
        "200":
          description: ""
      security:
        - bearer: []
      summary: Get Spotify playlist details
      tags: *a15
  /spotify/playlists/import:
    post:
      operationId: LegacySpotifyController_importPlaylist
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ImportSpotifyPlaylistRequestDto"
      responses:
        "200":
          description: ""
      security:
        - bearer: []
      summary: Import Spotify playlist payload and match to Deezer without Spotify
        OAuth session
      tags: *a15
  /spotify/tracks/{trackId}:
    get:
      operationId: LegacySpotifyController_getTrack
      parameters:
        - name: trackId
          required: true
          in: path
          description: Spotify track ID
          schema:
            type: string
      responses:
        "200":
          description: ""
      security:
        - bearer: []
      summary: Get Spotify track details
      tags: *a15
  /spotify/tracks/analyze:
    post:
      operationId: LegacySpotifyController_analyzeTrack
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/AnalyzeTrackDto"
      responses:
        "201":
          description: ""
      security:
        - bearer: []
      summary: Analyze track for BPM, mood, and characteristics
      tags: *a15
  /spotify/tracks/analyze-batch:
    post:
      operationId: LegacySpotifyController_analyzeBatch
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/BatchAnalyzeTracksDto"
      responses:
        "201":
          description: ""
      security:
        - bearer: []
      summary: Analyze multiple tracks in batch
      tags: *a15
  /spotify/tracks/{trackId}/audio-features:
    get:
      operationId: LegacySpotifyController_getAudioFeatures
      parameters:
        - name: trackId
          required: true
          in: path
          description: Spotify track ID
          schema:
            type: string
      responses:
        "200":
          description: ""
      security:
        - bearer: []
      summary: Get audio features for a track
      tags: *a15
  /spotify/tracks/{trackId}/audio-analysis:
    get:
      operationId: LegacySpotifyController_getAudioAnalysis
      parameters:
        - name: trackId
          required: true
          in: path
          description: Spotify track ID
          schema:
            type: string
      responses:
        "200":
          description: ""
      security:
        - bearer: []
      summary: Get detailed audio analysis for a track
      tags: *a15
  /version:
    get:
      operationId: LegacyMetaController_getVersion
      parameters: []
      responses:
        "200":
          description: ""
      summary: Legacy version endpoint (V1 compatible route)
      tags: &a16
        - Legacy Meta
  /api-yaml:
    get:
      operationId: LegacyMetaController_getApiYaml
      parameters: []
      responses:
        "200":
          description: ""
      summary: Legacy OpenAPI YAML endpoint (V1 compatible route)
      tags: *a16
  /public/{filename}:
    get:
      operationId: LegacyMetaController_servePublicFile
      parameters:
        - name: filename
          required: true
          in: path
          schema:
            type: string
      responses:
        "200":
          description: ""
      summary: Legacy public file endpoint (V1 compatible route)
      tags: *a16
  /users/profile:
    get:
      operationId: UserController_getProfile
      parameters: []
      responses:
        "200":
          description: Return user profile
      security: &a17
        - bearer: []
      summary: Get user profile
      tags: &a18
        - users
    put:
      operationId: UserController_updateProfile
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UpdateUserDto"
      responses:
        "200":
          description: Return updated user profile
      security: *a17
      summary: Update user profile
      tags: *a18
  /hexmusic/search/tracks:
    get:
      description: Search Spotify for tracks by name, artist, or any search term.
        Returns up to 10 tracks with details including ID, name, artists, album,
        and cover art. Results are cached for 24 hours.
      operationId: HexMusicController_searchTracks
      parameters:
        - name: query
          required: true
          in: query
          description: Search query string (track name, artist, or keywords)
          schema:
            example: Bohemian Rhapsody Queen
            type: string
      responses:
        "200":
          description: Successfully retrieved track search results
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/TrackResponseDto"
        "500":
          description: Failed to search tracks (Spotify API error)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponseDto"
      summary: Search for tracks
      tags: &a19
        - Music & Recommendations
  /hexmusic/search/playlists:
    get:
      description: Search Spotify for playlists by name or keywords. Returns up to 20
        playlists with metadata including ID, name, description, owner, and
        track count. Results are cached for 24 hours.
      operationId: HexMusicController_searchPlaylists
      parameters:
        - name: query
          required: true
          in: query
          description: Search query string (playlist name or keywords)
          schema:
            example: Rock Classics
            type: string
      responses:
        "200":
          description: Successfully retrieved playlist search results
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/PlaylistSearchResultDto"
        "500":
          description: Failed to search playlists (Spotify API error)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponseDto"
      summary: Search for playlists
      tags: *a19
  /hexmusic/playlist/{playlistId}:
    get:
      description: Retrieve detailed information about a specific Spotify playlist
        including all tracks, metadata, and cover art.
      operationId: HexMusicController_getSpotifyPlaylist
      parameters:
        - name: playlistId
          required: true
          in: path
          description: Spotify playlist ID
          schema:
            example: 37i9dQZF1DWXRqgorJj26U
            type: string
      responses:
        "200":
          description: Successfully retrieved playlist details
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PlaylistDetailResponseDto"
        "500":
          description: Failed to fetch Spotify playlist
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponseDto"
      summary: Get playlist details
      tags: *a19
  /hexmusic/recommendations/playlist/{playlistId}:
    get:
      description: Generate song recommendations based on the first 5 tracks from a
        Spotify playlist. Returns 20 recommended tracks similar to the playlist
        content.
      operationId: HexMusicController_getRecommendationsFromPlaylist
      parameters:
        - name: playlistId
          required: true
          in: path
          description: Spotify playlist ID to base recommendations on
          schema:
            example: 37i9dQZF1DWXRqgorJj26U
            type: string
      responses:
        "200":
          description: Successfully generated recommendations from playlist
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    id:
                      type: string
                    name:
                      type: string
                    artists:
                      type: string
                    album:
                      type: string
                    previewUrl:
                      type: string
                      nullable: true
                    imageUrl:
                      type: string
                      nullable: true
        "500":
          description: Failed to generate recommendations
      summary: Get recommendations from a playlist
      tags: *a19
  /hexmusic/playlist-recommendations:
    get:
      description: Search for playlists by query, select the first result, and
        generate recommendations based on it. Results are saved to the database.
      operationId: HexMusicController_getPlaylistRecommendations
      parameters:
        - name: query
          required: true
          in: query
          description: Playlist search query
          schema:
            example: Chill Vibes
            type: string
      responses:
        "200":
          description: Successfully searched playlist and generated recommendations
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                  query:
                    type: string
                  selectedPlaylist:
                    type: object
                    properties:
                      id:
                        type: string
                      name:
                        type: string
                      description:
                        type: string
                      owner:
                        type: string
                      tracksTotal:
                        type: number
                      imageUrl:
                        type: string
                        nullable: true
                  recommendations:
                    type: array
                    items:
                      type: object
        "404":
          description: No playlists found for query
        "500":
          description: Failed to process request
      summary: Search playlists and get recommendations
      tags: *a19
  /hexmusic/recommendations:
    post:
      description: "Generate personalized song recommendations based on 1-5 seed
        tracks. Supports flexible input: provide track IDs, track names (with
        optional artist), or a mix of both. Configurable recommendation limit
        (1-100). Results are cached for 24 hours. This is the primary
        recommendation endpoint with the most flexibility."
      operationId: HexMusicController_getRecommendations
      parameters: []
      requestBody:
        required: true
        description: Recommendation request with flexible track input
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/RecommendationRequestDto"
            examples:
              Track IDs:
                value:
                  tracks:
                    - id: 3n3Ppam7vgaVa1iaRUc9Lp
                    - id: 5ChkMS8OtdzJeqyybCc9R5
                  limit: 20
                summary: Using Spotify track IDs
              Track Names:
                value:
                  tracks:
                    - name: Bohemian Rhapsody
                      artist: Queen
                    - name: Stairway to Heaven
                      artist: Led Zeppelin
                  limit: 30
                summary: Using track names with artists
              Mixed Input:
                value:
                  tracks:
                    - id: 3n3Ppam7vgaVa1iaRUc9Lp
                    - name: Hotel California
                    - name: Wonderwall
                      artist: Oasis
                  limit: 15
                summary: Mix of IDs and names
      responses:
        "200":
          description: Successfully generated recommendations
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/TrackWithPreviewResponseDto"
        "400":
          description: Could not resolve any of the provided tracks
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponseDto"
        "500":
          description: Failed to fetch recommendations
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponseDto"
      summary: Get song recommendations (flexible input)
      tags: *a19
  /hexmusic/recommendations/legacy:
    post:
      description: Legacy endpoint for backward compatibility. Accepts only track IDs
        and returns exactly 20 recommendations. Use the /recommendations
        endpoint instead for more flexibility.
      operationId: HexMusicController_getRecommendationsLegacy
      parameters: []
      requestBody:
        required: true
        description: Legacy recommendation request with track IDs only
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/LegacyRecommendationRequestDto"
            examples:
              default:
                value:
                  trackIds:
                    - 3n3Ppam7vgaVa1iaRUc9Lp
                    - 5ChkMS8OtdzJeqyybCc9R5
                    - 0c6xIDDpzE81m2q797ordA
      responses:
        "200":
          description: Successfully generated 20 recommendations
        "500":
          description: Failed to fetch recommendations
      summary: Get recommendations (legacy endpoint)
      tags: *a19
  /hexmusic/recommendations/generate/{playlistSearchId}:
    post:
      description: Generate recommendations based on a previously saved playlist
        search result. Uses the first playlist from the search results.
        Recommendations are saved to database.
      operationId: HexMusicController_generateAndSaveRecommendations
      parameters:
        - name: playlistSearchId
          required: true
          in: path
          description: ID of a previously saved playlist search
          schema:
            example: clx1234567890abcdef
            type: string
      responses:
        "201":
          description: Successfully generated and saved recommendations
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                  playlistSearchId:
                    type: string
                  recommendations:
                    type: array
                    items:
                      type: object
                  createdAt:
                    type: string
                    format: date-time
                  updatedAt:
                    type: string
                    format: date-time
        "404":
          description: Playlist search not found
        "500":
          description: Failed to generate recommendations
      summary: Generate and save recommendations from playlist search
      tags: *a19
  /hexmusic/songs:
    get:
      description: Search for tracks on Spotify with a customizable limit. Similar to
        /search/tracks but with configurable result count. Returns track details
        including preview URLs and cover art.
      operationId: HexMusicController_fetchSongs
      parameters:
        - name: query
          required: true
          in: query
          description: Search query for tracks
          schema:
            example: The Beatles
            type: string
        - name: limit
          required: false
          in: query
          description: Maximum number of results to return
          schema:
            example: 10
            type: number
      responses:
        "200":
          description: Successfully fetched songs
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    id:
                      type: string
                    name:
                      type: string
                    artists:
                      type: array
                      items:
                        type: string
                      example:
                        - The Beatles
                    album:
                      type: string
                    previewUrl:
                      type: string
                      nullable: true
                    imageUrl:
                      type: string
                      nullable: true
        "500":
          description: Failed to fetch songs
      summary: Fetch songs (search tracks)
      tags: *a19
  /hexmusic/recommendations/bulk:
    post:
      description: Submit an array of songs and receive recommendations. Accepts any
        number of songs (uses up to 5 as seeds due to Spotify API limits). Each
        song can be specified by ID, name, or name+artist. The "n" parameter
        controls how many recommendations to return (defaults to the number of
        input songs). Perfect for getting recommendations based on a playlist or
        collection of songs.
      operationId: HexMusicController_getBulkRecommendations
      parameters: []
      requestBody:
        required: true
        description: Bulk songs recommendation request
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/BulkSongsRecommendationDto"
            examples:
              With IDs and Names:
                value:
                  giveSongs:
                    - id: 3n3Ppam7vgaVa1iaRUc9Lp
                      name: Mr. Brightside
                    - name: Somebody Told Me
                      artist: The Killers
                    - name: When You Were Young
                      artist: The Killers
                    - id: 0eGsygTp906u18L0Oimnem
                  n: 10
                summary: Mixed IDs and names with custom count
              Only Names:
                value:
                  giveSongs:
                    - name: Blinding Lights
                      artist: The Weeknd
                    - name: Levitating
                      artist: Dua Lipa
                    - name: Save Your Tears
                      artist: The Weeknd
                    - name: Don't Start Now
                      artist: Dua Lipa
                    - name: Peaches
                      artist: Justin Bieber
                summary: Using only track names (returns 5 recommendations by default)
              Large Playlist:
                value:
                  giveSongs:
                    - name: Bohemian Rhapsody
                      artist: Queen
                    - name: Stairway to Heaven
                      artist: Led Zeppelin
                    - name: Hotel California
                      artist: Eagles
                    - name: Imagine
                      artist: John Lennon
                    - name: Sweet Child O Mine
                      artist: Guns N' Roses
                    - name: November Rain
                      artist: Guns N' Roses
                    - name: Dream On
                      artist: Aerosmith
                  n: 20
                summary: 7 classic rock songs, requesting 20 recommendations
      responses:
        "200":
          description: Successfully generated bulk recommendations
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/TrackWithPreviewResponseDto"
        "400":
          description: Could not resolve any of the provided songs
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponseDto"
        "500":
          description: Failed to generate bulk recommendations
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponseDto"
      summary: Get recommendations from bulk songs
      tags: *a19
  /hexmusic/recommendations/deezer:
    post:
      description: Submit an array of track names and receive Deezer track
        recommendations with Deezer IDs. Track names can be simple titles or
        "Artist - Track" format for better accuracy. The "n" parameter controls
        how many recommendations to return (defaults to the number of input
        tracks). Perfect for getting Deezer-based recommendations that can be
        used with the Deezer API or player. Results are cached for 24 hours and
        stored in the database.
      operationId: HexMusicController_getDeezerRecommendations
      parameters: []
      requestBody:
        required: true
        description: Deezer recommendation request with track names and optional mode
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/DeezerRecommendationRequestDto"
            examples:
              Strict Mode - Same Artists:
                value:
                  trackNames:
                    - Queen - Bohemian Rhapsody
                    - Queen - We Will Rock You
                    - Led Zeppelin - Stairway to Heaven
                  n: 10
                  mode: 0
                summary: "Strict mode (0): Returns more tracks from the same artists"
              Balanced Mode - Related Artists:
                value:
                  trackNames:
                    - Bohemian Rhapsody
                    - Stairway to Heaven
                    - Hotel California
                    - Imagine
                  n: 15
                  mode: 1
                summary: "Balanced mode (1): Returns tracks from related artists in similar
                  genres"
              Diverse Mode - Genre Variety:
                value:
                  trackNames:
                    - The Weeknd - Blinding Lights
                    - Dua Lipa - Levitating
                    - Pink Floyd - Comfortably Numb
                  n: 20
                  mode: 2
                summary: "Diverse mode (2): Returns varied tracks with loose genre adherence"
              Default Mode (Balanced):
                value:
                  trackNames:
                    - Blinding Lights
                    - Levitating
                    - Save Your Tears
                  n: 10
                summary: No mode specified - defaults to Balanced (1)
      responses:
        "200":
          description: Successfully generated Deezer recommendations
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/DeezerTrackResponseDto"
        "400":
          description: Could not resolve any of the provided track names
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponseDto"
        "500":
          description: Failed to generate Deezer recommendations
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponseDto"
      summary: Get Deezer recommendations from track names
      tags: *a19
  /hexmusic/recommendations/json:
    post:
      description: Legacy endpoint that accepts a JSON string of song objects. Parses
        the JSON and generates recommendations from the song IDs. Use the
        /recommendations/bulk endpoint instead for better type safety.
      operationId: HexMusicController_getRecommendationsFromJson
      parameters: []
      requestBody:
        required: true
        description: JSON string containing array of song objects with IDs
        content:
          application/json:
            schema:
              type: object
              properties:
                songs:
                  type: string
                  example: '[{"id":"3n3Ppam7vgaVa1iaRUc9Lp","name":"Mr.
                    Brightside"},{"id":"5ChkMS8OtdzJeqyybCc9R5","name":"Somebody
                    Told Me"}]'
              required:
                - songs
      responses:
        "200":
          description: Successfully generated recommendations from JSON
        "400":
          description: Invalid JSON input or empty array
        "500":
          description: Failed to fetch recommendations
      summary: Get recommendations from JSON string (legacy)
      tags: *a19
info:
  title: Darkfloor.one API
  description: Aggregated music intelligence from Spotify, Last.fm, and Deezer
    with unified authentication, caching, and playlist workflows.
  version: 1.0.0
  contact: {}
tags: []
servers:
  - url: https://api.darkfloor.org
    description: Primary public URL (APP_URL)
components:
  securitySchemes:
    bearer:
      scheme: bearer
      bearerFormat: JWT
      type: http
      description: JWT Bearer token for protected endpoints
      in: header
  schemas:
    TrackArtistDto:
      type: object
      properties:
        name:
          type: string
          description: Artist name
        id:
          type: string
          description: Spotify artist ID
      required:
        - name
        - id
    TrackAlbumDto:
      type: object
      properties:
        name:
          type: string
          description: Album name
      required:
        - name
    TrackExternalUrlsDto:
      type: object
      properties:
        spotify:
          type: string
          description: Spotify URL for the track
      required:
        - spotify
    TrackDto:
      type: object
      properties:
        id:
          type: string
          description: Spotify track ID
        name:
          type: string
          description: Track title
        artists:
          description: List of track artists
          type: array
          items:
            $ref: "#/components/schemas/TrackArtistDto"
        album:
          description: Album information
          allOf:
            - $ref: "#/components/schemas/TrackAlbumDto"
        popularity:
          type: number
          description: Popularity score (0-100)
        preview_url:
          type: object
          description: 30 second preview MP3 URL
        external_urls:
          description: External URLs for the track
          allOf:
            - $ref: "#/components/schemas/TrackExternalUrlsDto"
        explicit:
          type: boolean
          description: Whether the track is explicit
        isrc:
          type: string
          description: ISRC code if available
      required:
        - id
        - name
        - artists
        - album
        - popularity
        - external_urls
    RecommendationSeedDto:
      type: object
      properties:
        id:
          type: string
          description: Seed identifier
        type:
          type: string
          description: Seed type (track, artist, genre)
        initialPoolSize:
          type: number
          description: Initial pool size used by Spotify
      required:
        - id
        - type
        - initialPoolSize
    RecommendationResponseDto:
      type: object
      properties:
        seeds:
          description: Seed details provided by Spotify
          type: array
          items:
            $ref: "#/components/schemas/RecommendationSeedDto"
        tracks:
          description: Recommended tracks
          type: array
          items:
            $ref: "#/components/schemas/TrackDto"
      required:
        - seeds
        - tracks
    RecommendationsFromSearchRequestDto:
      type: object
      properties:
        query:
          type: string
          description: Search query used to find a seed track
        limit:
          type: number
          description: Number of recommendations to return (1-100)
          default: 20
      required:
        - query
    SongInputDto:
      type: object
      properties:
        name:
          type: string
          description: Song title to use for seed search
        artist:
          type: string
          description: Artist name to use for seed search
        album:
          type: string
          description: Album name to use for seed search
    SpiceUpRequestDto:
      type: object
      properties:
        songs:
          minItems: 1
          description: Songs used to generate seed information
          type: array
          items:
            $ref: "#/components/schemas/SongInputDto"
        limit:
          type: number
          description: Number of recommendations to return (1-100)
          default: 20
        mode:
          type: string
          description: Diversity mode. strict -> most similar, balanced -> moderate
            variety, diverse -> maximum variety, wild -> experimental
            combinations
          enum: &a20
            - strict
            - balanced
            - diverse
            - wild
          default: balanced
        excludeTrackIds:
          description: Spotify track IDs to exclude from recommendations
          type: array
          items:
            type: string
        excludeDeezerIds:
          description: Deezer track IDs to exclude from recommendations
          type: array
          items:
            type: string
        excludeExplicit:
          type: boolean
          description: Exclude explicit tracks from recommendations
          default: false
        maxSeeds:
          type: number
          description: Maximum number of seeds to use from the queue (hard capped at 50)
          default: 30
          maximum: 50
        sampling:
          type: string
          description: Deterministic sampling strategy for large queues (ordered preserves
            input order)
          enum: &a21
            - evenly-spaced
            - ordered
          default: evenly-spaced
        seedStride:
          type: number
          description: Optional stride for deterministic sampling (used when
            sampling=evenly-spaced)
          minimum: 1
        queueMode:
          type: string
          description: Queue mode for server-side history blending (defaults to
            useQueueOnly)
          enum: &a22
            - useQueueOnly
            - blendHistory
            - includeHistory
          default: useQueueOnly
        historySongs:
          description: Optional server-provided history seeds (ignored when
            queueMode=useQueueOnly)
          type: array
          items:
            $ref: "#/components/schemas/SongInputDto"
      required:
        - songs
    SpiceUpTrackDto:
      type: object
      properties:
        id:
          type: string
          description: Spotify track ID
        name:
          type: string
          description: Track title
        artists:
          description: List of track artists
          type: array
          items:
            $ref: "#/components/schemas/TrackArtistDto"
        album:
          description: Album information
          allOf:
            - $ref: "#/components/schemas/TrackAlbumDto"
        popularity:
          type: number
          description: Popularity score (0-100)
        preview_url:
          type: object
          description: 30 second preview MP3 URL
        external_urls:
          description: External URLs for the track
          allOf:
            - $ref: "#/components/schemas/TrackExternalUrlsDto"
        explicit:
          type: boolean
          description: Whether the track is explicit
        isrc:
          type: string
          description: ISRC code if available
        deezerId:
          type: object
          description: Resolved Deezer track ID when available
        source:
          type: string
          description: Recommendation source platform
          enum:
            - spotify
            - lastfm
            - deezer
        reason:
          type: string
          description: Optional reason string for UI display
        score:
          type: number
          description: Optional score for UI display (0-1)
      required:
        - id
        - name
        - artists
        - album
        - popularity
        - external_urls
    SpiceUpSeedDto:
      type: object
      properties:
        id:
          type: string
          description: Seed identifier used by Spotify
        type:
          type: string
          description: Seed type (track, artist, genre)
        initialPoolSize:
          type: number
          description: Initial pool size for the seed
      required:
        - id
        - type
        - initialPoolSize
    SpiceUpSongResultDto:
      type: object
      properties:
        input:
          description: Original song input
          allOf:
            - $ref: "#/components/schemas/SongInputDto"
        track:
          description: Found track information
          allOf:
            - $ref: "#/components/schemas/TrackDto"
        confidence:
          type: number
          description: Search confidence score (0-1)
        searchMethod:
          type: string
          description: Search method used
        error:
          type: string
          description: Error message if search failed
      required:
        - input
        - confidence
        - searchMethod
    SeedQualityMetricsDto:
      type: object
      properties:
        overallScore:
          type: number
          description: Overall seed quality score (0-1)
        uniqueArtists:
          type: number
          description: Number of unique artists in seeds
        popularityRange:
          type: object
          description: Popularity range of seed tracks
        diversityScore:
          type: number
          description: Audio feature diversity score
        recommendations:
          description: Recommendations for improving seed quality
          type: array
          items:
            type: string
      required:
        - overallScore
        - uniqueArtists
        - popularityRange
        - diversityScore
    SpiceUpResponseDto:
      type: object
      properties:
        mode:
          type: string
          description: Diversity mode applied
        inputSongs:
          type: number
          description: Number of input songs provided
        foundSongs:
          type: number
          description: Number of songs successfully found
        tracks:
          description: Recommended tracks (consistent envelope)
          type: array
          items:
            $ref: "#/components/schemas/SpiceUpTrackDto"
        recommendations:
          description: "Deprecated: use tracks instead"
          type: array
          items:
            $ref: "#/components/schemas/SpiceUpTrackDto"
        seeds:
          description: Seed data returned by Spotify
          type: array
          items:
            $ref: "#/components/schemas/SpiceUpSeedDto"
        songResults:
          description: Detailed results for each input song
          type: array
          items:
            $ref: "#/components/schemas/SpiceUpSongResultDto"
        seedQuality:
          description: Seed quality analysis
          allOf:
            - $ref: "#/components/schemas/SeedQualityMetricsDto"
        warnings:
          description: Warning messages for partial failures
          type: array
          items:
            type: string
        requestId:
          type: string
          description: Request ID for traceability
      required:
        - mode
        - inputSongs
        - foundSongs
        - tracks
        - seeds
        - songResults
        - warnings
    UnifiedSpiceUpRequestDto:
      type: object
      properties:
        songs:
          minItems: 1
          description: Songs used to generate seed information
          type: array
          items:
            $ref: "#/components/schemas/SongInputDto"
        limit:
          type: number
          description: Number of recommendations to return (1-100)
          default: 20
        mode:
          type: string
          description: Diversity mode. strict -> most similar, balanced -> moderate
            variety, diverse -> maximum variety, wild -> experimental
            combinations
          enum: *a20
          default: balanced
        excludeTrackIds:
          description: Spotify track IDs to exclude from recommendations
          type: array
          items:
            type: string
        excludeDeezerIds:
          description: Deezer track IDs to exclude from recommendations
          type: array
          items:
            type: string
        excludeExplicit:
          type: boolean
          description: Exclude explicit tracks from recommendations
          default: false
        maxSeeds:
          type: number
          description: Maximum number of seeds to use from the queue (hard capped at 50)
          default: 30
          maximum: 50
        sampling:
          type: string
          description: Deterministic sampling strategy for large queues (ordered preserves
            input order)
          enum: *a21
          default: evenly-spaced
        seedStride:
          type: number
          description: Optional stride for deterministic sampling (used when
            sampling=evenly-spaced)
          minimum: 1
        queueMode:
          type: string
          description: Queue mode for server-side history blending (defaults to
            useQueueOnly)
          enum: *a22
          default: useQueueOnly
        historySongs:
          description: Optional server-provided history seeds (ignored when
            queueMode=useQueueOnly)
          type: array
          items:
            $ref: "#/components/schemas/SongInputDto"
        platforms:
          type: string
          description: Platforms to use for recommendations
          enum:
            - spotify
            - lastfm
            - deezer
            - auto
          default: auto
      required:
        - songs
    UnifiedSpiceUpResponseDto:
      type: object
      properties:
        mode:
          type: string
          description: Diversity mode applied
        inputSongs:
          type: number
          description: Number of input songs provided
        foundSongs:
          type: number
          description: Number of songs successfully found
        tracks:
          description: Recommended tracks (consistent envelope)
          type: array
          items:
            $ref: "#/components/schemas/SpiceUpTrackDto"
        recommendations:
          description: "Deprecated: use tracks instead"
          type: array
          items:
            $ref: "#/components/schemas/SpiceUpTrackDto"
        seeds:
          description: Seed data returned by Spotify
          type: array
          items:
            $ref: "#/components/schemas/SpiceUpSeedDto"
        songResults:
          description: Detailed results for each input song
          type: array
          items:
            $ref: "#/components/schemas/SpiceUpSongResultDto"
        seedQuality:
          description: Seed quality analysis
          allOf:
            - $ref: "#/components/schemas/SeedQualityMetricsDto"
        warnings:
          description: Warning messages for partial failures
          type: array
          items:
            type: string
        requestId:
          type: string
          description: Request ID for traceability
        platformsUsed:
          description: Platforms used for generating recommendations
          type: array
          items:
            type: string
        platformResults:
          type: object
          description: Platform-specific results
      required:
        - mode
        - inputSongs
        - foundSongs
        - tracks
        - seeds
        - songResults
        - warnings
        - platformsUsed
    ImportSpotifyPlaylistTrackPayloadDto:
      type: object
      properties:
        spotifyTrackId:
          type: string
          description: Spotify track ID
          example: 3n3Ppam7vgaVa1iaRUc9Lp
        name:
          type: string
          description: Track title
          example: Midnight City
        artist:
          type: string
          description: Primary artist name
          example: M83
        artists:
          description: Ordered list of Spotify artist names
          example:
            - Primary artist
            - Featured artist
          type: array
          items:
            type: string
        album:
          type: string
          description: Album title
          example: Hurry Up, We Are Dreaming
        albumName:
          type: string
          description: Album title alias used by frontend payloads
          example: Hurry Up, We Are Dreaming
        durationMs:
          type: number
          description: Spotify duration in milliseconds
          example: 241000
        index:
          type: number
          description: Source order index from Spotify
          example: 0
        explicit:
          type: boolean
          description: Whether the Spotify track is explicit
          example: false
        isrc:
          type: string
          description: ISRC if already known on the frontend
          example: USUG12100112
        externalUrl:
          type: string
          description: Spotify external URL for the track
          example: https://open.spotify.com/track/3n3Ppam7vgaVa1iaRUc9Lp
      required:
        - name
    ImportSpotifyPlaylistPayloadDto:
      type: object
      properties:
        id:
          type: string
          description: Spotify playlist ID or playlist URL
          example: 37i9dQZF1DXcBWIGoYBM5M
        name:
          type: string
          description: Spotify playlist display name
          example: Night Drive
        description:
          type: string
          description: Spotify playlist description
          example: Frontend-provided playlist payload
        ownerName:
          type: string
          description: Playlist owner display name
          example: Spotify User
        trackCount:
          type: number
          description: Track count provided by frontend
          example: 42
        imageUrl:
          type: string
          description: Playlist artwork URL
          example: https://i.scdn.co/image/ab67706f00000002...
        tracks:
          description: Ordered Spotify playlist tracks from the frontend
          type: array
          items:
            $ref: "#/components/schemas/ImportSpotifyPlaylistTrackPayloadDto"
      required:
        - id
        - name
        - tracks
    ImportSpotifyPlaylistRequestDto:
      type: object
      properties:
        targetUserId:
          type: string
          description: App user id forwarded by the trusted frontend import proxy when
            using a service token
          example: clx123example
        targetUserEmail:
          type: string
          description: App user email forwarded by the trusted frontend import proxy when
            using a service token
          example: listener@example.com
        targetUserName:
          type: string
          description: App user display name forwarded by the trusted frontend import
            proxy when using a service token
          example: Soulwax
        targetUserProfileImage:
          type: string
          description: App user profile image URL forwarded by the trusted frontend import
            proxy when using a service token
          example: https://cdn.discordapp.com/avatars/123/avatar.png
        source:
          type: string
          description: Optional source discriminator
          example: spotify
        spotifyPlaylistId:
          type: string
          description: Spotify playlist ID or URL for public server-side fetch using app
            credentials
          example: 37i9dQZF1DXcBWIGoYBM5M
        playlistId:
          type: string
          description: Legacy alias for spotifyPlaylistId, accepted for compatibility
          example: 37i9dQZF1DXcBWIGoYBM5M
        playlist:
          description: Stateless playlist payload from the frontend, bypassing backend
            Spotify OAuth/fetch
          allOf:
            - $ref: "#/components/schemas/ImportSpotifyPlaylistPayloadDto"
        sourcePlaylist:
          description: Alias for playlist, accepted for compatibility with frontend payloads
          allOf:
            - $ref: "#/components/schemas/ImportSpotifyPlaylistPayloadDto"
        playlistName:
          type: string
          description: Native playlist name override
          example: Imported Night Drive
        descriptionOverride:
          type: string
          description: Native playlist description override
          example: Imported from Spotify payload
        playlistDescription:
          type: string
          description: Alias for descriptionOverride, accepted for compatibility with
            frontend payloads
          example: Description override if provided
        createPlaylist:
          type: boolean
          description: When false, only translate Spotify tracks and return matched Deezer
            tracks without creating a backend playlist
          example: true
        isPublic:
          type: boolean
          description: Whether the created native playlist is public
          example: true
    RegisterDto:
      type: object
      properties:
        name:
          type: string
          example: John Doe
          description: The name of the user
        email:
          type: string
          example: john@example.com
          description: The email of the user
        password:
          type: string
          example: password123
          description: The password of the user
      required:
        - name
        - email
        - password
    LoginDto:
      type: object
      properties:
        email:
          type: string
          example: user@example.com
          description: The email of the user
        password:
          type: string
          example: password123
          description: The password of the user
      required:
        - email
        - password
    IssueServiceTokenDto:
      type: object
      properties:
        key:
          type: string
          description: Service key derived from UNIVERSAL_KEY.
          example: your-universal-key
      required:
        - key
    SpotifyRefreshDto:
      type: object
      properties:
        refreshToken:
          type: string
          description: Fallback app refresh token for non-cookie clients. Browser clients
            should use HTTP-only cookie.
    FindTrackIdResponseDto:
      type: object
      properties:
        name:
          type: string
          description: Original track title
        artist:
          type: string
          description: Original artist name
        deezerId:
          type: object
          description: Matched Deezer track ID
      required:
        - name
    TrackToConvertDto:
      type: object
      properties:
        name:
          type: string
          description: Track title to search on Deezer
        artist:
          type: string
          description: Artist name to improve Deezer search accuracy
      required:
        - name
    ConvertToDeezerRequestDto:
      type: object
      properties:
        tracks:
          minItems: 1
          description: Tracks to convert to Deezer IDs
          type: array
          items:
            $ref: "#/components/schemas/TrackToConvertDto"
      required:
        - tracks
    ConvertedTrackResultDto:
      type: object
      properties:
        name:
          type: string
          description: Original track title
        artist:
          type: string
          description: Original artist name
        deezerId:
          type: object
          description: Matched Deezer track ID
      required:
        - name
    ConvertToDeezerResponseDto:
      type: object
      properties:
        converted:
          type: number
          description: Number of tracks successfully converted
        total:
          type: number
          description: Total number of tracks processed
        tracks:
          description: Conversion results per track
          type: array
          items:
            $ref: "#/components/schemas/ConvertedTrackResultDto"
      required:
        - converted
        - total
        - tracks
    PreviewRequestDto:
      type: object
      properties:
        id:
          type: number
          description: Deezer track ID (number)
        query:
          type: string
          description: Search query string (will use first result)
        track:
          type: object
          description: Deezer track object (full track data)
    CreatePlaylistDto:
      type: object
      properties:
        name:
          type: string
          description: Playlist name
          example: My Chill Vibes
          maxLength: 100
        description:
          type: string
          description: Playlist description
          example: Perfect music for relaxing evenings
          maxLength: 500
        isPublic:
          type: boolean
          description: Whether the playlist is public
          example: true
          default: true
        coverImage:
          type: string
          description: Cover image URL
          example: https://example.com/cover.jpg
      required:
        - name
    ImportSpotifyPlaylistDto:
      type: object
      properties:
        spotifyPlaylistId:
          type: string
          description: Spotify playlist ID or playlist URL
          example: https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M
        nameOverride:
          type: string
          description: Override the created local playlist name
          example: Imported Favourites
        descriptionOverride:
          type: string
          description: Override the created local playlist description
          example: Imported from Spotify
        isPublic:
          type: boolean
          description: Whether the created local playlist should be public
          example: true
        createPlaylist:
          type: boolean
          description: When false, only translate Spotify tracks and return matched Deezer
            tracks without creating a backend playlist
          example: false
      required:
        - spotifyPlaylistId
    UpdatePlaylistDto:
      type: object
      properties:
        name:
          type: string
          description: Playlist name
          example: My Updated Playlist
          maxLength: 100
        description:
          type: string
          description: Playlist description
          example: Updated description
          maxLength: 500
        isPublic:
          type: boolean
          description: Whether the playlist is public
          example: false
        coverImage:
          type: string
          description: Cover image URL
          example: https://example.com/new-cover.jpg
    AddToPlaylistDto:
      type: object
      properties:
        deezerTrackId:
          type: string
          description: Deezer track ID to add
          example: "3135556"
        position:
          type: number
          description: Position in playlist (optional, defaults to end)
          example: 5
      required:
        - deezerTrackId
    ReorderPlaylistDto:
      type: object
      properties:
        trackId:
          type: string
          description: Track ID to move
          example: 123e4567-e89b-12d3-a456-426614174000
        newPosition:
          type: number
          description: New position (0-based index)
          example: 3
      required:
        - trackId
        - newPosition
    PlaylistConversionRequestDto:
      type: object
      properties:
        songs:
          description: Array of songs to convert
          example:
            - name: Creep
              artist: Radiohead
            - name: Bohemian Rhapsody
              artist: Queen
          type: array
          items:
            $ref: "#/components/schemas/SongInputDto"
        output:
          type: string
          enum:
            - deezer
            - spotify
          description: Target platform for conversion
          example: deezer
      required:
        - songs
        - output
    PlaylistConversionResponseDto:
      type: object
      properties:
        output:
          type: string
          description: Target platform
        inputCount:
          type: number
          description: Number of input songs
        convertedCount:
          type: number
          description: Number of successfully converted songs
        results:
          description: Array of conversion results, one per input song
          type: array
          items:
            type: string
      required:
        - output
        - inputCount
        - convertedCount
        - results
    LastfmSongInputDto:
      type: object
      properties:
        name:
          type: string
          description: Song title to use for Last.fm search
        artist:
          type: string
          description: Artist name to use for Last.fm search
        album:
          type: string
          description: Album name to use for Last.fm search
    LastfmSpiceUpRequestDto:
      type: object
      properties:
        songs:
          minItems: 1
          description: Songs used as seeds for Last.fm search
          type: array
          items:
            $ref: "#/components/schemas/LastfmSongInputDto"
        limit:
          type: number
          description: Number of recommended tracks to return (1-100)
          default: 20
        mode:
          type: string
          description: Diversity mode for recommendation variety
          enum: &a23
            - strict
            - normal
            - diverse
          default: normal
      required:
        - songs
    LastfmRecommendationDto:
      type: object
      properties:
        name:
          type: string
          description: Track name
        artist:
          type: string
          description: Artist name
        url:
          type: string
          description: Last.fm track URL
        match:
          type: number
          description: Match score provided by Last.fm
        mbid:
          type: string
          description: MusicBrainz ID if available
      required:
        - name
        - artist
        - url
    LastfmSpiceUpResponseDto:
      type: object
      properties:
        mode:
          type: string
          description: Diversity mode applied
        inputSongs:
          type: number
          description: Number of input songs provided
        recommendations:
          description: Recommended Last.fm tracks
          type: array
          items:
            $ref: "#/components/schemas/LastfmRecommendationDto"
        foundSongs:
          type: number
          description: Number of input songs successfully matched on Last.fm
      required:
        - mode
        - inputSongs
        - recommendations
        - foundSongs
    LastfmSpiceUpWithDeezerRequestDto:
      type: object
      properties:
        songs:
          minItems: 1
          description: Songs used as seeds for Last.fm search
          type: array
          items:
            $ref: "#/components/schemas/LastfmSongInputDto"
        limit:
          type: number
          description: Number of recommended tracks to return (1-100)
          default: 20
        mode:
          type: string
          description: Diversity mode for recommendation variety
          enum: *a23
          default: normal
        convertToDeezer:
          type: boolean
          description: Convert Last.fm recommendations to Deezer track IDs
          default: true
      required:
        - songs
    LastfmSpiceUpWithDeezerResponseRecommendationDto:
      type: object
      properties:
        name:
          type: string
          description: Track name
        artist:
          type: string
          description: Artist name
        url:
          type: string
          description: Last.fm track URL
        match:
          type: number
          description: Match score provided by Last.fm
        mbid:
          type: string
          description: MusicBrainz ID if available
        deezerId:
          type: object
          description: Deezer track ID if conversion succeeded
      required:
        - name
        - artist
        - url
    LastfmSpiceUpWithDeezerResponseDto:
      type: object
      properties:
        mode:
          type: string
          description: Diversity mode applied
        inputSongs:
          type: number
          description: Number of input songs provided
        foundSongs:
          type: number
          description: Number of input songs successfully matched on Last.fm
        recommendations:
          description: Recommended tracks with optional Deezer IDs
          type: array
          items:
            $ref: "#/components/schemas/LastfmSpiceUpWithDeezerResponseRecommendationDto"
        deezerConversion:
          type: object
          description: Summary of Deezer ID conversions
          example:
            converted: 18
            total: 20
      required:
        - mode
        - inputSongs
        - foundSongs
        - recommendations
    SpotifyAuthCallbackDto:
      type: object
      properties:
        code:
          type: string
          description: Authorization code from Spotify OAuth callback
          example: AQD7f9...
        state:
          type: string
          description: State parameter for CSRF protection
      required:
        - code
    AnalyzeTrackDto:
      type: object
      properties:
        trackId:
          type: string
          description: Spotify track ID or URL
          example: 3n3Ppam7vgaVa1iaRUc9Lp
      required:
        - trackId
    BatchAnalyzeTracksDto:
      type: object
      properties:
        trackIds:
          description: Array of Spotify track IDs
          example:
            - 3n3Ppam7vgaVa1iaRUc9Lp
            - 7qiZfU4dY1lWllzX7mPBI
          type: array
          items:
            type: string
      required:
        - trackIds
    UpdateUserDto:
      type: object
      properties:
        name:
          type: string
        profileImage:
          type: string
    TrackResponseDto:
      type: object
      properties:
        id:
          type: string
          description: Spotify track ID
          example: 3z8h0TU7ReDPLIbEnYhWZb
        name:
          type: string
          description: Track name
          example: Bohemian Rhapsody
        artists:
          type: string
          description: Comma-separated list of artist names
          example: Queen
        album:
          type: string
          description: Album name
          example: A Night At The Opera
        imageUrl:
          type: object
          description: Album cover art URL
          example: https://i.scdn.co/image/ab67616d0000b273e8b066f70c206551210d902b
          nullable: true
      required:
        - id
        - name
        - artists
        - album
    ErrorResponseDto:
      type: object
      properties:
        statusCode:
          type: number
          description: HTTP status code
          example: 400
        message:
          type: object
          description: Error message describing what went wrong
          example: Could not resolve any of the provided tracks
        error:
          type: string
          description: Error type/category
          example: Bad Request
      required:
        - statusCode
        - message
        - error
    PlaylistSearchResultDto:
      type: object
      properties:
        id:
          type: string
          description: Spotify playlist ID
          example: 37i9dQZF1DWXRqgorJj26U
        name:
          type: string
          description: Playlist name
          example: Rock Classics
        description:
          type: string
          description: Playlist description
          example: Rock legends & epic songs that continue to inspire generations.
        owner:
          type: string
          description: Playlist owner display name
          example: Spotify
        tracksTotal:
          type: number
          description: Total number of tracks in the playlist
          example: 150
        imageUrl:
          type: object
          description: Playlist cover image URL
          example: https://i.scdn.co/image/ab67706f00000003...
          nullable: true
      required:
        - id
        - name
        - description
        - owner
        - tracksTotal
    PlaylistDetailResponseDto:
      type: object
      properties:
        id:
          type: string
          description: Spotify playlist ID
          example: 37i9dQZF1DWXRqgorJj26U
        name:
          type: string
          description: Playlist name
          example: Rock Classics
        description:
          type: string
          description: Playlist description
          example: Rock legends & epic songs
        imageUrl:
          type: object
          description: Playlist cover image URL
          example: https://i.scdn.co/image/ab67706f00000003...
          nullable: true
        tracks:
          description: Array of tracks in the playlist
          type: array
          items:
            $ref: "#/components/schemas/TrackResponseDto"
      required:
        - id
        - name
        - description
        - tracks
    TrackInput:
      type: object
      properties:
        id:
          type: string
          description: Spotify track ID (mutually exclusive with name)
          example: 3n3Ppam7vgaVa1iaRUc9Lp
        name:
          type: string
          description: Track name for search-based resolution (mutually exclusive with id)
          example: Bohemian Rhapsody
        artist:
          type: string
          description: Artist name to improve search accuracy (used with name)
          example: Queen
    RecommendationRequestDto:
      type: object
      properties:
        tracks:
          description: Array of 1-5 tracks to base recommendations on. Each track can be
            specified by ID, name (with optional artist), or a mix of both.
          minItems: 1
          maxItems: 5
          example:
            - id: 3n3Ppam7vgaVa1iaRUc9Lp
            - name: Stairway to Heaven
              artist: Led Zeppelin
          type: array
          items:
            $ref: "#/components/schemas/TrackInput"
        limit:
          type: number
          description: Number of recommendations to return (1-100). Defaults to 20 if not
            specified.
          minimum: 1
          maximum: 100
          default: 20
          example: 30
      required:
        - tracks
    TrackWithPreviewResponseDto:
      type: object
      properties:
        id:
          type: string
          description: Spotify track ID
          example: 3z8h0TU7ReDPLIbEnYhWZb
        name:
          type: string
          description: Track name
          example: Bohemian Rhapsody
        artists:
          type: string
          description: Comma-separated list of artist names
          example: Queen
        album:
          type: string
          description: Album name
          example: A Night At The Opera
        imageUrl:
          type: object
          description: Album cover art URL
          example: https://i.scdn.co/image/ab67616d0000b273e8b066f70c206551210d902b
          nullable: true
        previewUrl:
          type: object
          description: 30-second preview URL (if available)
          example: https://p.scdn.co/mp3-preview/...
          nullable: true
      required:
        - id
        - name
        - artists
        - album
    LegacyRecommendationRequestDto:
      type: object
      properties:
        trackIds:
          description: Array of 1-5 Spotify track IDs to base recommendations on. Always
            returns 20 recommendations.
          minItems: 1
          maxItems: 5
          example:
            - 3n3Ppam7vgaVa1iaRUc9Lp
            - 5ChkMS8OtdzJeqyybCc9R5
            - 0c6xIDDpzE81m2q797ordA
          type: array
          items:
            type: string
      required:
        - trackIds
    BulkSongsRecommendationDto:
      type: object
      properties:
        giveSongs:
          description: Array of song objects. Each song can have an ID or name (with
            optional artist). Will use up to 5 songs as seeds.
          minItems: 1
          example:
            - id: 3n3Ppam7vgaVa1iaRUc9Lp
              name: Mr. Brightside
            - name: Somebody Told Me
              artist: The Killers
            - name: When You Were Young
              artist: The Killers
            - id: 0eGsygTp906u18L0Oimnem
          type: array
          items:
            $ref: "#/components/schemas/TrackInput"
        n:
          type: number
          description: Number of recommendations to return (1-100). Defaults to number of
            input songs if not specified.
          minimum: 1
          maximum: 100
          example: 10
      required:
        - giveSongs
    RecommendationMode:
      type: number
      enum:
        - 0
        - 1
        - 2
      description: >-
        Recommendation mode:

        - 0 (Strict): Returns tracks from the same artists as the seed tracks

        - 1 (Balanced): Returns tracks from related artists in similar genres
        (uses Spotify API internally)

        - 2 (Diverse): Returns tracks with vague genre adherence for more
        variety (uses Spotify API internally)

        Defaults to Balanced (1) if not specified.
    DeezerRecommendationRequestDto:
      type: object
      properties:
        trackNames:
          description: Array of track names to base recommendations on. Can be simple
            track names or "Artist - Track" format for better accuracy.
          minItems: 1
          example:
            - Bohemian Rhapsody
            - Queen - We Will Rock You
            - Led Zeppelin - Stairway to Heaven
            - Hotel California
          type: array
          items:
            type: string
        n:
          type: number
          description: Number of recommendations to return. Defaults to the number of
            input tracks if not specified.
          minimum: 1
          maximum: 100
          example: 10
        mode:
          description: >-
            Recommendation mode:

            - 0 (Strict): Returns tracks from the same artists as the seed
            tracks

            - 1 (Balanced): Returns tracks from related artists in similar
            genres (uses Spotify API internally)

            - 2 (Diverse): Returns tracks with vague genre adherence for more
            variety (uses Spotify API internally)

            Defaults to Balanced (1) if not specified.
          example: 1
          allOf:
            - $ref: "#/components/schemas/RecommendationMode"
      required:
        - trackNames
    DeezerArtistResponseDto:
      type: object
      properties:
        id:
          type: number
          description: Deezer artist ID
          example: 27
        name:
          type: string
          description: Artist name
          example: Daft Punk
        link:
          type: string
          description: Deezer artist page URL
          example: https://www.deezer.com/artist/27
        picture:
          type: string
          description: Primary artist image
          example: https://api.deezer.com/artist/27/image
        picture_small:
          type: string
          description: Small artist image
          example: https://e-cdns-images.dzcdn.net/images/artist/12345/56x56-000000-80-0-0.jpg
        picture_medium:
          type: string
          description: Medium artist image
          example: https://e-cdns-images.dzcdn.net/images/artist/12345/250x250-000000-80-0-0.jpg
        picture_big:
          type: string
          description: Large artist image
          example: https://e-cdns-images.dzcdn.net/images/artist/12345/500x500-000000-80-0-0.jpg
        picture_xl:
          type: string
          description: Extra large artist image
          example: https://e-cdns-images.dzcdn.net/images/artist/12345/1000x1000-000000-80-0-0.jpg
        tracklist:
          type: string
          description: Tracklist URL for artist top tracks
          example: https://api.deezer.com/artist/27/top?limit=50
        type:
          type: string
          description: Object type identifier
          example: artist
      required:
        - id
        - name
        - link
        - picture
        - picture_small
        - picture_medium
        - picture_big
        - picture_xl
        - tracklist
        - type
    DeezerAlbumResponseDto:
      type: object
      properties:
        id:
          type: number
          description: Deezer album ID
          example: 302127
        title:
          type: string
          description: Album title
          example: Discovery
        cover:
          type: string
          description: Primary album cover
          example: https://api.deezer.com/album/302127/image
        cover_small:
          type: string
          description: Small album cover
          example: https://e-cdns-images.dzcdn.net/images/cover/12345/56x56-000000-80-0-0.jpg
        cover_medium:
          type: string
          description: Medium album cover
          example: https://e-cdns-images.dzcdn.net/images/cover/12345/250x250-000000-80-0-0.jpg
        cover_big:
          type: string
          description: Large album cover
          example: https://e-cdns-images.dzcdn.net/images/cover/12345/500x500-000000-80-0-0.jpg
        cover_xl:
          type: string
          description: Extra large album cover
          example: https://e-cdns-images.dzcdn.net/images/cover/12345/1000x1000-000000-80-0-0.jpg
        md5_image:
          type: string
          description: MD5 hash for the cover image
          example: 1a2b3c4d5e6f7890abcdef1234567890
        tracklist:
          type: string
          description: Tracklist URL for the album
          example: https://api.deezer.com/album/302127/tracks
        type:
          type: string
          description: Object type identifier
          example: album
      required:
        - id
        - title
        - cover
        - cover_small
        - cover_medium
        - cover_big
        - cover_xl
        - md5_image
        - tracklist
        - type
    DeezerTrackResponseDto:
      type: object
      properties:
        id:
          type: number
          description: Deezer track ID
          example: 3135556
        readable:
          type: boolean
          description: Whether the track is available for playback
          example: true
        title:
          type: string
          description: Track title
          example: Harder, Better, Faster, Stronger
        title_short:
          type: string
          description: Short track title
          example: Harder Better Faster Stronger
        title_version:
          type: string
          description: Track version information
          example: ""
        link:
          type: string
          description: Deezer track URL
          example: https://www.deezer.com/track/3135556
        duration:
          type: number
          description: Track duration in seconds
          example: 224
        rank:
          type: number
          description: Track popularity ranking
          example: 654321
        explicit_lyrics:
          type: boolean
          description: Whether the track contains explicit lyrics
          example: false
        explicit_content_lyrics:
          type: number
          description: Explicit lyrics flag (numeric)
          example: 0
        explicit_content_cover:
          type: number
          description: Explicit cover flag (numeric)
          example: 0
        preview:
          type: object
          description: Preview URL (30 seconds)
          example: https://cdns-preview-d.dzcdn.net/stream/abcdefg
          nullable: true
        md5_image:
          type: string
          description: MD5 hash for the track image
          example: 1a2b3c4d5e6f7890abcdef1234567890
        artist:
          description: Track artist details
          allOf:
            - $ref: "#/components/schemas/DeezerArtistResponseDto"
        album:
          description: Track album details
          allOf:
            - $ref: "#/components/schemas/DeezerAlbumResponseDto"
        type:
          type: string
          description: Object type identifier
          example: track
      required:
        - id
        - readable
        - title
        - title_short
        - title_version
        - link
        - duration
        - rank
        - explicit_lyrics
        - explicit_content_lyrics
        - explicit_content_cover
        - md5_image
        - artist
        - album
        - type
