Files
metadata-agregator/docs/research/lidarr-metadata-api/analysis/API.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

27 KiB

Lidarr Metadata API - API Reference

Base URL and Versioning

Production deployment:

  • Stable: https://api.lidarr.audio/api/v0.3
  • Testing: https://api.lidarr.audio/api/testing

Local development:

  • Default: http://localhost:5001
  • Configurable via APPLICATION_ROOT environment variable

Version strategy: Dual deployment with stable (v0.3) and testing versions running simultaneously.

Authentication

Read endpoints: No authentication required (public access)

Write endpoints: API key authentication via header

POST /invalidate HTTP/1.1
X-Api-Key: your-api-key-here

Configuration:

export INVALIDATE_APIKEY=your-secure-key

Default: replaceme (insecure, must change in production)

Response Format

All endpoints return JSON with consistent structure.

Common Response Headers

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: s-maxage=2592000, max-age=0
X-Application-Version: 10.0.0.0

Cache-Control explanation:

  • s-maxage=2592000: CDN can cache for 30 days
  • max-age=0: Clients must revalidate (always check CDN/origin)

Error Response Format

{
  "error": "Artist not found",
  "status": 404,
  "mbid": "invalid-mbid-format"
}

HTTP status codes:

  • 200: Success
  • 400: Bad request (invalid parameters)
  • 401: Unauthorized (missing/invalid API key)
  • 404: Resource not found
  • 429: Rate limit exceeded
  • 500: Internal server error
  • 503: Service unavailable (database/cache down)

Health and Version Endpoints

GET /

Purpose: Health check and version information

Parameters: None

Response:

{
  "version": "10.0.0.0",
  "status": "healthy",
  "timestamp": "2025-04-28T12:34:56Z"
}

Cache: No caching

Use case: Load balancer health checks, monitoring

Artist Endpoints

GET /artist/{mbid}

Purpose: Retrieve complete artist metadata with releases

Parameters:

Parameter Type Required Default Description
mbid UUID Yes - MusicBrainz artist ID
primTypes String No All Primary release types (comma-separated)
secTypes String No All Secondary release types (comma-separated)
releaseStatuses String No All Release statuses (comma-separated)

Primary release types:

  • Album: Studio albums
  • Single: Singles
  • EP: Extended plays
  • Broadcast: Radio/TV broadcasts
  • Other: Miscellaneous

Secondary release types:

  • Compilation: Compilation albums
  • Soundtrack: Movie/game soundtracks
  • Spokenword: Audiobooks, poetry
  • Interview: Interview recordings
  • Audiobook: Audiobooks
  • Live: Live recordings
  • Remix: Remix albums
  • DJ-mix: DJ mix albums
  • Mixtape/Street: Mixtapes

Release statuses:

  • Official: Official releases
  • Promotion: Promotional releases
  • Bootleg: Bootleg recordings
  • Pseudo-Release: Pseudo-releases

Example request:

GET /artist/5b11f4ce-a62d-471e-81fc-a69a8278c7da?primTypes=Album,Single&releaseStatuses=Official HTTP/1.1

Response:

{
  "Id": "5b11f4ce-a62d-471e-81fc-a69a8278c7da",
  "OldIds": [],
  "ArtistName": "Nirvana",
  "SortName": "Nirvana",
  "Disambiguation": "90s US grunge band",
  "Overview": "Nirvana was an American rock band formed in Aberdeen, Washington, in 1987...",
  "Type": "Group",
  "Status": "Ended",
  "Gender": null,
  "Hometown": "Aberdeen, WA, United States",
  "StartYear": 1987,
  "EndYear": 1994,
  "ArtistAliases": [
    {
      "Name": "ニルヴァーナ",
      "SortName": "ニルヴァーナ",
      "Locale": "ja",
      "Primary": true
    }
  ],
  "Links": [
    {
      "Url": "https://www.spotify.com/artist/6olE6TJLqED3rqDCT0FyPh",
      "Name": "spotify"
    },
    {
      "Url": "https://www.allmusic.com/artist/mn0000352188",
      "Name": "allmusic"
    },
    {
      "Url": "https://www.discogs.com/artist/65450",
      "Name": "discogs"
    },
    {
      "Url": "https://en.wikipedia.org/wiki/Nirvana_(band)",
      "Name": "wikipedia"
    }
  ],
  "Images": [
    {
      "Url": "https://imagecache.lidarr.audio/fanart/artist/5b11f4ce-a62d-471e-81fc-a69a8278c7da/poster.jpg",
      "CoverType": "poster",
      "Extension": ".jpg"
    },
    {
      "Url": "https://imagecache.lidarr.audio/fanart/artist/5b11f4ce-a62d-471e-81fc-a69a8278c7da/banner.jpg",
      "CoverType": "banner",
      "Extension": ".jpg"
    },
    {
      "Url": "https://imagecache.lidarr.audio/fanart/artist/5b11f4ce-a62d-471e-81fc-a69a8278c7da/logo.png",
      "CoverType": "logo",
      "Extension": ".png"
    },
    {
      "Url": "https://imagecache.lidarr.audio/fanart/artist/5b11f4ce-a62d-471e-81fc-a69a8278c7da/fanart.jpg",
      "CoverType": "fanart",
      "Extension": ".jpg"
    }
  ],
  "Genres": [
    "Grunge",
    "Alternative Rock",
    "Punk Rock"
  ],
  "Rating": {
    "Votes": 42,
    "Value": 4.8
  },
  "Albums": [
    {
      "Id": "1b022e01-4da6-387b-8658-8678046e4cef",
      "Title": "Nevermind",
      "Disambiguation": "",
      "ReleaseDate": "1991-09-24",
      "Type": "Album",
      "SecondaryTypes": [],
      "Status": "Official",
      "Genres": ["Grunge", "Alternative Rock"],
      "Rating": {
        "Votes": 156,
        "Value": 4.9
      },
      "Images": [
        {
          "Url": "https://imagecache.lidarr.audio/cover/1b022e01-4da6-387b-8658-8678046e4cef/front.jpg",
          "CoverType": "cover",
          "Extension": ".jpg"
        }
      ]
    }
  ]
}

Response fields:

Field Type Description
Id UUID MusicBrainz artist ID
OldIds Array Historical MusicBrainz IDs (after merges)
ArtistName String Primary artist name
SortName String Name for alphabetical sorting
Disambiguation String Disambiguation comment
Overview String Artist biography (from Wikipedia)
Type String Artist type (Person, Group, Orchestra, etc.)
Status String Artist status (Active, Ended, etc.)
Gender String Gender (for Person type)
Hometown String Origin location
StartYear Integer Formation/birth year
EndYear Integer Dissolution/death year
ArtistAliases Array Alternative names and translations
Links Array External links (Spotify, AllMusic, Discogs, etc.)
Images Array Artist images (poster, banner, logo, fanart)
Genres Array Genre tags
Rating Object Community rating (votes and value)
Albums Array Release groups (filtered by parameters)

Cache behavior:

  • Cache key: artist:{mbid}:{primTypes}:{secTypes}:{releaseStatuses}
  • TTL: 30 days (2592000 seconds)
  • Invalidation: Manual via /artist/{mbid}/refresh or automatic via crawler

Performance:

  • Cold request: 2-5 seconds (MusicBrainz DB + external APIs)
  • Cached request: 50-200ms (Redis/PostgreSQL)
  • CDN request: 10-50ms (Cloudflare edge)

POST /artist/{mbid}/refresh

Purpose: Invalidate cache and force fresh metadata fetch

Authentication: Required (API key)

Parameters:

Parameter Type Required Description
mbid UUID Yes MusicBrainz artist ID

Request:

POST /artist/5b11f4ce-a62d-471e-81fc-a69a8278c7da/refresh HTTP/1.1
X-Api-Key: your-api-key-here

Response:

{
  "status": "success",
  "mbid": "5b11f4ce-a62d-471e-81fc-a69a8278c7da",
  "invalidated": [
    "redis:artist:5b11f4ce-a62d-471e-81fc-a69a8278c7da",
    "postgres:artist:5b11f4ce-a62d-471e-81fc-a69a8278c7da",
    "cdn:https://api.lidarr.audio/api/v0.3/artist/5b11f4ce-a62d-471e-81fc-a69a8278c7da"
  ]
}

Cache invalidation:

  1. Delete from Redis cache
  2. Delete from PostgreSQL cache
  3. Purge from Cloudflare CDN
  4. Next request will fetch fresh data

Use cases:

  • Artist metadata updated in MusicBrainz
  • New images added to FanArt.tv
  • Wikipedia article updated
  • Manual cache refresh

GET /recent/artist

Purpose: List recently updated artists

Parameters:

Parameter Type Required Default Description
limit Integer No 50 Maximum number of results
since ISO 8601 No 24h ago Only artists updated after this timestamp

Example request:

GET /recent/artist?limit=10&since=2025-04-27T00:00:00Z HTTP/1.1

Response:

{
  "artists": [
    {
      "Id": "5b11f4ce-a62d-471e-81fc-a69a8278c7da",
      "ArtistName": "Nirvana",
      "LastUpdated": "2025-04-28T10:30:00Z",
      "ChangeType": "metadata"
    },
    {
      "Id": "83d91898-7763-47d7-b03b-b92132375c47",
      "ArtistName": "Pink Floyd",
      "LastUpdated": "2025-04-28T09:15:00Z",
      "ChangeType": "new_release"
    }
  ],
  "total": 2,
  "limit": 10,
  "since": "2025-04-27T00:00:00Z"
}

Change types:

  • metadata: Artist metadata updated
  • new_release: New release added
  • updated_release: Existing release updated
  • new_link: New external link added
  • cover_art: Cover art updated

Cache: 1 hour TTL

Use case: Crawler scheduling, monitoring MusicBrainz updates

Album Endpoints

GET /album/{mbid}

Purpose: Retrieve complete album metadata with tracks

Parameters:

Parameter Type Required Description
mbid UUID Yes MusicBrainz release group ID

Example request:

GET /album/1b022e01-4da6-387b-8658-8678046e4cef HTTP/1.1

Response:

{
  "Id": "1b022e01-4da6-387b-8658-8678046e4cef",
  "OldIds": [],
  "Title": "Nevermind",
  "Disambiguation": "",
  "Overview": "Nevermind is the second studio album by American rock band Nirvana...",
  "ReleaseDate": "1991-09-24",
  "Type": "Album",
  "SecondaryTypes": [],
  "Status": "Official",
  "Artist": {
    "Id": "5b11f4ce-a62d-471e-81fc-a69a8278c7da",
    "ArtistName": "Nirvana"
  },
  "Links": [
    {
      "Url": "https://www.spotify.com/album/2guirTSEqLizK7j9i1MTTZ",
      "Name": "spotify"
    },
    {
      "Url": "https://www.allmusic.com/album/mw0000083881",
      "Name": "allmusic"
    }
  ],
  "Images": [
    {
      "Url": "https://imagecache.lidarr.audio/cover/1b022e01-4da6-387b-8658-8678046e4cef/front.jpg",
      "CoverType": "cover",
      "Extension": ".jpg"
    },
    {
      "Url": "https://imagecache.lidarr.audio/cover/1b022e01-4da6-387b-8658-8678046e4cef/back.jpg",
      "CoverType": "disc",
      "Extension": ".jpg"
    }
  ],
  "Genres": ["Grunge", "Alternative Rock"],
  "Rating": {
    "Votes": 156,
    "Value": 4.9
  },
  "Media": [
    {
      "Position": 1,
      "Format": "CD",
      "Tracks": [
        {
          "Position": 1,
          "Title": "Smells Like Teen Spirit",
          "Duration": 301000,
          "ArtistName": "Nirvana"
        },
        {
          "Position": 2,
          "Title": "In Bloom",
          "Duration": 254000,
          "ArtistName": "Nirvana"
        }
      ]
    }
  ]
}

Response fields:

Field Type Description
Id UUID MusicBrainz release group ID
OldIds Array Historical IDs (after merges)
Title String Album title
Disambiguation String Disambiguation comment
Overview String Album description (from Wikipedia)
ReleaseDate ISO 8601 Original release date
Type String Primary type (Album, Single, EP, etc.)
SecondaryTypes Array Secondary types (Compilation, Live, etc.)
Status String Release status (Official, Promotion, etc.)
Artist Object Artist information
Links Array External links
Images Array Cover art images
Genres Array Genre tags
Rating Object Community rating
Media Array Physical/digital media with track listings

Cache behavior:

  • Cache key: album:{mbid}
  • TTL: 30 days
  • Invalidation: Manual or automatic

POST /album/{mbid}/refresh

Purpose: Invalidate album cache

Authentication: Required (API key)

Parameters: Same as artist refresh

Response: Same structure as artist refresh

GET /recent/album

Purpose: List recently updated albums

Parameters: Same as /recent/artist

Response: Similar structure with album-specific fields

Search Endpoints

GET /search/artist

Purpose: Search for artists by name

Parameters:

Parameter Type Required Default Description
query String Yes - Search query
limit Integer No 10 Maximum results

Example request:

GET /search/artist?query=nirvana&limit=5 HTTP/1.1

Response:

{
  "results": [
    {
      "Id": "5b11f4ce-a62d-471e-81fc-a69a8278c7da",
      "ArtistName": "Nirvana",
      "Disambiguation": "90s US grunge band",
      "Type": "Group",
      "Score": 100,
      "Images": [
        {
          "Url": "https://imagecache.lidarr.audio/fanart/artist/5b11f4ce-a62d-471e-81fc-a69a8278c7da/poster.jpg",
          "CoverType": "poster",
          "Extension": ".jpg"
        }
      ]
    },
    {
      "Id": "9282c8b4-ca0b-4c6b-b7e3-4f7762dfc4d6",
      "ArtistName": "Nirvana",
      "Disambiguation": "60s UK psychedelic band",
      "Type": "Group",
      "Score": 95,
      "Images": []
    }
  ],
  "total": 2,
  "query": "nirvana",
  "limit": 5
}

Search algorithm:

  1. Query Solr artist core with dismax parser
  2. Boost fields: artist^2 sortname alias
  3. Minimum match: 1 term
  4. Sort by relevance score
  5. Enrich results with cached metadata

Cache:

  • Cache key: search:artist:{query}:{limit}
  • TTL: 1 hour

Performance:

  • Cold request: 500ms-1s (Solr query + metadata enrichment)
  • Cached request: 50-100ms

GET /search/album

Purpose: Search for albums by title

Parameters: Same as artist search

Response: Similar structure with album-specific fields

Search algorithm: Same as artist search, using release-group Solr core

GET /search/all

Purpose: Combined artist and album search

Parameters:

Parameter Type Required Default Description
query String Yes - Search query
artistLimit Integer No 5 Max artist results
albumLimit Integer No 5 Max album results

Response:

{
  "artists": [...],
  "albums": [...],
  "query": "nevermind",
  "artistLimit": 5,
  "albumLimit": 5
}

Use case: Unified search UI, autocomplete

POST /search/fingerprint

Purpose: Acoustic fingerprint search (AcoustID integration)

Parameters:

Parameter Type Required Description
fingerprint String Yes Chromaprint fingerprint
duration Integer Yes Track duration in seconds

Request:

POST /search/fingerprint HTTP/1.1
Content-Type: application/json

{
  "fingerprint": "AQADtNGSJE...",
  "duration": 301
}

Response:

{
  "results": [
    {
      "Id": "5b11f4ce-a62d-471e-81fc-a69a8278c7da",
      "ArtistName": "Nirvana",
      "AlbumTitle": "Nevermind",
      "TrackTitle": "Smells Like Teen Spirit",
      "Score": 0.98,
      "Duration": 301
    }
  ]
}

Use case: Audio file identification, automatic tagging

Spotify Integration Endpoints

GET /spotify/artist/{id}

Purpose: Get artist metadata by Spotify ID

Parameters:

Parameter Type Required Description
id String Yes Spotify artist ID

Example request:

GET /spotify/artist/6olE6TJLqED3rqDCT0FyPh HTTP/1.1

Response: Same structure as /artist/{mbid} with MusicBrainz mapping

Mapping algorithm:

  1. Query Spotify API for artist metadata
  2. Search MusicBrainz by artist name
  3. Calculate Levenshtein distance (threshold: 0.8)
  4. Return best match with MusicBrainz ID

GET /spotify/album/{id}

Purpose: Get album metadata by Spotify ID

Parameters: Same as artist endpoint

Response: Same structure as /album/{mbid} with MusicBrainz mapping

POST /spotify/lookup

Purpose: Batch Spotify ID to MusicBrainz ID mapping

Request:

POST /spotify/lookup HTTP/1.1
Content-Type: application/json

{
  "artists": ["6olE6TJLqED3rqDCT0FyPh", "0k17h0D3J5VfsdmQ1iZtE9"],
  "albums": ["2guirTSEqLizK7j9i1MTTZ"]
}

Response:

{
  "artists": {
    "6olE6TJLqED3rqDCT0FyPh": "5b11f4ce-a62d-471e-81fc-a69a8278c7da",
    "0k17h0D3J5VfsdmQ1iZtE9": "83d91898-7763-47d7-b03b-b92132375c47"
  },
  "albums": {
    "2guirTSEqLizK7j9i1MTTZ": "1b022e01-4da6-387b-8658-8678046e4cef"
  }
}

Cache: 90 days TTL (Spotify IDs rarely change)

GET /spotify/auth

Purpose: Get Spotify OAuth authorization URL

Response:

{
  "auth_url": "https://accounts.spotify.com/authorize?client_id=...&response_type=code&redirect_uri=..."
}

Use case: User authentication for Spotify features

GET /spotify/renew

Purpose: Refresh Spotify OAuth token

Parameters:

Parameter Type Required Description
refresh_token String Yes Spotify refresh token

Response:

{
  "access_token": "BQD...",
  "expires_in": 3600
}

Chart Endpoints

GET /chart/{name}/{type}/{selection}

Purpose: Get music charts from various sources

Parameters:

Parameter Type Required Values Description
name String Yes apple-music, billboard, itunes, lastfm Chart source
type String Yes artist, album, track Chart type
selection String Yes Source-specific Chart category

Chart sources and selections:

Apple Music

Selections:

  • top-albums: Top 100 albums
  • new-releases: New album releases
  • top-songs: Top 100 songs

Example:

GET /chart/apple-music/album/top-albums HTTP/1.1

Billboard

Selections:

  • hot-100: Billboard Hot 100
  • billboard-200: Billboard 200 albums
  • artist-100: Top artists
  • streaming-songs: Top streaming songs

Example:

GET /chart/billboard/track/hot-100 HTTP/1.1

iTunes

Selections:

  • top-albums: iTunes top albums
  • top-songs: iTunes top songs

Example:

GET /chart/itunes/album/top-albums HTTP/1.1

Last.fm

Selections:

  • top-artists: Most scrobbled artists
  • top-albums: Most scrobbled albums
  • top-tracks: Most scrobbled tracks

Example:

GET /chart/lastfm/artist/top-artists HTTP/1.1

Response:

{
  "chart": "billboard",
  "type": "track",
  "selection": "hot-100",
  "date": "2025-04-28",
  "entries": [
    {
      "position": 1,
      "previousPosition": 2,
      "peakPosition": 1,
      "weeksOnChart": 12,
      "artist": {
        "Id": "5b11f4ce-a62d-471e-81fc-a69a8278c7da",
        "ArtistName": "Nirvana"
      },
      "album": {
        "Id": "1b022e01-4da6-387b-8658-8678046e4cef",
        "Title": "Nevermind"
      },
      "track": {
        "Title": "Smells Like Teen Spirit",
        "Duration": 301000
      }
    }
  ]
}

Cache: 6 hours TTL (charts update daily)

MusicBrainz mapping: Chart entries are automatically mapped to MusicBrainz IDs when possible

Series Endpoints

GET /series/{mbid}

Purpose: Get series metadata (box sets, compilations)

Parameters:

Parameter Type Required Description
mbid UUID Yes MusicBrainz series ID

Response:

{
  "Id": "series-mbid",
  "Name": "The Beatles Remastered Series",
  "Type": "Release group series",
  "Albums": [
    {
      "Id": "album-mbid-1",
      "Title": "Please Please Me",
      "Position": 1
    },
    {
      "Id": "album-mbid-2",
      "Title": "With the Beatles",
      "Position": 2
    }
  ]
}

Use case: Box set tracking, series completion

Cache Management Endpoints

POST /invalidate

Purpose: Batch cache invalidation

Authentication: Required (API key)

Request:

POST /invalidate HTTP/1.1
X-Api-Key: your-api-key-here
Content-Type: application/json

{
  "artists": [
    "5b11f4ce-a62d-471e-81fc-a69a8278c7da",
    "83d91898-7763-47d7-b03b-b92132375c47"
  ],
  "albums": [
    "1b022e01-4da6-387b-8658-8678046e4cef"
  ]
}

Response:

{
  "status": "success",
  "invalidated": {
    "artists": 2,
    "albums": 1,
    "total_keys": 6
  }
}

Invalidation scope:

  • Redis cache
  • PostgreSQL cache
  • Cloudflare CDN cache

Use case: Bulk cache refresh after MusicBrainz updates

Rate Limiting

Default: No rate limiting (NullRateLimiter)

Optional: Redis-based distributed rate limiting

Configuration:

RATE_LIMITER = 'redis'
RATE_LIMIT_REQUESTS = 100
RATE_LIMIT_WINDOW = 60  # seconds

Rate limit response:

HTTP/1.1 429 Too Many Requests
Retry-After: 30

{
  "error": "Rate limit exceeded",
  "limit": 100,
  "window": 60,
  "retry_after": 30
}

CORS Support

Default: CORS enabled for all origins

Headers:

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: Content-Type, X-Api-Key

Configuration:

CORS_ORIGINS = ['https://lidarr.audio', 'https://app.lidarr.audio']

Pagination

Not implemented: All endpoints return complete result sets

Workaround: Use limit parameter on search and recent endpoints

Future consideration: Cursor-based pagination for large result sets

Filtering and Sorting

Artist endpoint:

  • Filter by release type: primTypes, secTypes
  • Filter by release status: releaseStatuses
  • Sort: Albums sorted by release date (descending)

Search endpoints:

  • Sort: Relevance score (descending)
  • Filter: Not implemented

Chart endpoints:

  • Sort: Chart position (ascending)
  • Filter: Not implemented

Compression

Response compression: Supported via Accept-Encoding: gzip

Request compression: Not supported

Example:

GET /artist/5b11f4ce-a62d-471e-81fc-a69a8278c7da HTTP/1.1
Accept-Encoding: gzip

HTTP/1.1 200 OK
Content-Encoding: gzip
Content-Length: 1234

Compression ratio: Typically 5:1 for JSON responses

Conditional Requests

ETag support: Not implemented

Last-Modified support: Not implemented

Future consideration: ETag generation based on cache timestamp

Webhooks

Not implemented: No webhook support for cache invalidation or updates

Workaround: Poll /recent/artist and /recent/album endpoints

Future consideration: WebSocket or Server-Sent Events for real-time updates

API Versioning Strategy

Current approach: Path-based versioning (/api/v0.3)

Version lifecycle:

  1. New features developed in testing version
  2. Tested in production alongside stable version
  3. Promoted to new stable version (e.g., v0.4)
  4. Old stable version deprecated after 6 months

Breaking changes: Only in major version increments

Backward compatibility: Maintained within minor versions

Performance Benchmarks

Endpoint Cold (ms) Cached (ms) CDN (ms)
GET /artist/{mbid} 2000-5000 50-200 10-50
GET /album/{mbid} 1500-3000 50-150 10-50
GET /search/artist 500-1000 50-100 N/A
GET /chart/billboard/hot-100 3000-5000 100-200 20-100
POST /artist/{mbid}/refresh 100-200 N/A N/A

Factors affecting cold request performance:

  • MusicBrainz database query complexity
  • Number of external API calls (FanArt, Wikipedia, etc.)
  • External API response times
  • Network latency

Cache hit rate: 85%+ with crawler enabled

Error Handling Examples

Invalid MBID format:

GET /artist/invalid-mbid HTTP/1.1

HTTP/1.1 400 Bad Request
{
  "error": "Invalid MBID format",
  "mbid": "invalid-mbid"
}

Artist not found:

GET /artist/00000000-0000-0000-0000-000000000000 HTTP/1.1

HTTP/1.1 404 Not Found
{
  "error": "Artist not found",
  "mbid": "00000000-0000-0000-0000-000000000000"
}

Missing API key:

POST /invalidate HTTP/1.1

HTTP/1.1 401 Unauthorized
{
  "error": "Missing or invalid API key"
}

Database connection error:

GET /artist/5b11f4ce-a62d-471e-81fc-a69a8278c7da HTTP/1.1

HTTP/1.1 503 Service Unavailable
{
  "error": "Database unavailable",
  "retry_after": 60
}

Client Implementation Examples

Python

import requests

class LidarrMetadataClient:
    def __init__(self, base_url='https://api.lidarr.audio/api/v0.3'):
        self.base_url = base_url
        self.session = requests.Session()
    
    def get_artist(self, mbid, prim_types=None, sec_types=None, statuses=None):
        params = {}
        if prim_types:
            params['primTypes'] = ','.join(prim_types)
        if sec_types:
            params['secTypes'] = ','.join(sec_types)
        if statuses:
            params['releaseStatuses'] = ','.join(statuses)
        
        response = self.session.get(f'{self.base_url}/artist/{mbid}', params=params)
        response.raise_for_status()
        return response.json()
    
    def search_artist(self, query, limit=10):
        response = self.session.get(
            f'{self.base_url}/search/artist',
            params={'query': query, 'limit': limit}
        )
        response.raise_for_status()
        return response.json()

# Usage
client = LidarrMetadataClient()
artist = client.get_artist('5b11f4ce-a62d-471e-81fc-a69a8278c7da', prim_types=['Album'])
results = client.search_artist('nirvana')

JavaScript

class LidarrMetadataClient {
  constructor(baseUrl = 'https://api.lidarr.audio/api/v0.3') {
    this.baseUrl = baseUrl;
  }
  
  async getArtist(mbid, options = {}) {
    const params = new URLSearchParams();
    if (options.primTypes) params.set('primTypes', options.primTypes.join(','));
    if (options.secTypes) params.set('secTypes', options.secTypes.join(','));
    if (options.releaseStatuses) params.set('releaseStatuses', options.releaseStatuses.join(','));
    
    const response = await fetch(`${this.baseUrl}/artist/${mbid}?${params}`);
    if (!response.ok) throw new Error(`HTTP ${response.status}`);
    return response.json();
  }
  
  async searchArtist(query, limit = 10) {
    const params = new URLSearchParams({ query, limit });
    const response = await fetch(`${this.baseUrl}/search/artist?${params}`);
    if (!response.ok) throw new Error(`HTTP ${response.status}`);
    return response.json();
  }
}

// Usage
const client = new LidarrMetadataClient();
const artist = await client.getArtist('5b11f4ce-a62d-471e-81fc-a69a8278c7da', {
  primTypes: ['Album']
});
const results = await client.searchArtist('nirvana');

Conclusion

The API provides comprehensive music metadata with:

  • 15+ endpoints covering artists, albums, search, charts, and Spotify integration
  • Multi-source aggregation from MusicBrainz, FanArt.tv, Wikipedia, Spotify, Last.fm, Billboard
  • Intelligent caching with 30-day TTL and CDN integration
  • Flexible filtering for release types and statuses
  • Chart integration from 4 major sources
  • Spotify mapping for cross-platform compatibility

The API is production-ready with excellent performance characteristics when properly cached. The dual-version deployment strategy allows safe rollout of new features.

Key strengths: comprehensive metadata, excellent caching, multi-source enrichment.

Key weaknesses: no authentication on read endpoints, no pagination, no webhooks.