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, including spotify_url, output_format, bit_rate, output_dir, and boolean flags for lyrics and cover art.
  • DownloadResponse – Returned upon job creation, containing task_id, status, content_type, and a human-readable message.
  • DownloadStatus – Polling payload with progress percentage, current_track, and detailed status fields.
  • TrackInfo, AlbumInfo, PlaylistInfo – Metadata structures returned by the /inspect endpoint.

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/v1 for programmatic control of Spotify downloads.
  • Entry point: spotifysaver/api/main.py bootstraps the Uvicorn server, while spotifysaver/api/app.py configures CORS and mounts the download router.
  • Core router: spotifysaver/api/routers/download.py implements six primary endpoints: POST /download, GET /download/{task_id}/status, GET /download/{task_id}/cancel, GET /downloads, GET /inspect, and GET /config/output_dir.
  • Data models: spotifysaver/api/schemas.py defines Pydantic schemas (DownloadRequest, DownloadResponse, DownloadStatus) that enforce type safety and auto-generate OpenAPI documentation at /docs.
  • Async processing: Downloads run as FastAPI BackgroundTasks via DownloadService in spotifysaver/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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →