24 KiB
Airsonic-Pulse API Reference
Airsonic-Pulse exposes a music-streaming API that is compatible with the Subsonic API and implements a growing set of OpenSubsonic extensions. This document is generated from the codebase and reflects the actual state of the implemented endpoints.
- Subsonic protocol version reported:
1.16.1 - Server type:
airsonic-pulse - OpenSubsonic: advertised (
openSubsonic=true,serverVersionpresent)
API surfaces
Airsonic-Pulse serves three overlapping API surfaces:
- Subsonic — the standard Subsonic API. Airsonic-Pulse implements the complete Subsonic 1.16.1 endpoint surface.
- OpenSubsonic — the OpenSubsonic extensions: a compliant response envelope, the
getOpenSubsonicExtensionsdiscovery endpoint, additional endpoints, and enrichment fields layered onto existing Subsonic response types. - Native — Airsonic-Pulse specific endpoints that are not part of the Subsonic or OpenSubsonic specifications.
Endpoints and paths
All Subsonic/OpenSubsonic endpoints are served under both /rest/<endpoint> and /rest/<endpoint>.view, and accept both GET and POST (formPost extension). Most endpoints are also mapped under /ext/<endpoint> for JWT-authenticated external/share access. Response format is selected with the f request parameter (xml, json, or jsonp).
Authentication
Standard Subsonic authentication parameters apply to all /rest/** endpoints (u plus p, or u plus t+s token/salt). getOpenSubsonicExtensions is the only endpoint that does not require authentication. Removal of legacy authentication methods and an apiKeyAuthentication extension are planned — see #56 and #145.
How the endpoints were organized
The Subsonic API began as a single SubsonicRESTController monolith and was split into 16 domain controllers under tracking issue #34, with cross-cutting follow-ups for exception handling (#98), a shared base class (#112), and a hygiene sweep (#176). The endpoint reference below is a single table grouped by the Domain column. The Ref column lists the issue(s) that implemented or updated that specific endpoint — typically the controller-extraction issue that moved it, plus any endpoint-specific functional change.
Status legend
| Symbol | Meaning |
|---|---|
| ✅ | Implemented — fully working in the current codebase |
| 🔧 | Partial — exists but incomplete or with known limitations |
| 🚧 | In Progress — actively being worked on |
| 📋 | Planned — on the roadmap / tracked by an open issue |
| ❌ | Not Planned — no plans to implement |
API Type: Subsonic (standard spec) · OpenSubsonic (extension or new endpoint) · Native (Airsonic-Pulse specific) · Legacy (deprecated / slated for removal).
Airsonic-Pulse registers the complete Subsonic 1.16.1 endpoint surface — there are no entirely-absent Subsonic endpoints. The only functional caveats are getVideoInfo (🔧 routed but not implemented) and the chat endpoints (❌ intentionally unsupported).
Endpoint reference
| Endpoint | Domain | Controller | Status | API Type | Ref | Notes |
|---|---|---|---|---|---|---|
ping |
System | SubsonicSystemController |
✅ | Subsonic | #69 | |
getLicense |
System | SubsonicSystemController |
✅ | Subsonic | #69 | Always returns a valid license (Airsonic-Pulse is free) |
startScan |
System | SubsonicSystemController |
✅ | Subsonic | #69 | Requires ADMIN role |
getScanStatus |
System | SubsonicSystemController |
✅ | Subsonic | #69 | |
getOpenSubsonicExtensions |
System | SubsonicRESTController |
✅ | OpenSubsonic | #66, #132, #141 | Extension discovery; no auth required. Declares formPost, transcodeOffset, songLyrics, indexBasedQueue |
tokenInfo |
System | — | ❌ | OpenSubsonic | — | Related to the apiKeyAuthentication extension (#145); no tracking issue yet |
getChatMessages |
Chat | SubsonicSystemController |
❌ | Subsonic | #69 | Stub — returns error "Chat messages are not supported on this server" |
addChatMessage |
Chat | SubsonicSystemController |
❌ | Subsonic | #69 | Stub — returns error "Posting chat messages is not supported on this server" |
getMusicFolders |
Browsing | SubsonicBrowsingController |
✅ | Subsonic | #71 | |
getIndexes |
Browsing | SubsonicBrowsingController |
✅ | Subsonic | #71 | |
getMusicDirectory |
Browsing | SubsonicBrowsingController |
✅ | Subsonic | #71 | |
getGenres |
Browsing | SubsonicBrowsingController |
✅ | Subsonic | #71 | |
getVideos |
Browsing | SubsonicBrowsingController |
✅ | Subsonic | #71 | |
getVideoInfo |
Browsing | SubsonicBrowsingController |
🔧 | Subsonic | #71, #59 | Registered but not implemented — returns a structured error envelope |
getNowPlaying |
Browsing | SubsonicBrowsingController |
✅ | Subsonic | #71 | |
getAlbumList |
Browsing | SubsonicBrowsingController |
✅ | Subsonic | #71 | |
getRandomSongs |
Browsing | SubsonicBrowsingController |
✅ | Subsonic | #71 | |
getSongsByGenre |
Browsing | SubsonicBrowsingController |
✅ | Subsonic | #71 | |
getArtists |
Browsing (ID3) | SubsonicID3Controller |
✅ | Subsonic | #80, #137, #138 | ArtistID3 carries OpenSubsonic musicBrainzId, sortName |
getArtist |
Browsing (ID3) | SubsonicID3Controller |
✅ | Subsonic | #80, #137, #138 | ArtistID3 carries OpenSubsonic musicBrainzId, sortName |
getAlbum |
Browsing (ID3) | SubsonicID3Controller |
✅ | Subsonic | #80, #129, #130, #136 | OpenSubsonic AlbumID3 metadata bundle pending (#142) |
getSong |
Browsing (ID3) | SubsonicID3Controller |
✅ | Subsonic | #80, #129, #130, #134, #135, #139, #143 | Child carries OpenSubsonic enrichments; contributors[] still pending (#144) |
getAlbumList2 |
Browsing (ID3) | SubsonicID3Controller |
✅ | Subsonic | #80 | |
getSimilarSongs |
Album/Artist info | SubsonicArtistInfoController |
✅ | Subsonic | #106 | |
getSimilarSongs2 |
Album/Artist info | SubsonicArtistInfoController |
✅ | Subsonic | #106 | |
getTopSongs |
Album/Artist info | SubsonicArtistInfoController |
✅ | Subsonic | #106 | |
getArtistInfo |
Album/Artist info | SubsonicArtistInfoController |
✅ | Subsonic | #106 | |
getArtistInfo2 |
Album/Artist info | SubsonicArtistInfoController |
✅ | Subsonic | #106 | |
getAlbumInfo |
Album/Artist info | SubsonicArtistInfoController |
✅ | Subsonic | #106 | |
getAlbumInfo2 |
Album/Artist info | SubsonicArtistInfoController |
✅ | Subsonic | #106 | |
search |
Search | SubsonicSearchController |
✅ | Subsonic | #85, #178, #55 | Legacy search; superseded by search2/search3. Security review of query handling open (#178) |
search2 |
Search | SubsonicSearchController |
✅ | Subsonic | #85 | |
search3 |
Search | SubsonicSearchController |
✅ | Subsonic | #85 | |
star |
Annotation | SubsonicAnnotationController |
✅ | Subsonic | #89 | |
unstar |
Annotation | SubsonicAnnotationController |
✅ | Subsonic | #89 | |
setRating |
Annotation | SubsonicAnnotationController |
✅ | Subsonic | #89 | |
scrobble |
Annotation | SubsonicAnnotationController |
✅ | Subsonic | #89 | |
getStarred |
Annotation | SubsonicAnnotationController |
✅ | Subsonic | #89 | |
getStarred2 |
Annotation | SubsonicAnnotationController |
✅ | Subsonic | #89 | |
stream |
Media retrieval | SubsonicMediaController |
✅ | Subsonic | #110, #117, #132 | Supports transcodeOffset (timeOffset); known timeOffset bug across playqueue (#177) |
download |
Media retrieval | SubsonicMediaController |
✅ | Subsonic | #110 | |
hls |
Media retrieval | SubsonicMediaController |
✅ | Subsonic | #110 | HLS segment playlist |
getCoverArt |
Media retrieval | SubsonicMediaController |
✅ | Subsonic | #110 | |
getAvatar |
Media retrieval | SubsonicMediaController |
✅ | Subsonic | #110, #115 | Content-Type fix |
getLyrics |
Media retrieval | SubsonicMediaController |
✅ | Subsonic | #110 | |
getLyricsBySongId |
Media retrieval | SubsonicMediaController |
✅ | OpenSubsonic | #110, #131, #157, #158 | songLyrics extension (unsynced, read from tags at request time). Synced/LRC + DB storage planned (#140) |
getCaptions |
Media retrieval | SubsonicMediaController |
✅ | Subsonic | #110, #59 | Error-envelope fix |
getPlaylists |
Playlists | SubsonicPlaylistController |
✅ | Subsonic | #104 | |
getPlaylist |
Playlists | SubsonicPlaylistController |
✅ | Subsonic | #104 | |
createPlaylist |
Playlists | SubsonicPlaylistController |
✅ | Subsonic | #104 | |
updatePlaylist |
Playlists | SubsonicPlaylistController |
✅ | Subsonic | #104 | |
deletePlaylist |
Playlists | SubsonicPlaylistController |
✅ | Subsonic | #104 | |
getPlayQueue |
Play queue | SubsonicPlayQueueController |
✅ | Subsonic | #91 | |
savePlayQueue |
Play queue | SubsonicPlayQueueController |
✅ | Subsonic | #91 | |
getPlayQueueByIndex |
Play queue | SubsonicPlayQueueController |
✅ | OpenSubsonic | #141 | indexBasedQueue extension |
savePlayQueueByIndex |
Play queue | SubsonicPlayQueueController |
✅ | OpenSubsonic | #141 | indexBasedQueue extension |
getBookmarks |
Bookmarks | SubsonicBookmarkController |
✅ | Subsonic | #93 | |
createBookmark |
Bookmarks | SubsonicBookmarkController |
✅ | Subsonic | #93 | |
deleteBookmark |
Bookmarks | SubsonicBookmarkController |
✅ | Subsonic | #93 | |
getShares |
Sharing | SubsonicShareController |
✅ | Subsonic | #95 | |
createShare |
Sharing | SubsonicShareController |
✅ | Subsonic | #95 | |
updateShare |
Sharing | SubsonicShareController |
✅ | Subsonic | #95 | |
deleteShare |
Sharing | SubsonicShareController |
✅ | Subsonic | #95 | |
getPodcasts |
Podcasts | SubsonicPodcastController |
✅ | Subsonic | #97 | |
getNewestPodcasts |
Podcasts | SubsonicPodcastController |
✅ | Subsonic | #97 | |
getPodcastEpisode |
Podcasts | SubsonicPodcastController |
✅ | OpenSubsonic | #97, #133 | Not in the Subsonic spec; OpenSubsonic addition |
refreshPodcasts |
Podcasts | SubsonicPodcastController |
✅ | Subsonic | #97 | |
createPodcastChannel |
Podcasts | SubsonicPodcastController |
✅ | Subsonic | #97 | |
deletePodcastChannel |
Podcasts | SubsonicPodcastController |
✅ | Subsonic | #97 | |
deletePodcastEpisode |
Podcasts | SubsonicPodcastController |
✅ | Subsonic | #97 | |
downloadPodcastEpisode |
Podcasts | SubsonicPodcastController |
✅ | Subsonic | #97 | |
exportPodcasts/opml |
Podcasts | SubsonicPodcastController |
✅ | Native | #97 | Airsonic OPML export; not part of the Subsonic or OpenSubsonic spec |
getInternetRadioStations |
Internet radio | SubsonicRadioController |
✅ | Subsonic | #100 | |
createInternetRadioStation |
Internet radio | SubsonicRadioController |
✅ | Subsonic | #100, #123 | Subsonic 1.16.0 CRUD (admin-only) |
updateInternetRadioStation |
Internet radio | SubsonicRadioController |
✅ | Subsonic | #100, #123 | Subsonic 1.16.0 CRUD (admin-only) |
deleteInternetRadioStation |
Internet radio | SubsonicRadioController |
✅ | Subsonic | #100, #123 | Subsonic 1.16.0 CRUD (admin-only) |
jukeboxControl |
Jukebox | SubsonicJukeboxController |
✅ | Subsonic | #102 | Direct audio output to the server sound card |
changePassword |
User management | SubsonicUserController |
✅ | Subsonic | #108 | |
getUser |
User management | SubsonicUserController |
✅ | Subsonic | #108 | |
getUsers |
User management | SubsonicUserController |
✅ | Subsonic | #108 | |
createUser |
User management | SubsonicUserController |
✅ | Subsonic | #108 | |
updateUser |
User management | SubsonicUserController |
✅ | Subsonic | #108, #57 | streamRole mapping bug fixed |
deleteUser |
User management | SubsonicUserController |
✅ | Subsonic | #108 |
OpenSubsonic capabilities (non-endpoint)
The items in this section are part of OpenSubsonic compliance but are not callable endpoints — they are the response envelope, the capability flags advertised through getOpenSubsonicExtensions, and enrichment fields added to existing Subsonic responses. The OpenSubsonic-specific endpoints themselves (getOpenSubsonicExtensions, getLyricsBySongId, getPodcastEpisode, getPlayQueueByIndex, savePlayQueueByIndex) appear in the endpoint reference above with API Type OpenSubsonic. Tracking issue: #35 — Implement OpenSubsonic API support.
Base compliance — ✅ Implemented
- Response envelope advertises
openSubsonic=true,type="airsonic-pulse", andserverVersion(#64). - Protocol version reported as
1.16.1(#113). - Extension discovery available via the
getOpenSubsonicExtensionsendpoint (#66).
Declared extension flags — ✅ Implemented
These are returned by getOpenSubsonicExtensions:
| Extension | Version | Status | Ref | Notes |
|---|---|---|---|---|
formPost |
1 | ✅ | #66 | All endpoints accept POST |
transcodeOffset |
1 | ✅ | #132 | stream accepts a transcode time offset |
songLyrics |
1 | ✅ | #131, #157, #158 | getLyricsBySongId; unsynced lyrics read from tags at request time |
indexBasedQueue |
1 | ✅ | #141 | Adds getPlayQueueByIndex / savePlayQueueByIndex |
Response field enrichments — ✅ Implemented
| Type | Fields | Ref |
|---|---|---|
Child |
played, musicBrainzId, displayArtist, displayAlbumArtist, mediaType, sortName, bpm, genres[], replayGain |
#129, #130, #134, #135, #139, #143 |
AlbumID3 |
played, playCount, musicBrainzId, displayArtist, sortName |
#129, #130, #136 |
ArtistID3 |
musicBrainzId, sortName, mediaType |
#130, #137, #138 |
Artist (legacy, returned by getIndexes / getStarred) |
userRating, averageRating |
#179 |
Response field enrichments — 📋 Planned
| Item | Ref |
|---|---|
contributors[] — multi-role contributor extraction |
#144 |
AlbumID3 bundle — isCompilation, releaseTypes, originalReleaseDate, discTitles, recordLabels |
#142 |
songLyrics — synced / LRC support with DB storage |
#140 |
Capability extensions — 📋 Planned (not yet declared)
| Extension | Ref | Notes |
|---|---|---|
apiKeyAuthentication |
#145 | Tied to removal of legacy authentication (#56); would add the tokenInfo endpoint (see the endpoint reference) |
Response fields — ❌ Not currently planned
These OpenSubsonic response fields exist in the specification but have no tracking issue yet:
- Audio-detail
Childfields:bitDepth,samplingRate,channelCount. Child.moods[],explicitStatus.
References
- Subsonic API specification: http://www.subsonic.org/pages/api.jsp
- OpenSubsonic specification: https://opensubsonic.netlify.app/
- OpenSubsonic tracking issue (this project): #35