How to Integrate the SpotifySaver API with External Applications Using REST Endpoints
The SpotifySaver API provides FastAPI-based REST endpoints that allow external applications to trigger downloads, monitor task progress, and retrieve Spotify metadata via standard HTTP requests.
The SpotifySaver API is the REST interface for the gabrielbaute/spotify-saver repository, exposing a stateless HTTP layer over the core download engine. Built on FastAPI and served by Uvicorn, it enables third-party automation, CI/CD pipelines, or frontend applications to programmatically convert Spotify tracks, albums, and playlists into local audio files without interacting with the CLI directly.
API Architecture and Entry Points
The server bootstrap logic resides in spotifysaver/api/main.py, where the FastAPI application is instantiated and executed:
app = create_app() # FastAPI instance built via factory
uvicorn.run(
"spotifysaver.api.main:app",
host=APIConfig.API_HOST,
port=APIConfig.API_PORT,
reload=True,
log_level=APIConfig.LOG_LEVEL,
)
The create_app() factory in spotifysaver/api/app.py configures Cross-Origin Resource Sharing (CORS) using APIConfig.ALLOWED_ORIGINS, mounts static UI assets, and registers the download router under the /api/v1 prefix. Centralized configuration defaults are stored in spotifysaver/api/config.py, including host, port, and output directory settings.
REST Endpoint Reference
All public REST endpoints are defined in spotifysaver/api/routers/download.py and mounted at /api/v1. The router exposes the following operations:
| HTTP Method | Path | Purpose | Implementation Function |
|---|---|---|---|
| POST | /api/v1/download |
Initiates a download job for a track, album, or playlist. Returns a task_id. |
start_download (lines 33–84) |
| GET | /api/v1/download/{task_id}/status |
Retrieves current job status: pending, processing, completed, or failed. |
get_download_status (lines 90–96) |
| GET | /api/v1/download/{task_id}/cancel |
Cancels a running job if it has not finished. | cancel_download (lines 99–114) |
| GET | /api/v1/downloads |
Lists all tasks categorized into completed, pending, and processing. |
list_downloads (lines 117–138) |
| GET | /api/v1/inspect |
Returns Spotify metadata (title, artists, duration) without downloading files. | inspect_spotify_url (lines 141–199) |
| GET | /api/v1/config/output_dir |
Exposes the default output directory configured in APIConfig. |
get_default_output_dir (lines 55–58) |
The start_download endpoint accepts a JSON body matching the DownloadRequest Pydantic schema and delegates execution to DownloadService via FastAPI's BackgroundTasks, ensuring the HTTP response returns immediately while processing continues asynchronously.
Data Contracts and Schemas
Type safety and automatic API documentation are enforced through Pydantic models located in spotifysaver/api/schemas.py:
DownloadRequest– Defines the POST body for/download, includingspotify_url,output_format,bit_rate,output_dir, and boolean flags for lyrics and cover art.DownloadResponse– Returned upon job creation, containingtask_id,status,content_type, and a human-readablemessage.DownloadStatus– Polling payload withprogresspercentage,current_track, and detailed status fields.TrackInfo,AlbumInfo,PlaylistInfo– Metadata structures returned by the/inspectendpoint.
These schemas generate the interactive OpenAPI documentation accessible at /docs when the server is running.
Integration Examples
Start a Download via cURL
curl -X POST http://localhost:8000/api/v1/download \
-H "Content-Type: application/json" \
-d '{
"spotify_url": "https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M",
"download_lyrics": true,
"download_cover": true,
"generate_nfo": false,
"output_format": "mp3",
"bit_rate": 256,
"output_dir": "/tmp/music"
}'
Expected Response:
{
"task_id": "a3f1c9e2-4d7b-48b5-9e6d-2b7c9fa5e3d1",
"status": "pending",
"spotify_url": "https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M",
"content_type": "playlist",
"message": "Download task started for playlist"
}
Poll Task Status with Python Requests
import time
import requests
BASE_URL = "http://localhost:8000/api/v1"
TASK_ID = "a3f1c9e2-4d7b-48b5-9e6d-2b7c9fa5e3d1"
while True:
response = requests.get(f"{BASE_URL}/download/{TASK_ID}/status")
status = response.json()
print(f"[{status['status']}] {status['progress']}% – {status.get('current_track', 'N/A')}")
if status["status"] in ("completed", "failed"):
break
time.sleep(2)
Inspect Metadata Without Downloading
curl "http://localhost:8000/api/v1/inspect?spotify_url=https://open.spotify.com/track/2kd0T6zgABT8P0s2h9QU5O"
Response Structure:
{
"name": "Song Title",
"artists": ["Artist One", "Artist Two"],
"album_name": "Album Name",
"duration": 212,
"number": 1,
"uri": "spotify:track:2kd0T6zgABT8P0s2h9QU5O"
}
Cancel a Running Job
curl -X GET http://localhost:8000/api/v1/download/a3f1c9e2-4d7b-48b5-9e6d-2b7c9fa5e3d1/cancel
List All Tasks
curl http://localhost:8000/api/v1/downloads
Summary
- The SpotifySaver API exposes FastAPI-based REST endpoints under
/api/v1for programmatic control of Spotify downloads. - Entry point:
spotifysaver/api/main.pybootstraps the Uvicorn server, whilespotifysaver/api/app.pyconfigures CORS and mounts the download router. - Core router:
spotifysaver/api/routers/download.pyimplements six primary endpoints:POST /download,GET /download/{task_id}/status,GET /download/{task_id}/cancel,GET /downloads,GET /inspect, andGET /config/output_dir. - Data models:
spotifysaver/api/schemas.pydefines Pydantic schemas (DownloadRequest,DownloadResponse,DownloadStatus) that enforce type safety and auto-generate OpenAPI documentation at/docs. - Async processing: Downloads run as FastAPI
BackgroundTasksviaDownloadServiceinspotifysaver/api/services/download_service.py, allowing immediate HTTP responses while processing continues server-side.
Frequently Asked Questions
How do I authenticate requests to the SpotifySaver API?
The current implementation in gabrielbaute/spotify-saver does not enforce authentication or API keys on its REST endpoints. The API is designed for local or trusted network deployments where the FastAPI instance runs behind a firewall or reverse proxy. For production exposure, you should implement OAuth2, API key headers, or network-level authentication (VPN, IP whitelisting) as the underlying code does not provide built-in auth mechanisms.
What Spotify content types can I download through the API?
According to the start_download implementation in spotifysaver/api/routers/download.py, the API accepts Spotify URLs for individual tracks, full albums, and public playlists. The inspect_spotify_url endpoint returns distinct metadata schemas for each type (TrackInfo, AlbumInfo, PlaylistInfo in spotifysaver/api/schemas.py), confirming support for all three content categories.
How does the API handle concurrent download jobs?
The API leverages FastAPI's BackgroundTasks system to handle concurrency. When you POST to /api/v1/download, the start_download function immediately returns a task_id and delegates the heavy processing to DownloadService via background_tasks.add_task(). This allows the server to accept multiple simultaneous jobs; however, the current in-memory task registry in download_service.py is not persistent. For high-concurrency production use, you should replace the in-memory store with Redis or a database to prevent task loss on server restarts.
Can I retrieve metadata without downloading files?
Yes. The GET /api/v1/inspect endpoint, implemented in spotifysaver/api/routers/download.py as the inspect_spotify_url function, returns full metadata for any Spotify URL without triggering a download. It accepts a spotify_url query parameter and returns JSON structures defined in spotifysaver/api/schemas.py (TrackInfo, AlbumInfo, or PlaylistInfo), including track names, artist lists, album details, and Spotify URIs.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →