# Music Assistant Webserver Controller API Commands: Complete Reference

> Explore Music Assistant webserver controller API commands. Learn about REST JSON-RPC, HTTP endpoints, WebSocket, and authentication for seamless integration. Get the full reference.

- Repository: [Music Assistant/server](https://github.com/music-assistant/server)
- Tags: api-reference
- Published: 2026-06-21

---

**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`](https://github.com/music-assistant/server/blob/main/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

- **WebserverController** ([`music_assistant/controllers/webserver/controller.py`](https://github.com/music-assistant/server/blob/main/music_assistant/controllers/webserver/controller.py)): Starts a configurable `Webserver` instance, registers static assets (frontend, logo, CSS), adds dynamic routes, and wires all API endpoints. It coordinates authentication, remote access, and SendSpin proxy handling.
- **Webserver Helper** ([`music_assistant/helpers/webserver.py`](https://github.com/music-assistant/server/blob/main/music_assistant/helpers/webserver.py)): A thin wrapper around `aiohttp.web.Application` that supports dynamic route registration and static file serving.
- **Authentication Manager** ([`music_assistant/controllers/webserver/auth.py`](https://github.com/music-assistant/server/blob/main/music_assistant/controllers/webserver/auth.py)): Issues and validates bearer tokens stored hashed in an SQLite table, working with middleware in [`helpers/auth_middleware.py`](https://github.com/music-assistant/server/blob/main/helpers/auth_middleware.py) to inject user contexts into requests via `set_current_user`.
- **WebSocket Handler** ([`music_assistant/controllers/webserver/websocket_client.py`](https://github.com/music-assistant/server/blob/main/music_assistant/controllers/webserver/websocket_client.py)): Manages persistent connections to the `/ws` endpoint, wrapping each connection in a `WebsocketClientHandler` for bidirectional JSON-RPC communication and event streaming.

### 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`](https://github.com/music-assistant/server/blob/main/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`](https://github.com/music-assistant/server/blob/main/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`](https://github.com/music-assistant/server/blob/main/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`](https://github.com/music-assistant/server/blob/main/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`](https://github.com/music-assistant/server/blob/main/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

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

```

**Response:**

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

```

### Executing a JSON-RPC Command

```bash
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)

```bash
curl http://localhost:8095/info

```

**Response:**

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

```

### WebSocket Client Implementation

```python
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

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

```

## Summary

- The **WebserverController** in [`music_assistant/controllers/webserver/controller.py`](https://github.com/music-assistant/server/blob/main/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`](https://github.com/music-assistant/server/blob/main/helpers/auth_middleware.py) and managed by [`auth.py`](https://github.com/music-assistant/server/blob/main/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`](https://github.com/music-assistant/server/blob/main//api-docs/commands.json) and `/api-docs/*`. These are generated on-the-fly by [`api_docs.py`](https://github.com/music-assistant/server/blob/main/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.