Playlist write access in the Extension API

I want to make a case for one specific gap in the Extension API, because I think the demand for it is about to grow quickly.

The gap. The Extension API can browse the entire hierarchy and it can control transport, but it cannot write a playlist. Walking the browse hierarchy with node-roon-api-browse, every action list I can reach — at album level and at track level, on library content and on Qobuz content — offers exactly four actions:

Play Now · Add Next · Queue · Start Radio

There is no “Add to Playlist”, no create-playlist call, and no way to reach the menu that the Roon Remote UI exposes for exactly this. RoonApiBrowse has no write surface, and there is no RoonApiPlaylist service.

Why this matters more now than it did in 2017. The Extension API was designed around control surfaces and audio devices, and for that it’s excellent. But the thing people increasingly want to automate is curation, and LLM-based assistants have made that suddenly practical. A concrete example from this week: I had a ranked list of 50 albums and wanted it as a Roon playlist, preferring Qobuz over my own files wherever my local copy was a lossy rip. Everything about that is easy — identify the albums, scan my library to find which local copies are MP3, resolve each album in Roon’s search. Every step worked through the API. The last step, “now save that as a playlist”, is the only one that’s impossible, and it’s the one that turns the work into something I can actually use.

The workarounds don’t cover it:

  • M3U import works, but M3U can only reference local file paths. It cannot express a Qobuz track, so it’s useless for any playlist that draws on streaming — which is most of them, for most subscribers.

  • Queueing via the API plays the right thing once, but a queue isn’t a playlist.

  • Doing it by hand in Remote is 50 albums of clicking, which is precisely the thing worth automating.

What I’m asking for, roughly in order of how much I’d value it:

  1. Create a playlist, and append tracks or albums to it, by the same item keys the browse hierarchy already hands out. That alone unlocks nearly everything.

  2. The same for Tags — Roon’s tag system is arguably a better fit for machine-built collections than playlists are, and it has the same read-only limitation today.

  3. Optionally: remove/reorder within a playlist, and delete a playlist.

Read access to playlist contents would be a welcome bonus, but write is the blocker.

I’d also note that this is a natural fit for the existing extension trust model — extensions already require explicit enabling in Settings → Extensions, so a playlist-write permission has an obvious place to live and an obvious consent gate. It wouldn’t need a new security story.

I recognize there may be good architectural reasons this hasn’t happened, and I’d genuinely be interested to hear them if so. But from outside, this looks like a small addition to an API that already knows how to identify every item involved — and it’s the difference between the Extension API being a remote-control protocol and it being a real automation surface.


Update: I found a workaround, posting it here so the next person doesn’t dead-end. The short version: you can’t write a playlist through Roon, but you can write one into your streaming service’s account, and Roon will sync it in.

The workaround (Qobuz, but the pattern generalizes):

  1. Build the playlist in your Qobuz account, not in Roon. Roon syncs your Qobuz playlists automatically: they appear under Qobuz → My Qobuz → My Playlists, and from there Add to Library makes it a first-class playlist. Force an immediate pickup via Settings → Services → Qobuz → Edit → Sync library now.

  2. Qobuz has no public API, but the web player’s own REST API works with your session.

    • Log into play.qobuz.com. Your auth token is in DevTools → Application → Local Storage → localuser → the token field.

    • API base: https://www.qobuz.com/api.json/0.2/. Auth is two request headers: X-App-Id and X-User-Auth-Token. Parameters go in the URL query string, even on POST.

    • :warning: The app_id embedded in the current web player bundle may not be the one your token authenticates against — mine returned 401 with the bundle’s id and worked with a known older web-player id. If you get 401 “User authentication is required”, try other published app ids before assuming your token is wrong.

    • The endpoints you need: playlist/create (pass is_public=false), album/search (query), album/get (album_id → tracks.items[].id), playlist/addTracks (playlist_id + comma-separated track_ids + no_duplicate=true), and playlist/delete. Append album-by-album in order and the playlist keeps your sequence.

    • Pace requests (~1/sec is safe); playlists cap at 2,000 tracks.

  3. Watch the edition trap. Match search results by expected track count, not title: the plain-titled entry is sometimes the deluxe box (for one album the plain title was a 65-track set and the “45th Anniversary” entry was the actual 11-track album). If only a deluxe exists, album/get returns disc order — adding just the first N track ids gets you the album proper.

Limits: tracks that only exist as local files can’t be inserted this way (Qobuz can’t reference them) — those still need a manual edit in Roon afterwards. And this is an unofficial API: treat it gently and expect it to change without notice.

None of this replaces the actual ask — playlist create/append in the supported Extension API — but it unblocks the use case today.

1 Like