Music Hub API Reference for Agents
Current REST + SSE API for automation against the desktop hub.
Defaults
- Base URL:
http://localhost:38472 - Protocol: REST + SSE
- Format: JSON
- Data dir:
~/.music-hub
Trust and auth
- Loopback / same-machine: no auth required, full API access.
- LAN (same Wi-Fi): most read endpoints open; writes may require pairing or
MUSIC_HUB_API_TOKEN. - Remote / proxied: requires active license + bearer token from
/api/auth/pairor/api/auth/refresh.
Public unauthenticated routes:
GET /api/ping,GET /api/infoPOST /api/auth/pair,POST /api/auth/refreshGET /api/share/:type/:id/bootstrapPOST /api/share/session/heartbeatGET /api/collab/invites/preview-opaque,POST /api/collab/invites/claim-opaque
Fast start
# Health + info
curl http://localhost:38472/api/ping
curl http://localhost:38472/api/infoIf databaseHealth.status is not healthy, most library routes return 503 database_unavailable.
Pairing flow (for remote agents)
1. Arm pairing window (from the desktop UI)
Open Settings > Pairing in the desktop app and arm a pairing window. Agents on the same machine can read pairing state directly.
2. Exchange pairing code for tokens
curl -X POST http://localhost:38472/api/auth/pair \
-H 'Content-Type: application/json' \
-d '{"pairingCode":"abc123","deviceId":"agent-1","deviceName":"automation"}'3. Use the access token
curl "http://localhost:38472/api/tracks?limit=5" \
-H "Authorization: Bearer $ACCESS_TOKEN"4. Refresh when needed
curl -X POST http://localhost:38472/api/auth/refresh \
-H 'Content-Type: application/json' \
-d '{"deviceId":"agent-1","refreshToken":"..."}'Core read endpoints
Library & Stats
GET /api/library/stats— track/album/artist counts, total duration/size, distributionsGET /api/library/filters— available genres, tags, formats, BPM range, year range, foldersGET /api/tracks?limit=50&offset=0— paginated tracks with filters (genre, year, BPM, tags, folder, duration, sort)GET /api/tracks?match=query— full-text filter across title, artist, album, genres, tagsGET /api/tracks/:id— single trackGET /api/tracks/:id/metadata— metadata overlay (genres, tags, enrichment, ISRC, barcode, MBIDs)
Albums, Artists, Labels
GET /api/albums?limit=50&offset=0GET /api/albums/:id,GET /api/albums/:id/tracksGET /api/artists?limit=50&offset=0GET /api/artists/:id,GET /api/artists/:id/tracks,GET /api/artists/:id/albumsGET /api/labels?limit=50&offset=0,GET /api/labels/:id
Playlists
GET /api/playlistsGET /api/playlists/:id,GET /api/playlists/:id/tracksPOST /api/playlists{ "name": "...", "description": "...", "folder": "..." }POST /api/playlists/:id/tracks{ "trackIds": [...] }DELETE /api/playlists/:id
Search
GET /api/search?q=miles+davis&type=tracks|albums|artists&limit=50
Playback & History
GET /api/playback/state— current queue stateGET /api/library/recently-played?limit=10GET /api/analytics/play-history?days=7&limit=100— chronological play eventsGET /api/analytics/hub-counter— global playback counter + license gate
Agent Playback
POST /api/agent/play— start playback from agent context{ "trackIds": ["abc123"], "startIndex": 0 }POST /api/agent/queue— add tracks to current queue without interrupting{ "trackIds": ["ghi789"] }
Shared / Saved
GET /api/saved— saved track/artist/album IDsGET /api/library/bookmarked— bookmarked playlistsGET /api/share/:type/:id/bootstrap— public share page data
AI Context
GET /api/ai/context— current track, queue, session snapshot
Suggestions
GET /api/suggestions?seed_track_id=...&limit=10GET /api/tracks/:id/similar?limit=10
Core write endpoints
PUT /api/saved/tracks/:id{ "status": "new|saved|heard", "source": "desktop|mobile" }POST /api/play/events{ "trackId": "...", "source": "desktop|mobile", "completed": true }PUT /api/tracks/:id/metadata/curated{ "genres": [...], "tags": [...], "styles": [...] }PUT /api/tracks/:id/metadata/overrides{ "manualGenres": [...], "manualTags": [...] }DELETE /api/tracks/:id/metadata/overridesPOST /api/tracks/:id/tags/write-to-filePUT /api/tracks/:id/primary-metadata{ "title": "...", "artist": "...", "album": "..." }
Enrichment
GET /api/tracks/:id/enrichment/job— current enrichment statusPOST /api/tracks/:id/re-enrich/search{ "provider": "musicbrainz|discogs", "title": "...", "artist": "...", "album": "..." }POST /api/tracks/:id/re-enrich/apply{ "provider": "musicbrainz", "candidate": {...} }
License
POST /api/license/activate{ "licenseKey": "..." }POST /api/license/validate{ "force": true }GET /api/license/status
Inbox / Library triage
POST /api/library/inbox/remove{ "trackIds": [...] }POST /api/library/inbox/clearPOST /api/library/inbox/mark-heard{ "trackIds": [...] }POST /api/library/inbox/mark-to-listen{ "trackIds": [...] }POST /api/library/inbox/undo
SSE feeds
GET /api/library/events— track updates, enrichment status, metadata changesGET /api/events/stream— scan progress, track added/updated/deleted
Remote / Tunnel
GET /api/remote/statusPOST /api/remote/cloudflare/setup,POST /api/remote/cloudflare/deletePOST /api/remote/tailscale/setup,POST /api/remote/tailscale/deletePOST /api/remote/route/toggle{ "route": "cloudflare|tailscale|sovereign", "enabled": true }
Diagnostics
GET /api/diagnostics/statusPOST /api/diagnostics/upload
Settings
GET /api/settingsPUT /api/settings/server{ "name": "...", "port": 38472 }
Local-only operations
These must run on the desktop host itself (loopback):
POST /api/settings/folders/rescanPOST /api/database/rebuildGET /api/auth/devices,DELETE /api/auth/devices/:deviceIdGET /api/analytics/hub-counter/recalculate
Share-specific public routes
GET /api/share/playlist/:id/bootstrapGET /api/share/artist/:id/bootstrapGET /api/share/album/:id/bootstrapGET /api/share/track/:id/bootstrapPOST /api/share/session/heartbeat
Bootstrap responses include shareSessionId and mediaToken. Both are short-lived.
Recovery
If the hub reports a faulted database:
curl http://localhost:38472/api/info
# Check databaseHealth.status
curl -X POST http://localhost:38472/api/database/rebuildDo not script destructive DB deletion. The hub preserves and archives faulted DBs.
Failure modes
401— remote auth missing or expired403— license required or local-only endpoint called remotely404— resource not found409 pairing_not_armed— pairing window not active503 database_unavailable— hub DB is faulted or incompatible
Full reference
See the complete markdown doc shipped with the desktop app:
desktop/docs/API-REFERENCE-FOR-AGENTS.md