music-api ========= spotify search and download api using embed graphql metadata and librespot streaming ROUTES: | Method | Path | Description | | ------ | ---- | ----------- | | POST | /api/spotify/download/search | Search best track and download audio | | GET | /api/spotify/search | Search tracks, albums, artists, playlists | | GET | /api/spotify/download/tracks/:id | Download track audio (Premium, auth required) | | GET | /api/spotify/tracks/:id | Track metadata | | GET | /api/spotify/albums/:id | Album metadata | | GET | /api/spotify/playlists/:id | Playlist metadata | | GET | /api/spotify/artists/:id | Artist metadata | | GET | /api/spotify/lyrics/tracks/:id | Track lyrics | | GET | /api/spotify/parse | Parse a Spotify URL | | GET | /api/spotify/auth/login | Start Spotify OAuth (PKCE) | | GET | /api/spotify/auth/callback | Complete Spotify OAuth redirect | | GET | /api/spotify/auth/status | Auth and librespot status | | POST | /api/spotify/auth/logout | Clear stored credentials | | GET | / | This usage page | | GET | /api/health | Health check | POST /api/spotify/download/search ================================ curl -L "http://music.bartoszbak.org/api/spotify/download/search" \ -H "Content-Type: application/json" \ -d '{"search":"Starboy the weeknd","bitrate":320,"format":"mp3"}' \ -o starboy.mp3 REQUEST FIELDS: | Field | Where | Required | Description | | ----- | ----- | -------- | ----------- | | search | JSON body | yes | Natural-language track query | | bitrate | JSON body | no | Spotify source bitrate: 160 or 320 (default 320, Premium) | | format | JSON body | no | mp3 or ogg (default mp3; ogg skips ffmpeg) | EXAMPLE RESPONSE: (binary audio/mpeg or audio/ogg stream) RESPONSE HEADERS: | Header | Description | | ------ | ----------- | | X-Spotify-Track-Id | Matched Spotify track id | | X-Spotify-Track-Name | Matched Spotify track name | | X-Spotify-Track-Artists | Matched artist names | | X-Spotify-Track-Url | Spotify URL for the match | | X-Output-Format | mp3 or ogg | ERROR RESPONSE: { "error": "No track found for query", "search": "..." } GET /api/spotify/search ==================== curl "http://music.bartoszbak.org/api/spotify/search?q=blinding%20lights&type=track&limit=5" REQUEST FIELDS: | Field | Where | Required | Description | | ----- | ----- | -------- | ----------- | | q | query | yes | Search query | | type | query | no | track, album, artist, or playlist (default track) | | limit | query | no | Max results 1-50 (default 20) | | offset | query | no | Pagination offset (default 0) | EXAMPLE RESPONSE: { "query": "blinding lights", "type": "track", "limit": 5, "offset": 0, "items": [ { "id": "0VjIjW4GlUZAMYd2vXMi3b", "name": "Blinding Lights", "type": "track", "artists": [ { "id": "1Xyo4u8uXC1ZmMpatF05PJ", "name": "The Weeknd" } ], "album": { "id": "4yP0hdKOZMnw8iBPLsKfhU", "name": "After Hours", "releaseDate": "2020", "images": [ { "url": "https://i.scdn.co/image/..." } ] }, "durationMs": 200040, "explicit": false, "url": "https://open.spotify.com/track/0VjIjW4GlUZAMYd2vXMi3b" } ] } GET /api/spotify/download/tracks/:id =================================== curl -L "http://music.bartoszbak.org/api/spotify/download/tracks/0VjIjW4GlUZAMYd2vXMi3b?bitrate=320" -o track.ogg REQUEST FIELDS: | Field | Where | Required | Description | | ----- | ----- | -------- | ----------- | | id | path | yes | Spotify track id | | bitrate | query | no | 160 or 320 (default 320, Premium) | EXAMPLE RESPONSE: (binary audio/ogg stream) ERROR RESPONSE: { "error": "Not authenticated. Visit GET /api/spotify/auth/login..." } GET /api/spotify/lyrics/tracks/:id ================================= curl "http://music.bartoszbak.org/api/spotify/lyrics/tracks/7MXVkk9YMctZqd1Srtv4MB?format=lrc" REQUEST FIELDS: | Field | Where | Required | Description | | ----- | ----- | -------- | ----------- | | id | path | yes | Spotify track id | | format | query | no | json or lrc (default json) | EXAMPLE RESPONSE: { "id": "7MXVkk9YMctZqd1Srtv4MB", "lyrics": { "syncType": "LINE_SYNCED", "lines": [ { "startTimeMs": "12345", "words": "example line" } ] }, "lrc": "[00:12.34] example line" } GET /api/spotify/auth/login =========================== curl "http://music.bartoszbak.org/api/spotify/auth/login" EXAMPLE RESPONSE: { "authUrl": "https://accounts.spotify.com/authorize?...", "state": "abc123", "callbackMode": "api-route", "message": "Open authUrl in a browser, authorize with your Premium Spotify account...", "redirectUri": "http://music.bartoszbak.org/api/spotify/auth/callback" } for deployed and iOS Shortcuts flows, register the redirect URI in Spotify and set SPOTIFY_CLIENT_ID local desktop auth can keep the default http://127.0.0.1:4381/login redirect GET /api/spotify/auth/callback ============================== curl "http://music.bartoszbak.org/api/spotify/auth/callback?code=...&state=..." REQUEST FIELDS: | Field | Where | Required | Description | | ----- | ----- | -------- | ----------- | | code | query | yes | Spotify authorization code | | state | query | yes | OAuth state returned by /api/spotify/auth/login | EXAMPLE RESPONSE: (text/html authentication result page) GET /api/spotify/parse ====================== curl "http://music.bartoszbak.org/api/spotify/parse?url=https://open.spotify.com/track/0VjIjW4GlUZAMYd2vXMi3b" REQUEST FIELDS: | Field | Where | Required | Description | | ----- | ----- | -------- | ----------- | | url | query | yes | Spotify open URL | EXAMPLE RESPONSE: { "type": "track", "id": "0VjIjW4GlUZAMYd2vXMi3b", "url": "https://open.spotify.com/track/0VjIjW4GlUZAMYd2vXMi3b" }