* refacto wip * move from yarn to pnpm * update api doc * fix pnpm * fix ci * fix express type * fix api * front fixes * fix delete loading
23 KiB
Tidarr API Documentation
This documentation describes how to use the Tidarr REST API to automate downloads and manage your instance.
Table of Contents
- Basic Configuration
- Authentication
- Playback Endpoints
- Download Endpoints
- Queue Management
- History Endpoints
- Configuration Endpoints
- Synchronization Endpoints (watch list)
- Custom CSS Endpoints
- Lidarr Integration
- Usage Examples
Basic Configuration
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.
Authentication
Tidarr supports two authentication methods:
Method 1: API Key (Recommended for automation)
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 Key
Use 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-key
Regenerate API key (requires JWT):
POST /api/api-key/regenerate
⚠️ Warning: Invalidates the current key. Update it everywhere it's used.
Method 2: JWT Token (For web UI and interactive sessions)
Login:
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"
Check if authentication is active
GET /api/is-auth-active
Response:
{
"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).
Method 3: OpenID Connect (OIDC) Authentication
Tidarr supports OIDC authentication for integration with identity providers like Keycloak, PocketID, Authentik, etc.
Initiate OIDC login:
GET /api/auth/oidc/login
Redirects the user to the configured OIDC provider for authentication.
OIDC callback:
GET /api/auth/oidc/callback
Handles 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)
Playback Endpoints
Generate signed streaming URL
GET /api/stream/sign/:id
Generates 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.
Play audio stream
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.
Download Endpoints
Add an item to the download queue
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).
Album
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"
}
}'
Track
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"
}
}'
Video
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"
}
}'
Playlist
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"
}
}'
Mix
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"
}
}'
Artist (all albums)
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"
}
}'
Artist (all videos)
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"
}
}'
Favorites
# 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
Remove an item from the queue
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
Clear the entire queue
curl -X DELETE http://localhost:8484/api/remove-all \
-H "X-Api-Key: your-api-key"
Response: 204 No Content
Remove finished items
curl -X DELETE http://localhost:8484/api/remove-finished \
-H "X-Api-Key: your-api-key"
Response: 204 No Content
Retry failed items
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
Queue Management
Get queue list
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).
Pause the queue
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
Resume the queue
curl -X POST http://localhost:8484/api/queue/resume \
-H "X-Api-Key: your-api-key"
Response: 204 No Content
Get queue status
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.
Single download (NO_DOWNLOAD mode)
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.
Retry post-processing
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.
History Endpoints
Note: History requires ENABLE_HISTORY=true in Docker configuration.
Get download history
curl http://localhost:8484/api/history/list \
-H "X-Api-Key: your-api-key"
Response:
["251082404", "77610756", "123456789"]
Clear history
curl -X DELETE http://localhost:8484/api/history/list \
-H "X-Api-Key: your-api-key"
Response: 204 No Content
Configuration Endpoints
Get Tidarr configuration
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}"
}
}
}
Run Tidal authentication flow
GET /api/run-token
SSE 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.
Delete Tidal token
curl -X DELETE http://localhost:8484/api/token \
-H "X-Api-Key: your-api-key"
Response: 204 No Content
Get Tiddl TOML configuration
curl http://localhost:8484/api/tiddl/config \
-H "X-Api-Key: your-api-key"
Response:
{
"toml": "[download]\nquality = \"high\"\nthreads = 6\n..."
}
Save Tiddl TOML configuration
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"
}
Synchronization Endpoints
Get synchronized playlists
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"
}
]
Add playlist to sync
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
Remove playlist from sync
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
Remove all playlists from sync
curl -X DELETE http://localhost:8484/api/sync/remove-all \
-H "X-Api-Key: your-api-key"
Response: 204 No Content
Trigger sync now
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.
Custom CSS Endpoints
Get custom CSS
curl http://localhost:8484/api/custom-css \
-H "X-Api-Key: your-api-key"
Response:
{
"css": "body { background-color: #1a1a1a; }"
}
Save custom CSS
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"
}
Lidarr Integration
Tidarr integrates with Lidarr using:
- Newznab Indexer - Search and discover albums
- SABnzbd Download Client - Track downloads
📖 Complete setup guide: LIDARR_INTEGRATION.md
Newznab Indexer Endpoints
Base URL: http://your-tidarr-url:8484/api/lidarr
Get Capabilities
GET /api/lidarr?t=caps
Example:
curl "http://localhost:8484/api/lidarr?t=caps&apikey=your-api-key"
Response: XML capabilities document
Search Albums
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
Download Album
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
SABnzbd Download Client Endpoints
Base URL: http://your-tidarr-url:8484/api/sabnzbd/api
Get Version
GET /api/sabnzbd/api?mode=version
Example:
curl "http://localhost:8484/api/sabnzbd/api?mode=version&apikey=your-api-key"
Response:
{
"version": "3.0.0"
}
Add Download
GET /api/sabnzbd/api?mode=addurl&name={url}
POST /api/sabnzbd/api?mode=addfile # multipart/form-data with NZB file
Example:
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 Queue
GET /api/sabnzbd/api?mode=queue
Example:
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
Delete from Queue
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 History
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
Delete from History
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"]
}
Usage Examples
Bash: Download multiple albums
#!/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
Python: Add to queue
#!/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: Direct download
docker compose exec tidarr tiddl download url https://listen.tidal.com/album/251082404
HTTP Status Codes
200 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