{"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":["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":["Root"]}},"/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":["Root"]}},"/health":{"get":{"operationId":"AppController_getHealth","parameters":[],"responses":{"200":{"description":"Returns health status including database connectivity"}},"summary":"Health check endpoint with critical system status","tags":["Root"]}},"/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":["Root"]}},"/status":{"get":{"operationId":"OpsController_getStatus","parameters":[],"responses":{"200":{"description":"Service is alive"}},"summary":"Lightweight liveness check","tags":["Ops"]}},"/config/public":{"get":{"operationId":"OpsController_getPublicConfig","parameters":[],"responses":{"200":{"description":"Public config"}},"summary":"Public runtime configuration (non-secret)","tags":["Ops"]}},"/rate-limits":{"get":{"operationId":"OpsController_getRateLimits","parameters":[],"responses":{"200":{"description":"Rate limit policy"}},"summary":"Rate limit policy information","tags":["Ops"]}},"/docs/openapi":{"get":{"operationId":"OpsController_getOpenApiAlias","parameters":[],"responses":{"302":{"description":"Redirect to /openapi.json"}},"summary":"Alias to OpenAPI JSON spec","tags":["Ops"]}},"/cache/stats":{"get":{"operationId":"OpsController_getCacheStats[0]","parameters":[],"responses":{"200":{"description":"Cache statistics"}},"security":[{"bearer":[]}],"summary":"Get in-memory cache stats","tags":["Ops"]}},"/api/v2/cache/stats":{"get":{"operationId":"OpsController_getCacheStats[1]","parameters":[],"responses":{"200":{"description":"Cache statistics"}},"security":[{"bearer":[]}],"summary":"Get in-memory cache stats","tags":["Ops"]}},"/cache/clear":{"post":{"operationId":"OpsController_clearCaches","parameters":[],"responses":{"200":{"description":"Cache cleared"}},"security":[{"bearer":[]}],"summary":"Clear in-memory caches","tags":["Ops"]}},"/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":["Ops"]}},"/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":["Ops"]}},"/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":["Ops"]}},"/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":["Ops"]}},"/metrics":{"get":{"operationId":"OpsController_getMetrics","parameters":[],"responses":{"200":{"description":"Prometheus metrics payload","content":{"text/plain":{"schema":{"type":"string"}}}}},"summary":"Prometheus-style metrics","tags":["Ops"]}},"/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":["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":["Spotify"]}},"/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":["Spotify"]}},"/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":["Spotify"]}},"/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":["Spotify"]}},"/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":["Spotify"]}},"/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":["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":["auth"]}},"/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":["auth"]}},"/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":["auth"]}},"/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":["auth"]}},"/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":["auth"]}},"/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":["auth"]}},"/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":["auth"]}},"/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":["auth"]}},"/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":["auth"]}},"/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":["auth"]}},"/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":["auth"]}},"/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":["auth"]}},"/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":["auth"]}},"/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":["auth"]}},"/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":["auth"]}},"/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":["auth"]}},"/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":["auth"]}},"/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":["auth"]}},"/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":["auth"]}},"/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":["auth"]}},"/auth/me":{"get":{"operationId":"AuthController_getProfile[0]","parameters":[],"responses":{"200":{"description":"Return current user info"}},"security":[{"bearer":[]}],"summary":"Get current user info","tags":["auth"]}},"/api/auth/me":{"get":{"operationId":"AuthController_getProfile[1]","parameters":[],"responses":{"200":{"description":"Return current user info"}},"security":[{"bearer":[]}],"summary":"Get current user info","tags":["auth"]}},"/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":["auth"]}},"/auth/refresh":{"get":{"operationId":"AuthController_refresh[0]","parameters":[],"responses":{"200":{"description":"Token refreshed successfully."}},"security":[{"bearer":[]}],"summary":"Refresh the current JWT token","tags":["auth"]}},"/api/auth/refresh":{"get":{"operationId":"AuthController_refresh[1]","parameters":[],"responses":{"200":{"description":"Token refreshed successfully."}},"security":[{"bearer":[]}],"summary":"Refresh the current JWT token","tags":["auth"]}},"/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":["auth"]}},"/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":["auth"]}},"/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":["auth"]}},"/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":["auth"]}},"/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":["Deezer"]}},"/api/music/genres":{"get":{"operationId":"DeezerController_getGenresEnglish","parameters":[],"responses":{"200":{"description":"List of Deezer genres in English"}},"summary":"Get Deezer genres (English)","tags":["Deezer"]}},"/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":["Deezer"]}},"/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":["Deezer"]}},"/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":["Deezer"]}},"/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":["Deezer"]}},"/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":["Deezer"]}},"/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":["Deezer"]}},"/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":["Deezer"]}},"/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":["Deezer"]}},"/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":["Deezer"]}},"/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":["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":["Preview Images"]}},"/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":["Preview Images"]}},"/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":["Preview Images"]}},"/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.\n\n**Important:** The query parameter must be properly URL-encoded. Use `encodeURIComponent()` on the client side. Examples:\n- ✅ Works: `?q=isobel%20bj%C3%B6rk` (properly encoded)\n- ✅ Works: Use `--data-urlencode` with curl\n- ❌ 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":["Preview Images"]}},"/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":["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":["music"]}},"/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":["music"]}},"/music/health":{"get":{"operationId":"MusicStreamingController_healthCheck","parameters":[],"responses":{"200":{"description":"Service is healthy"}},"summary":"Health check endpoint","tags":["music"]}},"/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":["music"]}},"/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":["music"]}},"/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":["music"]}},"/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":["music"]}},"/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":["music"]}},"/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":["music"]}},"/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":["music"]}},"/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":["music"]}},"/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":[{"bearer":[]}],"summary":"Add a track to favorites","tags":["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":[{"bearer":[]}],"summary":"Remove a track from favorites","tags":["favorites"]}},"/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":[{"bearer":[]}],"summary":"Get all favorite tracks","tags":["favorites"]}},"/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":[{"bearer":[]}],"summary":"Check if a track is in favorites","tags":["favorites"]}},"/music/favorites/count":{"get":{"operationId":"FavoritesController_getFavoriteCount","parameters":[],"responses":{"200":{"description":"Returns { count: number }"},"401":{"description":"Unauthorized"}},"security":[{"bearer":[]}],"summary":"Get total count of favorite tracks","tags":["favorites"]}},"/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":[{"bearer":[]}],"summary":"Batch check if tracks are favorited","tags":["favorites"]}},"/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":[{"bearer":[]}],"summary":"Get listening history","tags":["listening-history"]},"delete":{"operationId":"ListeningHistoryController_clearHistory","parameters":[],"responses":{"204":{"description":"Listening history cleared"},"401":{"description":"Unauthorized"}},"security":[{"bearer":[]}],"summary":"Clear listening history","tags":["listening-history"]}},"/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":[{"bearer":[]}],"summary":"Get recently played tracks (unique)","tags":["listening-history"]}},"/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":[{"bearer":[]}],"summary":"Get listening statistics","tags":["listening-history"]}},"/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":[{"bearer":[]}],"summary":"Create a new playlist","tags":["playlists"]},"get":{"operationId":"PlaylistController_getUserPlaylists","parameters":[],"responses":{"200":{"description":"List of playlists"},"401":{"description":"Unauthorized"}},"security":[{"bearer":[]}],"summary":"Get all playlists for the authenticated user","tags":["playlists"]}},"/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":[{"bearer":[]}],"summary":"Import a public Spotify playlist into a native Starchild playlist","tags":["playlists"]}},"/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":[{"bearer":[]}],"summary":"Get a specific playlist by ID","tags":["playlists"]},"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":[{"bearer":[]}],"summary":"Update a playlist","tags":["playlists"]},"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":[{"bearer":[]}],"summary":"Delete a playlist","tags":["playlists"]}},"/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":[{"bearer":[]}],"summary":"Add a track to a playlist","tags":["playlists"]}},"/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":[{"bearer":[]}],"summary":"Remove a track from a playlist","tags":["playlists"]}},"/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":[{"bearer":[]}],"summary":"Reorder a track in a playlist","tags":["playlists"]}},"/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":["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":["Last.fm"]}},"/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":["Last.fm"]}},"/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":["Last.fm"]}},"/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":["Last.fm"]}},"/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":["Last.fm"]}},"/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":["Last.fm"]}},"/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":["Last.fm"]}},"/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":["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":["Legacy Spotify"]}},"/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":["Legacy Spotify"]}},"/spotify/auth/disconnect":{"delete":{"operationId":"LegacySpotifyController_disconnect","parameters":[],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Disconnect Spotify account","tags":["Legacy Spotify"]}},"/spotify/auth/status":{"get":{"operationId":"LegacySpotifyController_getConnectionStatus","parameters":[],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Check Spotify connection status","tags":["Legacy Spotify"]}},"/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":["Legacy Spotify"]}},"/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":["Legacy Spotify"]}},"/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":["Legacy Spotify"]}},"/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":["Legacy Spotify"]}},"/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":["Legacy Spotify"]}},"/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":["Legacy Spotify"]}},"/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":["Legacy Spotify"]}},"/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":["Legacy Spotify"]}},"/version":{"get":{"operationId":"LegacyMetaController_getVersion","parameters":[],"responses":{"200":{"description":""}},"summary":"Legacy version endpoint (V1 compatible route)","tags":["Legacy Meta"]}},"/api-yaml":{"get":{"operationId":"LegacyMetaController_getApiYaml","parameters":[],"responses":{"200":{"description":""}},"summary":"Legacy OpenAPI YAML endpoint (V1 compatible route)","tags":["Legacy Meta"]}},"/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":["Legacy Meta"]}},"/users/profile":{"get":{"operationId":"UserController_getProfile","parameters":[],"responses":{"200":{"description":"Return user profile"}},"security":[{"bearer":[]}],"summary":"Get user profile","tags":["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":[{"bearer":[]}],"summary":"Update user profile","tags":["users"]}},"/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":["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":["Music & Recommendations"]}},"/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":["Music & Recommendations"]}},"/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":["Music & Recommendations"]}},"/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":["Music & Recommendations"]}},"/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":["Music & Recommendations"]}},"/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":["Music & Recommendations"]}},"/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":["Music & Recommendations"]}},"/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":["Music & Recommendations"]}},"/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":["Music & Recommendations"]}},"/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":["Music & Recommendations"]}},"/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":["Music & Recommendations"]}}},"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":["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":["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":["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":["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":["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":["useQueueOnly","blendHistory","includeHistory"],"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":["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":["strict","normal","diverse"],"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:\n- 0 (Strict): Returns tracks from the same artists as the seed tracks\n- 1 (Balanced): Returns tracks from related artists in similar genres (uses Spotify API internally)\n- 2 (Diverse): Returns tracks with vague genre adherence for more variety (uses Spotify API internally)\nDefaults 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:\n- 0 (Strict): Returns tracks from the same artists as the seed tracks\n- 1 (Balanced): Returns tracks from related artists in similar genres (uses Spotify API internally)\n- 2 (Diverse): Returns tracks with vague genre adherence for more variety (uses Spotify API internally)\nDefaults 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"]}}}}