AI & Automation
API Reference for Agents

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/pair or /api/auth/refresh.

Public unauthenticated routes:

  • GET /api/ping, GET /api/info
  • POST /api/auth/pair, POST /api/auth/refresh
  • GET /api/share/:type/:id/bootstrap
  • POST /api/share/session/heartbeat
  • GET /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/info

If 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, distributions
  • GET /api/library/filters — available genres, tags, formats, BPM range, year range, folders
  • GET /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, tags
  • GET /api/tracks/:id — single track
  • GET /api/tracks/:id/metadata — metadata overlay (genres, tags, enrichment, ISRC, barcode, MBIDs)

Albums, Artists, Labels

  • GET /api/albums?limit=50&offset=0
  • GET /api/albums/:id, GET /api/albums/:id/tracks
  • GET /api/artists?limit=50&offset=0
  • GET /api/artists/:id, GET /api/artists/:id/tracks, GET /api/artists/:id/albums
  • GET /api/labels?limit=50&offset=0, GET /api/labels/:id

Playlists

  • GET /api/playlists
  • GET /api/playlists/:id, GET /api/playlists/:id/tracks
  • POST /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 state
  • GET /api/library/recently-played?limit=10
  • GET /api/analytics/play-history?days=7&limit=100 — chronological play events
  • GET /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 IDs
  • GET /api/library/bookmarked — bookmarked playlists
  • GET /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=10
  • GET /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/overrides
  • POST /api/tracks/:id/tags/write-to-file
  • PUT /api/tracks/:id/primary-metadata { "title": "...", "artist": "...", "album": "..." }

Enrichment

  • GET /api/tracks/:id/enrichment/job — current enrichment status
  • POST /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/clear
  • POST /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 changes
  • GET /api/events/stream — scan progress, track added/updated/deleted

Remote / Tunnel

  • GET /api/remote/status
  • POST /api/remote/cloudflare/setup, POST /api/remote/cloudflare/delete
  • POST /api/remote/tailscale/setup, POST /api/remote/tailscale/delete
  • POST /api/remote/route/toggle { "route": "cloudflare|tailscale|sovereign", "enabled": true }

Diagnostics

  • GET /api/diagnostics/status
  • POST /api/diagnostics/upload

Settings

  • GET /api/settings
  • PUT /api/settings/server { "name": "...", "port": 38472 }

Local-only operations

These must run on the desktop host itself (loopback):

  • POST /api/settings/folders/rescan
  • POST /api/database/rebuild
  • GET /api/auth/devices, DELETE /api/auth/devices/:deviceId
  • GET /api/analytics/hub-counter/recalculate

Share-specific public routes

  • GET /api/share/playlist/:id/bootstrap
  • GET /api/share/artist/:id/bootstrap
  • GET /api/share/album/:id/bootstrap
  • GET /api/share/track/:id/bootstrap
  • POST /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/rebuild

Do not script destructive DB deletion. The hub preserves and archives faulted DBs.

Failure modes

  • 401 — remote auth missing or expired
  • 403 — license required or local-only endpoint called remotely
  • 404 — resource not found
  • 409 pairing_not_armed — pairing window not active
  • 503 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