Files
metadata-agregator/docs/research/minim/analysis/INTEGRATIONS.md
T
Alexander a1f6701bac feat: initial implementation of metadata aggregator
- gRPC service with MusicBrainz provider
- PostgreSQL schema with migrations
- Service layer with database-first caching
- Repository pattern for data access
- YAML configuration support
- Research documentation for 17 music metadata projects
2026-04-28 16:28:53 +02:00

25 KiB

minim: Service Integrations

Overview

minim integrates with five music services, each with different authentication methods, API coverage, and capabilities:

Service Auth Method API Type Streaming Lyrics Credits Rate Limit
Discogs OAuth 1.0a, Personal Token Public No No Yes 60/min (auth), 25/min (unauth)
iTunes None Public No No No ~20/min
Qobuz Password Grant Private Yes No No Unknown
Spotify OAuth 2.0 (4 flows) Public + Private No Yes No 180/30sec
TIDAL OAuth 2.0 (PKCE, Client Creds) Public + Private Yes Yes Yes Unknown

Discogs Integration

Service Overview

Purpose: Music database, marketplace, collection management
Website: https://www.discogs.com
API Documentation: https://www.discogs.com/developers
API Type: Public, documented, RESTful

Authentication

Method 1: OAuth 1.0a

Setup:

  1. Create app at https://www.discogs.com/settings/developers
  2. Obtain consumer key and consumer secret
  3. Implement OAuth 1.0a flow (request token → user authorization → access token)

Implementation:

from minim import discogs

api = discogs.API(
    consumer_key="Abcd1234Efgh5678",
    consumer_secret="IjklMnopQrstUvwx"
)

# OAuth flow (opens browser)
api.set_access_token()

# Tokens saved to ~/minim.cfg

Method 2: Personal Access Token

Setup:

  1. Generate token at https://www.discogs.com/settings/developers
  2. Use token directly (no OAuth flow)

Implementation:

api = discogs.API(personal_access_token="YourPersonalToken")

Comparison:

  • OAuth 1.0a: Required for write operations (collection, wantlist), higher rate limit
  • Personal Token: Read-only, simpler setup, same rate limit as OAuth

API Coverage

Database:

  • Search releases, artists, labels, masters
  • Get detailed information (tracklist, credits, images, identifiers)
  • Browse by genre, style, format, year, country

Marketplace:

  • Search listings
  • Get listing details (price, condition, seller)
  • Not implemented in minim (read-only marketplace access)

Collection:

  • Get user's collection folders
  • List items in folder
  • Add/remove releases
  • Update notes and rating

Wantlist:

  • Get user's wantlist
  • Add/remove releases
  • Not implemented: Update notes

User:

  • Get user profile
  • Get user submissions (releases, artists, labels)
  • Not implemented in minim

Data Model

Release Object:

{
  "id": 249504,
  "title": "OK Computer",
  "artists": [{"name": "Radiohead", "id": 3840}],
  "labels": [{"name": "Parlophone", "catno": "7243 8 55229 2 5"}],
  "formats": [{"name": "CD", "qty": "1", "descriptions": ["Album"]}],
  "year": 1997,
  "country": "UK",
  "genres": ["Electronic", "Rock"],
  "styles": ["Alternative Rock", "Experimental"],
  "tracklist": [
    {"position": "1", "title": "Airbag", "duration": "4:44"},
    {"position": "2", "title": "Paranoid Android", "duration": "6:23"}
  ],
  "identifiers": [
    {"type": "Barcode", "value": "724385522925"}
  ],
  "images": [
    {"type": "primary", "uri": "https://...", "width": 600, "height": 600}
  ]
}

Artist Object:

{
  "id": 3840,
  "name": "Radiohead",
  "profile": "English rock band formed in 1985...",
  "members": [
    {"name": "Thom Yorke", "id": 239},
    {"name": "Jonny Greenwood", "id": 240}
  ],
  "urls": ["https://www.radiohead.com"],
  "images": [...]
}

Rate Limiting

Authenticated: 60 requests per minute
Unauthenticated: 25 requests per minute

Headers:

  • X-Discogs-Ratelimit: Total requests allowed per minute
  • X-Discogs-Ratelimit-Remaining: Requests remaining in current window
  • X-Discogs-Ratelimit-Used: Requests used in current window

Enforcement: HTTP 429 (Too Many Requests) when limit exceeded.

minim Implementation: Does not check rate limit headers. Caller responsible for tracking.

Use Cases

  1. Metadata Enrichment: Get detailed release information (catalog numbers, barcodes, formats)
  2. Collection Management: Sync local library with Discogs collection
  3. Credits Extraction: Get producer, engineer, musician credits from tracklist
  4. Format Identification: Determine pressing details (country, year, label, catalog number)

Limitations

  • No streaming or preview URLs
  • No lyrics
  • Marketplace write operations not implemented
  • User-submitted data (quality varies)
  • Rate limiting requires manual tracking

iTunes Integration

Service Overview

Purpose: Public music catalog search and lookup
Website: https://www.apple.com/itunes
API Documentation: https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/iTuneSearchAPI
API Type: Public, documented, RESTful

Authentication

None required. iTunes Search API is completely public.

Implementation:

from minim import itunes

api = itunes.SearchAPI()
results = api.search("Radiohead", media="music", entity="musicArtist")

API Coverage

Search:

  • Search by term across all media types
  • Filter by media (music, movie, podcast, audiobook, etc.)
  • Filter by entity (song, album, artist, etc.)
  • Filter by attribute (artist name, album name, song name, etc.)

Lookup:

  • Lookup by iTunes ID
  • Lookup by UPC (album barcode)
  • Lookup by ISBN (books)
  • Lookup by AMG (All Music Guide) ID

Not Available:

  • Streaming URLs
  • Lyrics
  • User library access
  • Playlist management

Data Model

Track Object:

{
  "trackId": 1109731797,
  "trackName": "Creep",
  "artistName": "Radiohead",
  "collectionName": "Pablo Honey",
  "collectionId": 1109731533,
  "artistId": 657515,
  "trackNumber": 2,
  "trackCount": 12,
  "discNumber": 1,
  "discCount": 1,
  "releaseDate": "1993-02-22T08:00:00Z",
  "primaryGenreName": "Alternative",
  "trackTimeMillis": 238640,
  "country": "USA",
  "isrc": "GBAYE9200070",
  "artworkUrl30": "https://.../30x30bb.jpg",
  "artworkUrl60": "https://.../60x60bb.jpg",
  "artworkUrl100": "https://.../100x100bb.jpg",
  "previewUrl": "https://.../preview.m4a",
  "trackViewUrl": "https://music.apple.com/us/album/creep/1109731533?i=1109731797"
}

Album Object:

{
  "collectionId": 1109731533,
  "collectionName": "Pablo Honey",
  "artistName": "Radiohead",
  "artistId": 657515,
  "trackCount": 12,
  "releaseDate": "1993-02-22T08:00:00Z",
  "primaryGenreName": "Alternative",
  "copyright": "℗ 1993 XL Recordings Ltd.",
  "country": "USA",
  "artworkUrl100": "https://.../100x100bb.jpg",
  "collectionViewUrl": "https://music.apple.com/us/album/pablo-honey/1109731533"
}

Rate Limiting

Limit: Approximately 20 requests per minute (undocumented)
Enforcement: HTTP 403 (Forbidden) when limit exceeded
Headers: No rate limit headers provided

Recommendation: Implement exponential backoff on 403 errors.

Use Cases

  1. Quick Metadata Lookup: Get basic track/album info without authentication
  2. UPC Lookup: Find albums by barcode
  3. Preview URLs: Get 30-second preview clips (M4A format)
  4. Artwork: Get album artwork in multiple sizes (30x30, 60x60, 100x100)

Limitations

  • No high-resolution artwork (max 100x100 pixels, can be scaled to 600x600 by changing URL)
  • No streaming URLs (only 30-second previews)
  • No lyrics
  • No user-specific data
  • Rate limit is undocumented and may change
  • Search results limited to 200 items

Qobuz Integration

Service Overview

Purpose: High-resolution music streaming and downloads
Website: https://www.qobuz.com
API Documentation: None (private API)
API Type: Private, undocumented, reverse-engineered

Authentication

Method: Password Grant OAuth 2.0

Setup:

  1. Qobuz account with active subscription
  2. App ID and secret auto-extracted from web player JavaScript
  3. Email and password for authentication

Implementation:

from minim import qobuz

api = qobuz.PrivateAPI(
    email="user@example.com",
    password="YourPassword"
)

# Automatic app_id/secret extraction and token acquisition
api.set_access_token()

App ID/Secret Extraction:

def _get_app_credentials(self):
    # Fetch Qobuz web player
    response = requests.get("https://play.qobuz.com")
    html = response.text
    
    # Extract bundle URL from HTML
    bundle_url_match = re.search(r'<script src="(/resources/\d+\.\d+\.\d+-[a-z]\d+/bundle\.js)"', html)
    bundle_url = "https://play.qobuz.com" + bundle_url_match.group(1)
    
    # Fetch bundle JavaScript
    bundle_js = requests.get(bundle_url).text
    
    # Extract app_id and secrets array
    app_id = re.search(r'production:{api:{appId:"(\d+)"', bundle_js).group(1)
    secrets = re.findall(r'[a-f0-9]{32}', bundle_js)
    
    # Test secrets to find valid one
    for secret in secrets:
        if self._test_secret(app_id, secret):
            return app_id, secret

Security Note: This method violates Qobuz terms of service. Use at your own risk.

API Coverage

Catalog:

  • Search tracks, albums, artists, playlists
  • Get detailed information
  • Browse by genre, new releases, charts

Streaming:

  • Get streaming URLs with quality selection
  • Quality levels: MP3 320kbps, FLAC 16/44.1, FLAC 24/96, FLAC Hi-Res (up to 24/192)
  • Download tracks (within subscription terms)

User Library:

  • Get user playlists
  • Create, update, delete playlists
  • Add/remove tracks from playlists
  • Get favorites (tracks, albums, artists)
  • Add/remove favorites

Not Available:

  • Lyrics
  • Credits (producer, engineer, etc.)
  • User playback history

Data Model

Track Object:

{
  "id": 12345678,
  "title": "Creep",
  "duration": 238,
  "track_number": 2,
  "media_number": 1,
  "isrc": "GBAYE9200070",
  "performer": {"name": "Radiohead", "id": 12345},
  "album": {
    "id": "0060254734729",
    "title": "Pablo Honey",
    "release_date_original": "1993-02-22",
    "upc": "0060254734729",
    "image": {
      "small": "https://.../230x230.jpg",
      "large": "https://.../600x600.jpg"
    },
    "label": {"name": "XL Recordings"}
  },
  "maximum_bit_depth": 16,
  "maximum_sampling_rate": 44.1
}

Streaming URL Response:

{
  "url": "https://streaming.qobuz.com/...",
  "format_id": 27,
  "mime_type": "audio/flac",
  "sampling_rate": 44.1,
  "bit_depth": 16,
  "restrictions": []
}

Quality Levels

Format ID Quality Codec Bitrate/Depth Subscription Tier
5 MP3 MP3 320 kbps Studio
6 CD FLAC 16-bit/44.1kHz Studio
7 Hi-Res FLAC 24-bit/96kHz Studio Sublime
27 Hi-Res FLAC Up to 24-bit/192kHz Studio Sublime

Availability: Quality depends on:

  1. User's subscription tier
  2. Album's available formats
  3. Geographic restrictions

Rate Limiting

Unknown. Private API does not document rate limits.

Observation: Aggressive usage (>100 requests/minute) may trigger temporary blocks.

Recommendation: Implement conservative rate limiting (10-20 requests/minute).

Use Cases

  1. High-Resolution Downloads: Get FLAC files up to 24-bit/192kHz
  2. Metadata Enrichment: Get detailed album info (label, UPC, release date)
  3. Playlist Management: Sync playlists between services
  4. Favorites Sync: Export/import favorite tracks

Limitations

  • Private API (may break without notice)
  • Requires active subscription
  • No lyrics or credits
  • Geographic restrictions on content
  • Terms of service violations (use at own risk)

Spotify Integration

Service Overview

Purpose: Music streaming, discovery, and social features
Website: https://www.spotify.com
API Documentation: https://developer.spotify.com/documentation/web-api
API Type: Public (Web API) + Private (Lyrics)

Authentication

Method: OAuth 2.0 with four flow types

Flow 1: Authorization Code

  • Full user access with refresh token
  • Requires user login via browser
  • Best for web applications

Flow 2: PKCE (Proof Key for Code Exchange)

  • For mobile and desktop apps
  • No client secret required
  • Enhanced security for public clients

Flow 3: Client Credentials

  • App-only access (no user context)
  • No user login required
  • Limited to catalog endpoints (no user library, playlists, playback)

Flow 4: Web Player (Undocumented)

  • Extract sp_dc cookie from browser
  • Access private endpoints (lyrics)
  • Violates terms of service

Implementation:

from minim import spotify

# Authorization Code flow
api = spotify.WebAPI(
    client_id="your_client_id",
    client_secret="your_client_secret",
    redirect_uri="http://localhost:8888"
)
api.set_flow("authorization_code", scopes=[
    "user-library-read",
    "playlist-read-private",
    "user-read-playback-state"
])
api.set_access_token()  # Opens browser

# Client Credentials flow (no user login)
api = spotify.WebAPI(client_id="...", client_secret="...")
api.set_flow("client_credentials")
api.set_access_token()

API Coverage

Catalog:

  • Search tracks, albums, artists, playlists, shows, episodes
  • Get detailed information
  • Get related artists
  • Get artist top tracks
  • Get album tracks
  • Get audio features (danceability, energy, tempo, etc.)
  • Get audio analysis (detailed beat/bar/section analysis)

User Library:

  • Get saved tracks, albums, shows, episodes
  • Save/remove items
  • Check if items are saved

Playlists:

  • Get user playlists
  • Get playlist details and tracks
  • Create, update, delete playlists
  • Add/remove tracks
  • Reorder tracks
  • Upload custom cover image

Playback:

  • Get current playback state
  • Get available devices
  • Start/pause/skip playback
  • Seek to position
  • Set volume
  • Toggle shuffle/repeat
  • Transfer playback between devices

Personalization:

  • Get top artists and tracks
  • Get recently played tracks
  • Get recommendations based on seeds

Follow:

  • Follow/unfollow artists, users, playlists
  • Check if following
  • Get followed artists

Browse:

  • Get featured playlists
  • Get new releases
  • Get categories
  • Get category playlists

Lyrics (Private API):

  • Get synchronized lyrics via Musixmatch integration
  • Requires sp_dc cookie

Data Model

Track Object:

{
  "id": "3n3Ppam7vgaVa1iaRUc9Lp",
  "name": "Creep",
  "artists": [
    {"name": "Radiohead", "id": "4Z8W4fKeB5YxbusRsdQVPb"}
  ],
  "album": {
    "name": "Pablo Honey",
    "id": "6AZv3m27uyRxi8KyJSfUxL",
    "release_date": "1993-02-22",
    "images": [
      {"url": "https://.../640x640.jpg", "width": 640, "height": 640}
    ]
  },
  "duration_ms": 238640,
  "track_number": 2,
  "disc_number": 1,
  "explicit": false,
  "external_ids": {"isrc": "GBAYE9200070"},
  "popularity": 82,
  "preview_url": "https://.../preview.mp3"
}

Audio Features Object:

{
  "id": "3n3Ppam7vgaVa1iaRUc9Lp",
  "danceability": 0.456,
  "energy": 0.789,
  "key": 7,
  "loudness": -6.234,
  "mode": 1,
  "speechiness": 0.034,
  "acousticness": 0.123,
  "instrumentalness": 0.000012,
  "liveness": 0.089,
  "valence": 0.234,
  "tempo": 92.456,
  "duration_ms": 238640,
  "time_signature": 4
}

Lyrics Object (Private API):

{
  "lyrics": {
    "syncType": "LINE_SYNCED",
    "lines": [
      {"startTimeMs": "0", "words": "When you were here before", "syllables": []},
      {"startTimeMs": "5230", "words": "Couldn't look you in the eye", "syllables": []}
    ],
    "language": "en"
  }
}

Scopes

Spotify uses OAuth scopes to control API access. Common scopes:

Library:

  • user-library-read: Read saved tracks/albums
  • user-library-modify: Save/remove tracks/albums

Playlists:

  • playlist-read-private: Read private playlists
  • playlist-read-collaborative: Read collaborative playlists
  • playlist-modify-public: Modify public playlists
  • playlist-modify-private: Modify private playlists

Playback:

  • user-read-playback-state: Read playback state
  • user-modify-playback-state: Control playback
  • user-read-currently-playing: Read currently playing track

Personalization:

  • user-top-read: Read top artists and tracks
  • user-read-recently-played: Read recently played tracks

Follow:

  • user-follow-read: Read followed artists/users
  • user-follow-modify: Follow/unfollow artists/users

User:

  • user-read-private: Read user profile (country, product)
  • user-read-email: Read user email

Rate Limiting

Limit: Varies by endpoint, typically 180 requests per 30 seconds
Enforcement: HTTP 429 (Too Many Requests)
Headers:

  • Retry-After: Seconds to wait before retrying

Recommendation: Implement exponential backoff and respect Retry-After header.

Use Cases

  1. Comprehensive Metadata: Get detailed track info, audio features, related artists
  2. Playlist Management: Create, sync, and manage playlists
  3. Playback Control: Build custom music players
  4. Music Discovery: Get recommendations, browse new releases
  5. Lyrics Integration: Display synchronized lyrics (via private API)

Limitations

  • No streaming URLs (only 30-second previews)
  • No download capability
  • Lyrics require private API (terms of service violation)
  • Rate limiting varies by endpoint
  • Some features require premium subscription

TIDAL Integration

Service Overview

Purpose: High-fidelity music streaming with MQA support
Website: https://www.tidal.com
API Documentation: Limited (mostly undocumented)
API Type: Public (limited) + Private (extensive)

Authentication

Method: OAuth 2.0 (PKCE or Client Credentials)

Public API:

  • Client credentials flow
  • Limited endpoints (catalog search, basic info)

Private API:

  • PKCE flow with user login
  • Full access (streaming URLs, lyrics, credits)

Implementation:

from minim import tidal

# Private API (full access)
api = tidal.PrivateAPI(
    client_id="your_client_id",
    client_secret="your_client_secret"
)
api.set_flow("pkce")
api.set_access_token()  # Opens browser for login

Client ID/Secret:

  • Extracted from TIDAL desktop/mobile apps
  • Not officially provided by TIDAL
  • Use at own risk (terms of service violation)

API Coverage

Catalog:

  • Search tracks, albums, artists, playlists, videos
  • Get detailed information
  • Get artist top tracks and albums
  • Get similar artists
  • Get album review and credits

Streaming:

  • Get streaming URLs with quality selection
  • Quality levels: LOW (96kbps AAC), HIGH (320kbps AAC), LOSSLESS (FLAC 16/44.1), HI_RES (FLAC 24/96+), HI_RES_LOSSLESS (MQA)
  • Manifest decryption for protected streams

Lyrics:

  • Get synchronized lyrics (LRC format)
  • Get plain text lyrics

Credits:

  • Get detailed credits (producers, engineers, musicians, composers, etc.)
  • Role-based organization

User Library:

  • Get user playlists
  • Create, update, delete playlists
  • Add/remove tracks
  • Get favorites (tracks, albums, artists, videos)
  • Add/remove favorites

Not Available:

  • Playback control (no remote control API)
  • Audio features/analysis
  • Recommendations (limited)

Data Model

Track Object:

{
  "id": 12345678,
  "title": "Creep",
  "duration": 238,
  "trackNumber": 2,
  "volumeNumber": 1,
  "isrc": "GBAYE9200070",
  "explicit": false,
  "audioQuality": "HI_RES",
  "artists": [
    {"name": "Radiohead", "id": 4050}
  ],
  "album": {
    "id": 1234567,
    "title": "Pablo Honey",
    "releaseDate": "1993-02-22",
    "cover": "01234567-89ab-cdef-0123-456789abcdef",
    "upc": "0060254734729",
    "numberOfTracks": 12,
    "audioQuality": "HI_RES"
  },
  "streamStartDate": "1993-02-22T00:00:00.000Z"
}

Streaming Manifest:

{
  "mimeType": "audio/flac",
  "codecs": "flac",
  "encryptionType": "NONE",
  "urls": ["https://streaming.tidal.com/..."],
  "soundQuality": "HI_RES",
  "bitDepth": 24,
  "sampleRate": 96000
}

Lyrics Object:

{
  "trackId": 12345678,
  "lyricsProvider": "Musixmatch",
  "providerLyricsId": "12345",
  "lyrics": "When you were here before\nCouldn't look you in the eye...",
  "subtitles": "[00:00.00] When you were here before\n[00:05.23] Couldn't look you in the eye..."
}

Credits Object:

{
  "credits": [
    {
      "type": "Producers",
      "contributors": [
        {"name": "Sean Slade", "id": 12345},
        {"name": "Paul Q. Kolderie", "id": 67890}
      ]
    },
    {
      "type": "Performers",
      "contributors": [
        {"name": "Thom Yorke", "id": 111, "role": "Vocals"},
        {"name": "Jonny Greenwood", "id": 222, "role": "Guitar"}
      ]
    }
  ]
}

Quality Levels

Quality Codec Bitrate/Depth Subscription Tier
LOW AAC 96 kbps Free (trial)
HIGH AAC 320 kbps HiFi
LOSSLESS FLAC 16-bit/44.1kHz HiFi
HI_RES FLAC 24-bit/96kHz+ HiFi Plus
HI_RES_LOSSLESS MQA 24-bit/96kHz+ (MQA) HiFi Plus

MQA (Master Quality Authenticated):

  • Proprietary format by Meridian Audio
  • Requires MQA-compatible DAC for full unfolding
  • Software decoding provides 24-bit/96kHz

Manifest Decryption

Some streaming URLs are encrypted. minim handles decryption:

def _decrypt_manifest(self, manifest: dict) -> str:
    from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
    from cryptography.hazmat.backends import default_backend
    import base64
    
    # Extract encrypted URL
    encrypted_url = manifest["urls"][0]
    
    # Decrypt using AES-128-CTR
    key = base64.b64decode(manifest["encryptionKey"])
    nonce = base64.b64decode(manifest["nonce"])
    
    cipher = Cipher(
        algorithms.AES(key),
        modes.CTR(nonce),
        backend=default_backend()
    )
    decryptor = cipher.decryptor()
    
    decrypted = decryptor.update(base64.b64decode(encrypted_url)) + decryptor.finalize()
    return decrypted.decode("utf-8")

Rate Limiting

Unknown. Private API does not document rate limits.

Observation: Moderate usage (<50 requests/minute) appears safe.

Recommendation: Implement conservative rate limiting and exponential backoff on errors.

Use Cases

  1. High-Fidelity Streaming: Get FLAC files up to 24-bit/192kHz and MQA
  2. Comprehensive Credits: Get detailed production credits
  3. Synchronized Lyrics: Display time-synced lyrics
  4. Metadata Enrichment: Get authoritative release dates, ISRCs, UPCs
  5. Playlist Management: Sync playlists between services

Limitations

  • Private API (may break without notice)
  • Requires active subscription (HiFi or HiFi Plus for lossless)
  • Client ID/secret extraction violates terms of service
  • No playback control API
  • No audio features/analysis
  • Geographic restrictions on content

Integration Comparison

Authentication Complexity

Simplest: iTunes (no auth)
Simple: Discogs (personal token), Spotify (client credentials)
Moderate: Spotify (authorization code), TIDAL (PKCE)
Complex: Qobuz (app_id extraction + password grant)

API Documentation Quality

Best: Spotify (comprehensive, well-maintained)
Good: Discogs, iTunes
Poor: TIDAL (limited public docs)
None: Qobuz (fully reverse-engineered)

Streaming Capability

High-Resolution: Qobuz (up to 24/192 FLAC), TIDAL (up to 24/192 FLAC + MQA)
Lossless: TIDAL (16/44.1 FLAC)
Lossy: TIDAL (AAC), Qobuz (MP3)
Preview Only: Spotify (30sec MP3), iTunes (30sec M4A)
None: Discogs

Metadata Richness

Credits: TIDAL (excellent), Discogs (good), others (none)
Lyrics: TIDAL (synced), Spotify (synced, private API), others (none)
Audio Features: Spotify (excellent), others (none)
Catalog Info: All services (good)

Terms of Service Compliance

Compliant: Discogs (public API), iTunes (public API), Spotify (public Web API)
Questionable: Spotify (private lyrics API)
Violation: Qobuz (app_id extraction, private API), TIDAL (client_id extraction, private API)

Summary

minim provides comprehensive integration with five music services, each serving different use cases:

  • Discogs: Best for credits, catalog numbers, and collection management
  • iTunes: Best for quick, unauthenticated metadata lookup
  • Qobuz: Best for high-resolution downloads (within subscription terms)
  • Spotify: Best for comprehensive metadata, audio features, and playlist management
  • TIDAL: Best for high-fidelity streaming, credits, and synchronized lyrics

All integrations follow consistent patterns (authentication, request handling, error raising) while exposing service-specific features. The private API usage (Qobuz, Spotify lyrics, TIDAL) provides powerful capabilities but carries legal and stability risks.

For a metadata aggregator project, prioritize public APIs (Spotify Web API, Discogs, iTunes) for production use, and use private APIs only for research or personal projects.