This documentation describes how to use the Tidarr REST API to automate downloads and manage your instance.
- Basic Configuration
- Authentication
- Playback Endpoints
- Download Endpoints
- Queue Management
- History Endpoints
- Configuration Endpoints
- Synchronization Endpoints (watch list)
- Custom CSS Endpoints
- Lidarr Integration
- Usage Examples
API Base URL: http://your-host:8484
All API endpoints (except /api/is-auth-active) require authentication if ADMIN_PASSWORD is set in your Docker configuration.
Tidarr supports two authentication methods:
The API key is automatically generated on first startup and stored in /shared/.tidarr-api-key.
Get your API key:
# Via Docker
docker exec tidarr cat /shared/.tidarr-api-key
# Or via Web UI: Settings → Authentication → API KeyUse it in requests:
# Via header (recommended)
curl http://localhost:8484/api/settings \
-H "X-Api-Key: your-api-key"
# Via query parameter
curl "http://localhost:8484/api/settings?apikey=your-api-key"Advantages:
- ✅ Secure random 64-character key
- ✅ No expiration (unlike JWT tokens)
- ✅ Standard for *arr applications
- ✅ Can be regenerated anytime
Management endpoints:
Get current API key (requires JWT):
GET /api/api-keyRegenerate API key (requires JWT):
POST /api/api-key/regenerateLogin:
curl -X POST http://localhost:8484/api/auth \
-H 'Content-Type: application/json' \
-d '{"password": "your_password"}'Response:
{
"status": "ok",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}Use the token:
curl http://localhost:8484/api/settings \
-H "Authorization: Bearer your-jwt-token"GET /api/is-auth-activeResponse:
{
"isAuthActive": true,
"authType": "password"
}Possible authType values:
"password"- Password authentication (ADMIN_PASSWORD)"oidc"- OpenID Connect authenticationnull- No authentication configured
Note: All examples below use the API key method (X-Api-Key header).
Tidarr supports OIDC authentication for integration with identity providers like Keycloak, PocketID, Authentik, etc.
Initiate OIDC login:
GET /api/auth/oidc/loginRedirects the user to the configured OIDC provider for authentication.
OIDC callback:
GET /api/auth/oidc/callbackHandles the OIDC callback and issues a JWT token. Redirects to the frontend with the token.
Required environment variables:
OIDC_ISSUER- The URL of your OpenID Connect providerOIDC_CLIENT_ID- The client ID registered in your OIDC providerOIDC_CLIENT_SECRET- The client secret for your applicationOIDC_REDIRECT_URI- The callback URL (e.g.,https://your-tidarr-domain.com/api/auth/oidc/callback)
GET /api/stream/sign/:idGenerates a time-limited signed URL for audio streaming.
Parameters:
id- The Tidal track ID
Example:
curl http://localhost:8484/api/stream/sign/123456789 \
-H "X-Api-Key: your-api-key"Response:
{
"url": "/api/stream/play/123456789?exp=1234567890&sig=abc123..."
}Note: The signed URL expires after 5 minutes.
GET /api/stream/play/:id?exp={expiration}&sig={signature}Streams audio content with signature validation. Supports range requests for seeking.
Parameters:
id- The Tidal track IDexp- Expiration timestamp (from signed URL)sig- Signature (from signed URL)
Note: This endpoint is typically called via the signed URL obtained from /api/stream/sign/:id.
Endpoint: POST /api/save
Important: Use full Tidal URLs (not numeric IDs). The id field is required and must be a non-empty string or number, unique within the queue (use the Tidal numeric ID for URL-based items, or the type value for favorites).
Supported types: album, track, video, playlist, mix, artist, artist_videos, favorite_albums, favorite_tracks, favorite_playlists, favorite_videos, favorite_artists
quality: Optional. If omitted, Tidarr uses the server's configured default quality (download.track_quality in config.toml).
curl -X POST http://localhost:8484/api/save \
-H "X-Api-Key: your-api-key" \
-H 'Content-Type: application/json' \
-d '{
"item": {
"id": "251082404",
"url": "https://listen.tidal.com/album/251082404",
"type": "album",
"status": "queue_download"
}
}'curl -X POST http://localhost:8484/api/save \
-H "X-Api-Key: your-api-key" \
-H 'Content-Type: application/json' \
-d '{
"item": {
"id": "123456789",
"url": "https://listen.tidal.com/track/123456789",
"type": "track",
"status": "queue_download"
}
}'curl -X POST http://localhost:8484/api/save \
-H "X-Api-Key: your-api-key" \
-H 'Content-Type: application/json' \
-d '{
"item": {
"id": "123456789",
"url": "https://listen.tidal.com/video/123456789",
"type": "video",
"status": "queue_download"
}
}'curl -X POST http://localhost:8484/api/save \
-H "X-Api-Key: your-api-key" \
-H 'Content-Type: application/json' \
-d '{
"item": {
"id": "abc123-def456",
"url": "https://listen.tidal.com/playlist/abc123-def456",
"type": "playlist",
"status": "queue_download"
}
}'curl -X POST http://localhost:8484/api/save \
-H "X-Api-Key: your-api-key" \
-H 'Content-Type: application/json' \
-d '{
"item": {
"id": "000000000000000000000000",
"url": "https://listen.tidal.com/mix/000000000000000000000000",
"type": "mix",
"status": "queue_download"
}
}'curl -X POST http://localhost:8484/api/save \
-H "X-Api-Key: your-api-key" \
-H 'Content-Type: application/json' \
-d '{
"item": {
"id": "3566315",
"url": "https://listen.tidal.com/artist/3566315",
"type": "artist",
"status": "queue_download"
}
}'curl -X POST http://localhost:8484/api/save \
-H "X-Api-Key: your-api-key" \
-H 'Content-Type: application/json' \
-d '{
"item": {
"id": "3566315",
"url": "https://listen.tidal.com/artist/3566315",
"type": "artist_videos",
"status": "queue_download"
}
}'# Favorite albums
curl -X POST http://localhost:8484/api/save \
-H "X-Api-Key: your-api-key" \
-H 'Content-Type: application/json' \
-d '{
"item": {
"id": "favorite_albums",
"type": "favorite_albums",
"status": "queue_download"
}
}'
# Favorite tracks
curl -X POST http://localhost:8484/api/save \
-H "X-Api-Key: your-api-key" \
-H 'Content-Type: application/json' \
-d '{
"item": {
"id": "favorite_tracks",
"type": "favorite_tracks",
"status": "queue_download"
}
}'
# Favorite playlists
curl -X POST http://localhost:8484/api/save \
-H "X-Api-Key: your-api-key" \
-H 'Content-Type: application/json' \
-d '{
"item": {
"id": "favorite_playlists",
"type": "favorite_playlists",
"status": "queue_download"
}
}'
# Favorite videos
curl -X POST http://localhost:8484/api/save \
-H "X-Api-Key: your-api-key" \
-H 'Content-Type: application/json' \
-d '{
"item": {
"id": "favorite_videos",
"type": "favorite_videos",
"status": "queue_download"
}
}'
# Favorite artists
curl -X POST http://localhost:8484/api/save \
-H "X-Api-Key: your-api-key" \
-H 'Content-Type: application/json' \
-d '{
"item": {
"id": "favorite_artists",
"type": "favorite_artists",
"status": "queue_download"
}
}'Response: 201 Created
curl -X DELETE http://localhost:8484/api/remove \
-H "X-Api-Key: your-api-key" \
-H 'Content-Type: application/json' \
-d '{"id": "12345"}'Response: 204 No Content
curl -X DELETE http://localhost:8484/api/remove-all \
-H "X-Api-Key: your-api-key"Response: 204 No Content
curl -X DELETE http://localhost:8484/api/remove-finished \
-H "X-Api-Key: your-api-key"Response: 204 No Content
Resets every item currently in error status back to queue_download. Items with any other status are left unchanged.
curl -X POST http://localhost:8484/api/retry-failed \
-H "X-Api-Key: your-api-key"Response: 204 No Content
Supports optional pagination via offset and limit query parameters.
curl http://localhost:8484/api/queue/list \
-H "X-Api-Key: your-api-key"
# Paginated
curl "http://localhost:8484/api/queue/list?offset=0&limit=50" \
-H "X-Api-Key: your-api-key"Response:
{
"total": 42,
"offset": 0,
"limit": null,
"queue": [
{
"id": "251082404",
"type": "album",
"title": "Album Name",
"artist": "Artist Name",
"quality": "max",
"status": "finished",
"url": "http://www.tidal.com/album/251082404",
"loading": false,
"error": false
}
]
}Possible status values: queue_download, download, queue_processing, processing, finished, error
errorStage: Present only when status is error. "download" means the download itself failed or never fully completed — retry via Retry post-processing if files are present, or a normal re-add otherwise. "post_processing" means the download succeeded but a later step (move, tagging, ...) failed — use Retry post-processing to retry just that step.
limitisnullwhen no limit is specified (all items returned).
curl -X POST http://localhost:8484/api/queue/pause \
-H "X-Api-Key: your-api-key"Response: 204 No Content
Behavior:
- Stops processing new items
- Cancels current download and resets it to "queue" status
- Cleans up incomplete downloads
curl -X POST http://localhost:8484/api/queue/resume \
-H "X-Api-Key: your-api-key"Response: 204 No Content
curl http://localhost:8484/api/queue/status \
-H "X-Api-Key: your-api-key"Response:
{
"isPaused": false,
"batchCount": 0,
"batchResumeAt": null
}batchCount/batchResumeAt: Only relevant when DOWNLOAD_BATCH_SIZE is set. batchCount is the number of items downloaded in the current batch; batchResumeAt is a timestamp (ms) for the scheduled auto-resume, or null if not paused for batching.
Trigger a one-off download for a specific queued item, bypassing the NO_DOWNLOAD mode pause. The item goes through the full download pipeline (beets, move to library, notifications) and ends up as finished on success, or error if the download fails (see errorStage above for what to do next).
curl -X POST http://localhost:8484/api/single-download \
-H "X-Api-Key: your-api-key" \
-H 'Content-Type: application/json' \
-d '{"id": "251082404"}'Response: 204 No Content
Behavior:
- Item is downloaded immediately, bypassing the paused queue
- Full post-processing pipeline runs (beets, permissions, move, notifications)
- Item ends as
finishedin the queue
Error: 500 if the item is not found.
Retries tagging/move for an item stuck in error status, without re-downloading. Useful when the download itself succeeded but a later step (e.g. moving files to the library) failed, for example due to wrong permissions on the library folder — fix the underlying issue, then retry just this step. Relies on the downloaded files still being present in the item's processing folder (kept automatically when a move fails, and also when a download was interrupted partway through — e.g. a network drop mid-album keeps whatever tracks were already downloaded).
curl -X POST http://localhost:8484/api/retry-post-processing \
-H "X-Api-Key: your-api-key" \
-H 'Content-Type: application/json' \
-d '{"id": "251082404"}'Response: 204 No Content
Behavior:
- Re-runs the full post-processing pipeline (tagging, permissions, move, notifications) using the files already downloaded
- Does not call tiddl again — no network request to Tidal
- Item ends as
finishedon success, or stayserrorif it fails again
Error: 500 if the item is not found, not in error status, or if another item is currently post-processing.
Note: History requires ENABLE_HISTORY=true in Docker configuration.
curl http://localhost:8484/api/history/list \
-H "X-Api-Key: your-api-key"Response:
["251082404", "77610756", "123456789"]curl -X DELETE http://localhost:8484/api/history/list \
-H "X-Api-Key: your-api-key"Response: 204 No Content
curl http://localhost:8484/api/settings \
-H "X-Api-Key: your-api-key"Response:
{
"noToken": false,
"quality": "high",
"enableBeetsAutotag": true,
"enablePlexUpdate": true,
"tiddl_config": {
"auth": {
"token": "...",
"refresh_token": "..."
},
"format": {
"quality": "high",
"album_template": "{album_artist}/{album}/{number:02d}. {title}"
}
}
}GET /api/run-tokenSSE endpoint that initiates the Tidal device authentication flow. Opens a stream that sends authentication events (login URL, status updates) until authentication completes or fails.
Response: text/event-stream
Note: This endpoint is used by the web UI during initial Tidal setup. Events are streamed until authentication completes.
curl -X DELETE http://localhost:8484/api/token \
-H "X-Api-Key: your-api-key"Response: 204 No Content
curl http://localhost:8484/api/tiddl/config \
-H "X-Api-Key: your-api-key"Response:
{
"toml": "[download]\nquality = \"high\"\nthreads = 6\n..."
}curl -X POST http://localhost:8484/api/tiddl/config \
-H "X-Api-Key: your-api-key" \
-H 'Content-Type: application/json' \
-d '{
"toml": "[download]\nquality = \"max\"\nthreads = 8\n..."
}'Response:
{
"success": true,
"message": "Tiddl config saved successfully"
}curl http://localhost:8484/api/sync/list \
-H "X-Api-Key: your-api-key"Response:
[
{
"id": "abc123-def456",
"title": "My Playlist",
"url": "https://listen.tidal.com/playlist/abc123-def456",
"type": "playlist"
}
]curl -X POST http://localhost:8484/api/sync/save \
-H "X-Api-Key: your-api-key" \
-H 'Content-Type: application/json' \
-d '{
"item": {
"id": "abc123-def456",
"title": "My Playlist",
"url": "https://listen.tidal.com/playlist/abc123-def456",
"type": "playlist"
}
}'Response: 201 Created
curl -X DELETE http://localhost:8484/api/sync/remove \
-H "X-Api-Key: your-api-key" \
-H 'Content-Type: application/json' \
-d '{"id": "abc123-def456"}'Response: 204 No Content
curl -X DELETE http://localhost:8484/api/sync/remove-all \
-H "X-Api-Key: your-api-key"Response: 204 No Content
curl -X POST http://localhost:8484/api/sync/trigger \
-H "X-Api-Key: your-api-key"Response: 202 Accepted
Note: Default sync schedule is 0 3 * * * (3 AM daily). Configure with SYNC_CRON_EXPRESSION.
curl http://localhost:8484/api/custom-css \
-H "X-Api-Key: your-api-key"Response:
{
"css": "body { background-color: #1a1a1a; }"
}curl -X POST http://localhost:8484/api/custom-css \
-H "X-Api-Key: your-api-key" \
-H 'Content-Type: application/json' \
-d '{
"css": "body { background-color: #1a1a1a; }"
}'Response:
{
"success": true,
"message": "Custom CSS saved successfully"
}Tidarr integrates with Lidarr using:
- Newznab Indexer - Search and discover albums
- SABnzbd Download Client - Track downloads
📖 Complete setup guide: LIDARR_INTEGRATION.md
Base URL: http://your-tidarr-url:8484/api/lidarr
GET /api/lidarr?t=capsExample:
curl "http://localhost:8484/api/lidarr?t=caps&apikey=your-api-key"Response: XML capabilities document
GET /api/lidarr?t=search&q={query}
GET /api/lidarr?t=music&artist={artist}&album={album}Parameters:
t- Request type:searchormusicq- Search queryartist- Artist name (fort=music)album- Album name (fort=music)
Examples:
# General search
curl "http://localhost:8484/api/lidarr?t=search&q=Daft%20Punk&apikey=your-api-key"
# Artist + Album search
curl "http://localhost:8484/api/lidarr?t=music&artist=Daft%20Punk&album=Random%20Access%20Memories&apikey=your-api-key"Response: Newznab XML with results
GET /api/lidarr/download/{albumId}/{quality}Parameters:
albumId- The Tidal album IDquality- Download quality:max(24-bit),high(16-bit),normal(AAC-320),low(AAC-96)
Example:
curl "http://localhost:8484/api/lidarr/download/34277251/high?apikey=your-api-key"Response: NZB file format
Base URL: http://your-tidarr-url:8484/api/sabnzbd/api
GET /api/sabnzbd/api?mode=versionExample:
curl "http://localhost:8484/api/sabnzbd/api?mode=version&apikey=your-api-key"Response:
{
"version": "3.0.0"
}GET /api/sabnzbd/api?mode=addurl&name={url}
POST /api/sabnzbd/api?mode=addfile # multipart/form-data with NZB fileExample:
curl "http://localhost:8484/api/sabnzbd/api?mode=addurl&name=https://listen.tidal.com/album/34277251&apikey=your-api-key"Response:
{
"status": true,
"nzo_ids": ["tidarr-34277251-1234567890"]
}GET /api/sabnzbd/api?mode=queueExample:
curl "http://localhost:8484/api/sabnzbd/api?mode=queue&apikey=your-api-key"Response:
{
"queue": {
"status": "Downloading",
"slots": [
{
"nzo_id": "tidarr-34277251-1234567890",
"filename": "Daft Punk - Random Access Memories",
"status": "Downloading"
}
]
}
}Status mapping:
Downloading- Currently processingQueued- Waiting in queuePaused- Queue paused
GET /api/sabnzbd/api?mode=queue&name=delete&value={nzo_id}Example:
curl "http://localhost:8484/api/sabnzbd/api?mode=queue&name=delete&value=tidarr_nzo_34277251&apikey=your-api-key"Response:
{
"status": true,
"nzo_ids": ["tidarr_nzo_34277251"]
}GET /api/sabnzbd/api?mode=history&limit={n}Example:
curl "http://localhost:8484/api/sabnzbd/api?mode=history&limit=50&apikey=your-api-key"Response:
{
"history": {
"slots": [
{
"nzo_id": "tidarr-34277251-1234567890",
"name": "Daft Punk - Random Access Memories",
"status": "Completed",
"storage": "/music/Daft Punk/2013 - Random Access Memories"
}
]
}
}Status mapping:
Completed- Successfully downloadedFailed- Download failed
GET /api/sabnzbd/api?mode=history&name=delete&value={nzo_id}Example:
curl "http://localhost:8484/api/sabnzbd/api?mode=history&name=delete&value=tidarr_nzo_34277251&apikey=your-api-key"Response:
{
"status": true,
"nzo_ids": ["tidarr_nzo_34277251"]
}#!/bin/bash
TIDARR_URL="http://localhost:8484"
TIDARR_API_KEY=$(docker exec tidarr cat /shared/.tidarr-api-key)
albums=(
"251082404 https://listen.tidal.com/album/251082404"
"123456789 https://listen.tidal.com/album/123456789"
)
for entry in "${albums[@]}"; do
id="${entry%% *}"
album="${entry#* }"
echo "Adding $album..."
curl -s -X POST $TIDARR_URL/api/save \
-H "X-Api-Key: $TIDARR_API_KEY" \
-H 'Content-Type: application/json' \
-d "{
\"item\": {
\"id\": \"$id\",
\"url\": \"$album\",
\"type\": \"album\",
\"status\": \"queue_download\"
}
}"
echo " ✓"
done#!/usr/bin/env python3
import requests
TIDARR_URL = "http://localhost:8484"
API_KEY = "your-api-key"
headers = {"X-Api-Key": API_KEY}
album_data = {
"item": {
"id": "251082404",
"url": "https://listen.tidal.com/album/251082404",
"type": "album",
"status": "queue_download"
}
}
requests.post(f"{TIDARR_URL}/api/save", headers=headers, json=album_data)
print("Album added to queue")docker compose exec tidarr tiddl download url https://listen.tidal.com/album/251082404200 OK- Success201 Created- Resource created202 Accepted- Async operation accepted204 No Content- Deletion successful400 Bad Request- Invalid data403 Forbidden- Invalid API key/token404 Not Found- Resource not found500 Internal Server Error- Server error
Part of this documentation was generated with AI assistance