Sendspin Servers API
Overview
LedFx provides REST API endpoints for managing Sendspin server connections. Sendspin is a synchronized multi-room audio system; LedFx can connect to a Sendspin server as a client to receive audio for real-time visualization effects.
Base URL: http://<host>:<port>/api/sendspin/servers
Availability: Requires Python 3.12+ and the aiosendspin package installed. On Python < 3.12 or without the package, all endpoints return a 501 Not Implemented equivalent response.
Detecting Availability
Before rendering Sendspin UI, frontends should check the features.sendspin flag from GET /api/info:
{
"features": {
"sendspin": true
}
}
When sendspin is false, the backend does not support Sendspin (Python < 3.12 or aiosendspin not installed). All /api/sendspin/* endpoints will return error responses and the frontend should hide the Sendspin section entirely.
Data Model
Server Object
{
"id": "living-room",
"server_url": "ws://192.168.1.12:8927/sendspin",
"client_name": "LedFx"
}
Fields:
Field |
Type |
Required |
Default |
Description |
|---|---|---|---|---|
|
string |
Yes (URL param for update/delete) |
— |
Unique server identifier. URL-safe slug; used as the key in |
|
string |
Yes |
|
WebSocket URL of the Sendspin server. Must start with |
|
string |
No |
|
Name this client announces to the Sendspin server. |
Endpoints
List All Servers
Returns all configured Sendspin servers.
GET /api/sendspin/servers
Success Response:
{
"servers": {
"living-room": {
"server_url": "ws://192.168.1.12:8927/sendspin",
"client_name": "LedFx"
},
"office": {
"server_url": "ws://192.168.1.55:8927/sendspin",
"client_name": "LedFx-Office"
}
}
}
When no servers are configured:
{
"servers": {}
}
Sendspin unavailable (Python < 3.12 or missing package):
{
"status": "failed",
"payload": {
"type": "error",
"reason": "Sendspin is not available. Requires Python 3.12+ and aiosendspin package."
}
}
Add Server
Creates a new Sendspin server configuration and hot-reloads it into the audio system.
POST /api/sendspin/servers
Request Body:
{
"id": "living-room",
"server_url": "ws://192.168.1.12:8927/sendspin",
"client_name": "LedFx"
}
Only
idandserver_urlare required. All other fields take defaults when omitted.
Success Response:
{
"status": "success",
"payload": {
"type": "success",
"reason": "Sendspin server 'living-room' added."
}
}
Validation Errors:
Missing required field:
{
"status": "failed",
"payload": {
"type": "error",
"reason": "Required key not provided: 'server_url'"
}
}
Duplicate server ID:
{
"status": "failed",
"payload": {
"type": "error",
"reason": "Server 'living-room' already exists. Use PUT to update."
}
}
Invalid URL scheme:
{
"status": "failed",
"payload": {
"type": "error",
"reason": "server_url must start with ws:// or wss://"
}
}
Update Server
Updates an existing Sendspin server configuration and hot-reloads the change.
PUT /api/sendspin/servers/{id}
URL Parameter: id — The server identifier to update.
Request Body: Any subset of server fields to change. Fields not provided retain their current values.
{
"server_url": "ws://192.168.1.20:8927/sendspin",
"client_name": "LedFx-Updated"
}
Success Response:
{
"status": "success",
"payload": {
"type": "success",
"reason": "Sendspin server 'living-room' updated."
}
}
Server not found:
{
"status": "failed",
"payload": {
"type": "error",
"reason": "Server 'living-room' not found."
}
}
Delete Server
Removes a Sendspin server configuration and removes it from the active audio system.
DELETE /api/sendspin/servers/{id}
URL Parameter: id — The server identifier to delete.
Success Response:
{
"status": "success",
"payload": {
"type": "success",
"reason": "Sendspin server 'living-room' removed."
}
}
Server not found:
{
"status": "failed",
"payload": {
"type": "error",
"reason": "Server 'living-room' not found."
}
}
Discover Servers
Scans the local network for Sendspin servers using mDNS/DNS-SD and returns any found. Does not automatically add discovered servers — the frontend should present results and let the user add desired servers via POST /api/sendspin/servers.
GET /api/sendspin/discover
Query Parameters:
Parameter |
Type |
Default |
Description |
|---|---|---|---|
|
float |
|
Discovery scan duration in seconds. Max |
Example:
GET /api/sendspin/discover?timeout=5.0
Success Response — servers found:
{
"status": "success",
"payload": {
"type": "info",
"reason": "Discovery complete. 2 server(s) found."
},
"data": {
"servers": [
{
"name": "Sendspin Living Room",
"server_url": "ws://192.168.1.12:8927/sendspin",
"host": "192.168.1.12",
"port": 8927,
"already_configured": false
},
{
"name": "Sendspin Office",
"server_url": "ws://192.168.1.55:8927/sendspin",
"host": "192.168.1.55",
"port": 8927,
"already_configured": true
}
]
}
}
Success Response — no servers found:
{
"status": "success",
"payload": {
"type": "info",
"reason": "Discovery complete. No Sendspin servers found on the local network."
},
"data": {
"servers": []
}
}
Timeout out of range:
{
"status": "failed",
"payload": {
"type": "error",
"reason": "timeout must be between 0.1 and 30.0 seconds"
}
}
Discovery fields:
Field |
Description |
|---|---|
|
Human-readable server name announced via mDNS |
|
Fully formed WebSocket URL ready to use in |
|
IP address or hostname of the discovered server |
|
TCP port (default: |
|
|
Hot-Reload Behaviour
All mutating operations (POST, PUT, DELETE) immediately update the in-memory SENDSPIN_SERVERS dict used by the audio system without requiring a restart. Specifically:
The
config.jsonsendspin_serverskey is written.SENDSPIN_SERVERS(fromledfx.effects.audio) is updated in-place.If the currently active audio source is
SENDSPIN: {id}, changing or removing that server reconciles the active Sendspin stream (restart on URL change, stop on removal).
Note: A server appearing in
SENDSPIN_SERVERSdoes not mean LedFx is actively streaming from it. The connection is only established when the user selects that server as the active audio input device (device name format:SENDSPIN: living-room).
Config Storage
Servers are persisted in config.json under the sendspin_servers key:
{
"sendspin_servers": {
"living-room": {
"server_url": "ws://192.168.1.12:8927/sendspin",
"client_name": "LedFx"
},
"office": {
"server_url": "ws://192.168.1.55:8927/sendspin",
"client_name": "LedFx-Office"
}
}
}
File Layout
Following the one-class-per-file rule for REST endpoints:
File |
Class |
Handles |
|---|---|---|
|
|
|
|
|
|
|
|
|
Usage Examples
Add a server manually
curl -X POST http://localhost:8888/api/sendspin/servers \
-H "Content-Type: application/json" \
-d '{"id": "living-room", "server_url": "ws://192.168.1.12:8927/sendspin"}'
Auto-discover and add the first found server
# Discover
curl http://localhost:8888/api/sendspin/discover?timeout=5.0
# Add the discovered server
curl -X POST http://localhost:8888/api/sendspin/servers \
-H "Content-Type: application/json" \
-d '{"id": "my-server", "server_url": "ws://192.168.1.12:8927/sendspin"}'
Update a server URL
curl -X PUT http://localhost:8888/api/sendspin/servers/living-room \
-H "Content-Type: application/json" \
-d '{"server_url": "ws://192.168.1.20:8927/sendspin"}'
Remove a server
curl -X DELETE http://localhost:8888/api/sendspin/servers/living-room