The Companion API lets small tools, hardware controllers, dashboards, and automations work with a running Astra desktop app. It is deliberately bounded: clients can observe and control playback, search for named library items, act on opaque references, edit the upcoming queue, set favorites, and maintain local normal playlists. It is not a replacement Astra client and cannot browse the whole catalog or retrieve audio files.
The API is disabled by default. Existing /v1 integrations continue to work unchanged.
In Astra, open Settings → Integrations → Local API and enable the API. The bearer token shown there works only on 127.0.0.1. Observation is granted when the API is enabled; playback control, library search, and library writes each have a separate switch and are off until enabled.
export ASTRA_API_URL=http://127.0.0.1:38401
export ASTRA_API_TOKEN='token copied from Astra settings'
curl -H "Authorization: Bearer $ASTRA_API_TOKEN" "$ASTRA_API_URL/v2/capabilities"LAN clients use Astra's pinned-HTTPS pairing flow. A client requests companion scopes and the person at Astra approves a subset for that device. Each paired credential can be revoked, expires after inactivity, and follows the existing rotation policy. There is no copyable LAN master token.
| Scope | Access |
|---|---|
observe |
Capabilities, playback, queue, artwork, and playback/queue events |
playback-control |
Playback actions, play/enqueue intents, and upcoming-queue edits |
library-search |
Bounded search, open intents, and favorite/playlist event topics |
library-write |
Explicit favorite state and locally owned normal playlist changes |
Use GET /v2/capabilities after connecting. It reports the transport, actual granted scopes, feature flags, and current limits instead of requiring clients to guess.
Search and playback responses use signed opaque AstraRef strings for tracks, albums, artists, and playlists. Treat a reference as an indivisible value: do not parse it, construct it, or persist it as a permanent library identifier. A valid reference may later return 404 if its target was deleted.
Public responses do not include filesystem paths, source IDs, credentials, raw artwork hashes, or audio streams. Artwork URLs return bounded thumbnails only. Search requires a non-empty query, defaults to 20 results, caps at 50, and has no pagination or empty-query catalog mode.
- Send
Authorization: Bearer <token>on every endpoint exceptGET /v2/openapi.json. - JSON errors are always shaped as
{ "error": { "code": "...", "message": "..." } }. - Timestamps are Unix epoch milliseconds. Playback positions and media durations are seconds.
- Renderer-executed playback, intent, and queue commands return
202 Accepted. A202means Astra accepted the command, not that playback has already changed. - If Astra's renderer is not ready, renderer-executed commands return
503 renderer_unavailable. - State-setting actions (
set-volume,set-muted,set-shuffle, andset-repeat) and favorite writes explicitly set state and are safe to retry. - JSON request bodies are capped at 64 KiB. Playlist additions accept 1–100 track references per request.
- CORS preflight is supported without cookies or credentialed CORS. Credentials still belong in the bearer header.
- Rate limits are per credential. At most eight v2 event streams may be connected at once.
GET /v2/events is a server-sent event stream. It accepts comma-separated topics=playback,queue,favorite,playlist. The favorite and playlist topics require library-search; unavailable topics are omitted from the stream.
Discrete playback and library changes are sent immediately. Position-only playback updates default to once per second. Set positionIntervalMs to an integer from 250 through 5000 to choose another interval.
event: playback
data: {"state":"playing","positionSeconds":12.4,...}
The examples use only the standard runtimes—no package install is required.
node docs/api/examples/observe.mjs
node docs/api/examples/search-to-play.mjs "Blue in Green"
node docs/api/examples/queue.mjs "Boards of Canada"
python3 docs/api/examples/playlist-generator.py "Morning Mix" "Nujabes" "Tycho" "Bonobo"- Observe playback with SSE
- Search and play a result
- Search and enqueue results
- Generate a normal playlist
- OpenAPI 3.1 contract
The served contract is available without authentication at GET /v2/openapi.json.
v2 does not expose pageable library browsing, collection contents, filesystem paths, audio streaming, metadata editing, scans or folders, remote-source administration, settings, DSP/EQ, visualizer samples, lyrics, playlist deletion, or dynamic-playlist rules. Library writes are limited to favorites and locally owned normal playlists; mirrored and dynamic playlists reject edits.