How it is built
Daemon API
How the local API is served, authenticated and structured, and the route groups it offers.
nuvo-core is an HTTP server (axum) on a unix socket. It is an internal interface between the Nuvo window and its service. It is not a public API and can change between versions.
Transport
- The socket is
$XDG_RUNTIME_DIR/nuvo/core.sock, in a directory with mode 0700 and with the socket at mode 0600.NUVO_CORE_SOCKEToverrides the path. - Every request needs
Authorization: Bearer <token>. The token is random, at least 32 characters, made at launch, and known to Electron main and the daemon only./healthneeds it too. A wrong token gives401. - A second daemon cannot take the socket while one answers.
- Request bodies have a size limit. Uploads to the cache are limited to 512 MiB.
Health and state
GET /health returns a status: starting while the daemon opens the library, then ok. While locked the library routes answer 423 with code LOCKED.
Errors
Every error body has the same shape:
{ "message": "...", "code": "NOT_FOUND", "reqId": "a1b2c3d4e5f6", "reason": "..." }
reason appears only for unplayable SoundCloud tracks. Codes: NOT_FOUND, INVALID_INPUT, FORBIDDEN_HOST, CONFLICT, LOCKED, CORE_STARTING, UNAUTHORIZED, UPSTREAM, UPSTREAM_TIMEOUT, RATE_LIMITED, SC_UNAVAILABLE, SC_UNPLAYABLE, UNSUPPORTED_FORMAT, INTERNAL. Internal errors give a short message and log the detail under the reqId.
Logging
The log records the method, the route template, the status and the time. It never records raw paths, so track ids do not become a listening history.
Route groups
| Prefix | What it does |
|---|---|
/v1/me, /v1/users/me |
Profile, liked tracks, saved albums and artists, playlists and their items, flags and pin order, history, playback events and now playing, search history, trims, daily mixes |
/v1/cache |
Encrypted audio: read with Range, write, delete, status, limit settings, missing list, background fetch jobs |
/v1/covers |
Cover art at display size |
/v1/tracks/{id}/lyrics |
Lyrics stream, a user’s own lyrics, timing offset |
/v1/lyrics |
Offsets, translator settings and translation |
/v1/recs |
Seeds, pool, rank, starters, suppressions, “Not interested”, excluded items |
/v1/tracks/{id}/radio, /alternative |
Radio and alternative sources |
/v1/match |
Matching of catalog tracks for imports and links |
/v1/imports |
Import jobs, rows, candidates, bulk actions, CSV reports |
/v1/sc |
SoundCloud search, tracks, sets, users, streams |
/v1/youtube |
Account state and preferences |
/v1/links |
Link inspection |
/v1/recognize |
Song recognition, history, tool status |
/v1/local |
Music folders, tracks, status, rescan, audio, covers |
/v1/downloads |
The save-as-files queue |
/v1/fs |
Routes only Electron main calls: they name folders or return documents for save dialogs (saved files, exports, local folders) |
/v1/recovery |
Recovery phrase, confirm, restore |
/v1/appearance, /v1/shortcuts |
Stored settings |
/v1/system |
Dependency check, network check, proxy, support report, shutdown |
/v1/lastfm |
Last.fm session and scrobbles (the app has no screen for it yet) |
/v1/explore |
Popular and most-saved lists |
Audio over the socket
GET /v1/cache/audio/{id} and GET /v1/local/tracks/{id}/audio serve Range requests. The daemon decrypts only the chunks a range needs. The renderer reaches them through the nuvo-core:// protocol that main forwards.
Stability
Routes carry /v1. Treat the API as private to Nuvo.