Version: 5.0.0

# Visibox API

Visibox exposes a local network API that enables remote control, automation, and custom integrations. This page is a developer reference — if you want to use Visibox through an AI assistant or a shell, see [AI Assistants](https://manual.spaceage.tv/5.0.0/integrations/ai/) or [Command Line Interface](https://manual.spaceage.tv/5.0.0/integrations/cli/) instead.

note

API access requires a Pro plan with the API entitlement.

## Overview

The API runs in a separate process for stability — if your integration misbehaves, it will not affect Visibox itself. Three services are available:

| Service | Port | Protocol | Description |
| --- | --- | --- | --- |
| **WebSocket** | 51734 | `ws://` | Real-time bidirectional communication. State updates are pushed to connected clients instantly. |
| **HTTP REST** | 51736 | `http://` | Standard request/response for querying state and sending commands. |
| **OSC** | 51735 | UDP | Open Sound Control (coming soon). |

All services bind to all network interfaces on the machine, so any device on the same local network can connect.

### Service Discovery

Visibox advertises itself on the local network using Bonjour (mDNS/DNS-SD). Applications can discover Visibox automatically without knowing its IP address:

| Service Type | Description |
| --- | --- |
| `_visibox._tcp` | WebSocket API |
| `_http._tcp` | HTTP REST API |

The advertised TXT records include the API version, hostname, platform, and port numbers.

## Authentication

### Localhost (Same Machine)

Connections from `127.0.0.1` or `::1` (localhost) are automatically authenticated. No pairing or token is needed. This enables integrations running on the same machine — like the Stream Deck plugin, the CLI, and the MCP server — to connect seamlessly.

The localhost authentication exemption can be configured via the `localhostAuthExempt` setting in the API configuration. It is enabled by default.

### Remote Devices (Pairing)

Devices connecting over the network must pair first using a one-time code. Open the [Remote Pairing](https://manual.spaceage.tv/5.0.0/integrations/remote-pairing/) window (Window > Remote Pairing), where a 6-digit code is displayed. Enter this code on the remote device to establish a connection. Tokens are valid for 30 days.

Once paired, the remote device includes the token in every request — either as an `Authorization: Bearer <token>` HTTP header, or in the initial WebSocket `auth` message.

See [Remote Pairing](https://manual.spaceage.tv/5.0.0/integrations/remote-pairing/) for full details.

## HTTP REST API

Base URL: `http://<visibox-ip>:51736`

### Health Check

```
GET /health
```

Returns a simple status response. No authentication required. Useful for verifying the API is running.

### API Info

```
GET /api/info
```

Returns the API version and a list of available endpoints.

### Pairing

```
POST /api/pair
```

Exchange a 6-digit OTP code for a JWT token:

```
{  "otp": "123456"}
```

Returns:

```
{  "token": "eyJhbGciOi..."}
```

### Projects

```
GET /api/projects
```

List all open Projects with their IDs, names, song counts, and which one is active.

```
GET /api/projects/:projectId
```

Get full data for a specific Project — all Songs, Clips, files, Effects, Visualizers, and display options.

```
GET /api/projects/:projectId/playstate
```

Get the current playback state — which Clips are playing, their positions, durations, and directions.

```
GET /api/active
```

A convenience endpoint that returns the active Project and its playback state in a single request.

#### Drill-Down Endpoints

For granular access to specific parts of a Project without fetching the entire data structure:

```
GET /api/projects/:projectId/songs
```

List all Songs in a Project with their IDs, titles, clip counts, and audio info.

```
GET /api/projects/:projectId/songs/:songId
```

Get full data for a specific Song — all Clips, audio settings, and metadata.

```
GET /api/projects/:projectId/songs/:songId/clips/:clipId
```

Get data for a specific Clip — file info, options, effects, and current state.

```
GET /api/projects/:projectId/effects
```

List all Effects in a Project with their IDs, names, types, and linked status.

```
GET /api/projects/:projectId/visualizers
```

List all Visualizers in a Project with their IDs, names, engines, and linked status.

### Media

```
GET /thumbnails/:projectId/:fileId.jpg
```

Get a Clip’s thumbnail image. Optional query parameters:

| Parameter | Default | Description |
| --- | --- | --- |
| `size` | original | Square output size in pixels (16–512). |
| `overlay` | none | Overlay icon: `play`, `pause`, or `none`. |
| `format` | jpeg | Output format: `jpeg` or `png`. |
| `quality` | 85 | JPEG quality (1–100). |

```
GET /waveforms/:projectId/:fileId.png
```

Get a waveform image for an audio file.

### Cameras

```
GET /api/cameras
```

List available cameras with their device IDs and labels.

```
GET /camera-thumbnails/:cameraId.jpg
```

Get a live camera thumbnail (updated every 5 seconds when the camera is active). Use `default` as the camera ID to get the default camera.

### Sending Commands

```
POST /api/v1/action
```

Send a playback or system action. The request body specifies the action name and parameters:

```
{  "action": {    "name": "PlayClipByIndexAction",    "params": ["0", "1"]  }}
```

```
POST /api/v1/edit
```

Send a project edit (add/remove/modify Songs, Clips, Effects, or Visualizers).

## WebSocket API

Connect to: `ws://<visibox-ip>:51734`

The WebSocket API provides real-time, bidirectional communication. Connect once, authenticate, and you will receive state updates pushed instantly as things change in Visibox — no polling required.

### Connecting

After establishing the WebSocket connection, send an `auth` message:

```
{  "type": "auth",  "payload": {    "token": "your-jwt-token"  }}
```

On success, the server responds with a `connected` event containing your client ID.

### Receiving State Updates

The server pushes `state-update` events whenever something changes:

```
{  "type": "event",  "payload": {    "event": "state-update",    "updates": [      {        "updateType": "playstate",        "projectId": "p1234567890",        "data": {          "event": "clip-play-state-changed",          "clipID": "c001",          "newState": "playing"        }      }    ]  }}
```

Update types include: `project`, `playstate`, `clip`, `song`, `volume`, and `full` (complete state refresh).

### Sending Actions

Send commands via the `action` message type:

```
{  "type": "action",  "payload": {    "action": {      "name": "NextSongAction",      "params": []    }  },  "correlationId": "req-123"}
```

The server responds with an `action-response` message containing the same `correlationId`, so you can match responses to requests.

## Available Actions

### Playback

| Action | Parameters | Description |
| --- | --- | --- |
| `PlayClipByIndexAction` | songIndex, clipIndex | Play a Clip by its position. |
| `PlayClipAction` | clipId | Play a specific Clip by ID. |
| `TriggerClipAction` | clipId | Trigger a Clip (respects retrigger behavior). |
| `StopAction` | — | Stop all playback. |
| `StopClipAction` | clipId | Stop a specific Clip. |
| `StopAllClipsAction` | — | Stop all Clips. |
| `PauseAction` | — | Pause playback. |
| `PauseToggleAction` | — | Toggle pause state. |
| `ResumeAction` | — | Resume from pause. |
| `PlayAction` | — | Start playback. |
| `RestartClipAction` | clipId | Restart a Clip from the beginning. |

### Navigation

| Action | Parameters | Description |
| --- | --- | --- |
| `SongSelectAction` | songIndex | Select a Song by its position. |
| `SongSelectByIdAction` | songId | Select a Song by ID. |
| `NextClipAction` | — | Advance to the next Clip. |
| `PrevClipAction` | — | Go to the previous Clip. |
| `NextSongAction` | — | Advance to the next Song. |
| `PrevSongAction` | — | Go to the previous Song. |

### Seeking & Direction

| Action | Parameters | Description |
| --- | --- | --- |
| `SeekClipAction` | clipId, position | Seek a Clip to a position (seconds). |
| `SeekSongAction` | songId, position | Seek Song audio to a position (seconds). |
| `ClipDirectionAction` | clipId, direction | Set Clip direction: `forward` or `reverse`. |

### Volume & System

| Action | Parameters | Description |
| --- | --- | --- |
| `OutputLevelAction` | level (0–1) | Set master volume. |
| `MuteToggleAction` | — | Toggle mute. |
| `PanicAction` | — | Emergency reload of all windows. |
| `FullscreenToggleAction` | — | Toggle fullscreen mode. |

## MCP Tools Reference

The [AI Assistants](https://manual.spaceage.tv/5.0.0/integrations/ai/) integration is powered by an MCP server that exposes a set of tools to AI clients. For end-user setup, see the AI Assistants page. This section is the developer reference for the tools themselves.

### Query Tools

| Tool | Description |
| --- | --- |
| `visibox_get_projects` | List all open Projects. |
| `visibox_get_project` | Get full data for a Project — Songs, Clips, files, Effects, Visualizers. |
| `visibox_get_active_project` | Get the active Project and its playback state in one call. |
| `visibox_get_playstate` | Get playback state for a Project. |
| `visibox_get_app_state` | Get app-level state — fullscreen, mute, volume level. |
| `visibox_get_presets` | List all Effect and Visualizer presets. Optionally include full preset data. |
| `visibox_get_preset` | Get full data for a single preset by ID and type. |

### Edit Tools

| Tool | Description |
| --- | --- |
| `visibox_clip_edit` | Add, move, duplicate, delete Clips, or update Clip options (filters, effects, visualizers). |
| `visibox_song_edit` | Add, move, duplicate, delete Songs, or manage Song audio and titles. |
| `visibox_project_edit` | Undo, redo, update display options, manage Background Clips, adjust zoom. |
| `visibox_effect_edit` | Add, update, remove, or copy Effects in a Project. |
| `visibox_visualizer_edit` | Add, update, remove, or copy Visualizers in a Project. |
| `visibox_preset_edit` | Add, update, or remove user Effects and Visualizers in the preset store. |

### Action Tools

| Tool | Description |
| --- | --- |
| `visibox_playback` | All playback controls — play, stop, pause, resume, trigger Clips, navigate Songs, seek, adjust volume. |
| `visibox_system` | System controls — toggle fullscreen, toggle mute, panic (emergency reload). |

### Live Editor Updates

When a `visibox_effect_edit` or `visibox_visualizer_edit` tool call modifies a preset, the corresponding Editor window updates in real time if it’s open — code changes, parameter changes, and the live preview all reflect the edit as it happens. This enables collaborative iteration with AI tools while watching the result live.

## Stream Deck Plugin

Visibox 5.0 includes an official Elgato Stream Deck plugin that connects via this API. See the [Stream Deck](https://manual.spaceage.tv/5.0.0/stream-deck/) page for full details.

## Security

The API is designed for local network use. A few things to keep in mind:

*   All communication is unencrypted (HTTP and WebSocket, not HTTPS or WSS). Do not expose these ports to the public internet.
*   Localhost connections bypass authentication — this is by design, for integrations running on the same machine.
*   OTP codes expire after 5 minutes.

## Error Handling

### HTTP Status Codes

| Code | Meaning |
| --- | --- |
| 400 | Bad request — invalid parameters. |
| 401 | Authentication required or invalid token. |
| 404 | Resource not found. |
| 500 | Server error. |
| 503 | Service unavailable — API not ready yet. |

### WebSocket Error Types

| Type | Description |
| --- | --- |
| `AUTHENTICATION_FAILED` | Invalid token. |
| `ACTION_FAILED` | The requested action could not be executed. |
| `INVALID_MESSAGE` | Malformed message. |
| `RATE_LIMITED` | Too many requests. |
| `SERVER_ERROR` | Internal server error. |

Source: https://manual.spaceage.tv/5.0.0/integrations/api/
