Music Assistant Webserver Controller API Commands: Complete Reference

The Music Assistant webserver controller exposes a REST/JSON-RPC API via aiohttp, supporting HTTP endpoints, WebSocket real-time communication, and dynamic authentication, with endpoints defined in controller.py and handlers registered in self.mass.command_handlers.

The Music Assistant server provides a comprehensive HTTP and WebSocket API for controlling media playback, managing libraries, and configuring players. Located in the music-assistant/server repository, the WebserverController serves as the central entry point that marshals all client requests through a secure, token-based authentication layer. This article explores the architecture, endpoints, and practical usage of the Music Assistant webserver controller API commands based on the current implementation in the dev branch.

Architecture Overview

The WebserverController acts as the central HTTP and WebSocket entry point, running on top of aiohttp and exposing a fully-featured REST/JSON-RPC API. All endpoints add permissive CORS headers (*) to allow calling from any origin.

Core Components

Request Flow

  1. Startup: WebserverController.setup() builds static routes for frontend files, logos, and info endpoints, registering them on a Webserver instance.
  2. Authentication: Middleware extracts bearer tokens, validates them against the auth_tokens table, and injects a User object into the request context.
  3. JSON-RPC Processing: The _handle_jsonrpc_api_command method receives CommandMessage objects at /api, dispatches them to self.mass.command_handlers[command], checks required roles, and returns JSON results.
  4. WebSocket Upgrade: The /ws endpoint creates a WebsocketClientHandler that streams events (e.g., player_state_updated) automatically to connected clients.

API Endpoints and Commands

JSON-RPC Command Endpoint (POST /api)

The primary API surface for executing commands. The _handle_jsonrpc_api_command method in controller.py parses incoming JSON payloads into CommandMessage instances (defined in music_assistant_models.api) and routes them to the appropriate handler registered in self.mass.command_handlers.

WebSocket Real-Time API (GET /ws)

Clients connect to /ws for bidirectional communication. The WebsocketClientHandler forwards incoming JSON-RPC messages over the socket and pushes server events without client polling, enabling real-time updates for player state changes.

Setup and Onboarding (POST /setup)

When no admin user exists, the server runs in setup mode and redirects all non-ingress requests to /setup. The _handle_setup endpoint creates the first admin account and returns a bearer token for subsequent authentication.

Preview Streaming (GET /preview)

The serve_preview_stream function in controller.py handles /preview?provider=…&item_id=…, returning short AAC audio snippets (typically ~30 seconds) for tracks without requiring full library access.

Server Information (GET /info)

Returns server version, uptime seconds, and lists of connected players and providers. This endpoint does not require authentication.

SendSpin Proxy

An authenticated WebSocket proxy to the internal SendSpin server (used by certain players) is handled by sendspin_proxy.py, providing relay functionality for specific player protocols.

Authentication Implementation

Authentication is managed by the AuthenticationManager with tokens stored hashed in SQLite. The auth_middleware.py validates tokens on every protected request and supports the builtin provider (username/password) and Home Assistant OAuth integration via auth_providers.py.

  • Setup Mode: Until an admin exists, the server restricts access to setup endpoints only.
  • Token Format: JWT-style bearer tokens returned as Authorization: Bearer <token> in the HTTP header.
  • Role-Based Access Control: Commands declare required roles, which are validated before handler execution.

Practical Code Examples

Obtaining an Authentication Token

curl -X POST http://localhost:8095/auth/login \
     -H "Content-Type: application/json" \
     -d '{"provider_id":"builtin","credentials":{"username":"admin","password":"mySecretPwd"}}'

Response:

{
  "success": true,
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…",
  "user": { "user_id": "c4e3…", "username": "admin", "role": "admin" }
}

Executing a JSON-RPC Command

curl -X POST http://localhost:8095/api \
     -H "Authorization: Bearer <TOKEN>" \
     -H "Content-Type: application/json" \
     -d '{
           "command": "media_library.search",
           "args": { "search_term": "Beatles", "media_type": "track" },
           "message_id": "req-001"
         }'

Retrieving Server Information (No Auth Required)

curl http://localhost:8095/info

Response:

{
  "version": "2026.1.0",
  "uptime": 34212,
  "players": [ … ],
  "providers": [ … ]
}

WebSocket Client Implementation

import websockets
import json
import asyncio

async def demo():
    async with websockets.connect('ws://localhost:8095/ws') as ws:
        # Send JSON-RPC command

        await ws.send(json.dumps({
            "command": "player.play",
            "args": {"player_id": "my_player"},
            "message_id": "ws-001"
        }))
        reply = await ws.recv()
        print('Received:', reply)

asyncio.run(demo())

Streaming Audio Previews

curl http://localhost:8095/preview?provider=spotify&item_id=track-123 \
     -o preview.aac

Summary

  • The WebserverController in music_assistant/controllers/webserver/controller.py manages all HTTP and WebSocket traffic for the Music Assistant server.
  • JSON-RPC commands are dispatched via POST /api to handlers registered in self.mass.command_handlers, with role validation performed by the controller.
  • WebSocket connections at /ws provide real-time bidirectional communication through WebsocketClientHandler, automatically pushing events like player_state_updated.
  • Authentication uses bearer tokens validated by middleware in helpers/auth_middleware.py and managed by auth.py, with support for builtin and OAuth providers.
  • Setup mode restricts access to /setup until an admin user is created via the _handle_setup endpoint.
  • Preview streams and server info endpoints provide additional functionality, with /preview serving short AAC clips via serve_preview_stream and /info providing anonymous server status.

Frequently Asked Questions

How do I authenticate with the Music Assistant API?

Send a POST request to /auth/login with a JSON body containing provider_id (e.g., "builtin" ) and credentials object with username and password. The response includes a bearer token that must be included as Authorization: Bearer <token> in subsequent requests to protected endpoints.

What is the difference between the HTTP API and WebSocket API?

The HTTP API at /api handles stateless JSON-RPC commands using the _handle_jsonrpc_api_command method, while the WebSocket endpoint /ws maintains persistent connections managed by WebsocketClientHandler for real-time bidirectional communication, automatically pushing events like player state changes without requiring client polling.

Where can I find the list of available API commands?

The server dynamically generates OpenAPI specifications and a complete command list with schemas, accessible at /api-docs/commands.json and /api-docs/*. These are generated on-the-fly by api_docs.py from the registered command handlers in self.mass.command_handlers.

How does the initial setup process work via the API?

When the server has no admin user, it enters setup mode and redirects all requests to /setup. You must send a POST request to /setup to create the first admin account, which returns an initial authentication token. After this setup completes, the server exits setup mode and normal API access is permitted with the issued token.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →