Skip to main content
Version: 6.0.0

Visibox API

Visibox exposes a local network API for remote control, automation, and custom integrations. This page is the technical reference. If you want to use Visibox through an AI assistant or a shell, see AI Assistants or Command Line Interface instead. If you want to drive it from a control surface, see OSC.

Overview

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

ServicePortProtocolDescription
WebSocket17734ws://Real-time two-way communication. State updates are pushed to connected clients.
HTTP REST17736http://Request and response, for querying state and sending commands.
OSC17735UDPOpen Sound Control. See OSC.

All three bind to every network interface on the machine, so any device on the same local network can connect.

note

These port numbers changed in Visibox 6.0: WebSocket moved from 51734 to 17734, OSC from 51735 to 17735, and HTTP from 51736 to 17736. If you have an integration built against the older numbers, update them.

Service Discovery

Visibox advertises itself on the local network using Bonjour (mDNS/DNS-SD):

Service TypeAdvertised asPort
_visibox._tcpVisibox - <hostname>17734
_http._tcpVisibox HTTP - <hostname>17736

The TXT records include the API version, hostname, platform, and the port numbers, including oscPort. OSC has no Bonjour service of its own.

Authentication

Localhost

Visibox authenticates connections from 127.0.0.1 or ::1 automatically. No pairing and no token. Integrations running on the same machine, such as the Stream Deck plugin, the CLI, and the MCP server, connect with no setup.

Remote devices

Devices connecting over the network must pair first. See Remote Pairing for how to pair a device and how long the token lasts.

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

HTTP REST API

Base URL: http://<visibox-ip>:17736

Health and info

GET /health
GET /api/v1/info

/health needs no authentication and is the quickest way to check the API is up. /api/v1/info returns the API version, the app version, and a map of every endpoint.

Pairing

POST /api/v1/pair
POST /api/v1/refresh

POST /api/v1/pair exchanges a 6-digit code for a token:

{
"otp": "123456"
}

Returns:

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

Projects

GET /api/v1/projects
GET /api/v1/projects/:projectId
GET /api/v1/projects/:projectId/summary
GET /api/v1/projects/:projectId/playstate
GET /api/v1/active
GET /api/v1/app-state

/projects lists every open project. /projects/:projectId returns everything: Songs, Clips, files, Effects, Visualizers, and display options. /summary is the light version of that, for a client that only needs names and counts.

/playstate returns what is playing, with positions, durations, and directions. /active bundles the active project and its play state into one request. /app-state returns full screen, mute, and volume.

Drill-down endpoints

For part of a Project without fetching the whole thing:

GET /api/v1/projects/:projectId/songs
GET /api/v1/projects/:projectId/songs/:songId
GET /api/v1/projects/:projectId/clips?ids=<id>,<id>
GET /api/v1/projects/:projectId/effects
GET /api/v1/projects/:projectId/visualizers

/clips takes a required ids query parameter and returns only those Clips.

Presets

GET /api/v1/presets
GET /api/v1/presets/:kind/:id

List the Effect and Visualizer presets, or fetch one. :kind is effect or visualizer.

Media

GET /thumbnails/:projectId/:fileId.jpg

A Clip’s thumbnail. Optional query parameters:

ParameterDefaultDescription
sizeoriginalSquare output size in pixels (16 to 512).
overlaynoneOverlay icon: play, pause, or none.
formatjpegOutput format: jpeg or png.
quality85JPEG quality, 1 to 100.
GET /waveforms/:projectId/:fileId.png

A waveform image for an audio file.

Cameras

GET /api/v1/cameras
GET /camera-thumbnails/:cameraId.jpg

List cameras with their device IDs and labels, or fetch a live thumbnail, updated every 5 seconds while the camera is active. Use default as the camera ID for the default camera.

Sending actions

POST /api/v1/action

The body names the action and its parameters:

{
"name": "PLAY_CLIP_BY_INDEX_IN",
"params": ["0", "1"],
"base": 0
}
FieldRequiredDescription
nameYesAn action name from the list below.
paramsNoArray of values. Everything is coerced to a string.
projectIDNoTarget project. Omit for the active one.
baseNo0 or 1. See Counting from zero or one.

Editing a Project

POST /api/v1/edit
GET /api/v1/edit/schema
GET /api/v1/edit/schema/:name

POST /api/v1/edit applies a Project mutation: add, move, or delete Songs, Clips, Effects, and Visualizers, set a Song’s timeline, import media, undo, redo. The two schema endpoints list the available edit names and the parameters each one takes, which is the reliable way to discover them rather than hard-coding a list.

Uploading a file

POST /api/v1/files/upload

WebSocket API

Connect to ws://<visibox-ip>:17734/v1. The /v1 path is required.

The WebSocket API is two-way. Connect once, authenticate, and state updates are pushed to you as things change, with no polling.

Connecting

As soon as the socket opens, and before you have sent anything, the server pushes a connected event carrying your client ID. It is a greeting, not an acknowledgement: every WebSocket connection authenticates, localhost included.

Send an auth message next:

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

On success the server replies with a response message carrying the same id as your auth message and data: { "authenticated": true }. Wait for that before you send anything else. A remote device pairing for the first time sends otp and deviceName instead of token. A client on the same machine can send auth with neither: Visibox puts an approval prompt on screen, and the response that follows carries a token to reuse next time. See Remote Pairing.

Receiving state updates

The server pushes state-update events:

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

event sits beside payload, not inside it, and payload is the array of updates itself. There is no wrapper key around it.

Update types are project, playstate, clip, song, volume, appState, presets, and full. appState carries app-level changes (full screen, mute, output level) and its projectId is null, because it belongs to no one project. presets fires when an Effect or Visualizer preset is added, changed or removed, so a client holding a cached preset list knows to refresh it. Updates are coalesced, so a burst of changes arrives as one message rather than fifty.

Sending actions

{
"id": "req-123",
"type": "action",
"action": {
"name": "NEXT_SONG_IN",
"params": []
},
"base": 1
}

The server responds with a response message carrying the same id, so you can match responses to requests. base sits beside action, not inside it.

Available Actions

Action names are uppercase and go in the name field over any transport.

Playback

ActionParametersDescription
PLAY_INnoneStart playback.
STOP_INnoneStop playback.
PAUSE_INclipID (optional)Pause.
RESUME_INclipID (optional)Resume from a pause.
PLAY_TOGGLE_INnoneToggle play and stop.
PAUSE_TOGGLE_INnoneToggle pause and resume.
PLAY_CLIP_INclipID (optional)Play a Clip by ID.
PLAY_CLIP_BY_INDEX_INindex, songID (optional)Play a Clip by its position.
TRIGGER_CLIP_INclipID, activateSong (optional)Trigger a Clip, respecting its retrigger behavior.
RESTART_CLIP_INclipID (optional)Restart a Clip from the beginning.
RELEASE_CLIP_INclipIDRelease a held Clip. See below.
RELEASE_CLIP_BY_INDEX_INindex, songID (optional)Release a held Clip by its position.
STOP_CLIP_INclipID, maybePlayBackground (optional)Stop one Clip.
STOP_ALL_CLIPS_INmaybePlayBackground (optional)Stop every Clip.

RELEASE_CLIP_IN and RELEASE_CLIP_BY_INDEX_IN are new in 6.0. They are the note-off half of a held button, and they do nothing unless the Clip is in Gate launch mode. That makes them safe to send unconditionally: build your surface to send trigger on press and release on release, and Clips in the other launch modes ignore the release.

ActionParametersDescription
NEXT_CLIP_INanySong (optional)Next Clip. Pass true to cross into the next Song.
PREV_CLIP_INanySong (optional)Previous Clip.
NEXT_SONG_INnoStop (optional)Next Song. Pass true to leave playback running.
PREV_SONG_INnoStop (optional)Previous Song.
PLAY_NEXT_SONG_INnoneMove to the next Song and start playing it.
SONG_SELECT_INindex, stopPlaying (optional)Select a Song by its position.
SONG_SELECT_BY_IDsongID, stopPlaying (optional)Select a Song by ID.
SONG_SELECT_PGM_IDpgmId, stopPlaying (optional)Select a Song by its Program Identifier.
SONG_SELECT_PERCENT_INpercent, stopPlaying (optional)Select a Song by position through the list, 0.0 to 1.0.

stopPlaying defaults to true.

Seeking and direction

ActionParametersDescription
SEEK_CLIP_INclipID, percentSeek a Clip. percent is 0.0 (start) to 1.0 (end).
SEEK_SONG_INsongID, percentSeek Song audio, 0.0 to 1.0.
CLIP_DIRECTIONclipID, directionSet direction: forward or backward.
warning

Both seek actions take a fraction from 0.0 to 1.0, not a number of seconds. Older documentation described them as seconds. The CLI seek command takes 0 to 100 and converts, so the two differ on purpose.

Real-Time Control

ActionParametersDescription
SET_CONTROLcontrolID, valueDrive a Control.
SET_PARAMtargetID, valueWrite one Target directly, skipping Controls.

Both are new in 6.0. controlID is a Control’s letter, A through Z, case-insensitive. targetID is of the form clip:abc123/opacity. Values are conventionally 0.0 to 1.0 and are not clamped here: shaping happens in the Control’s own settings. See Real-Time Control.

System

ActionParametersDescription
OUTPUT_LEVEL_INlevel (0.0 to 1.0)Set the master output level.
MUTE_TOGGLEnoneToggle mute.
FULLSCREEN_TOGGLEnoneToggle full screen.
RECORD_TOGGLEmode (optional)Toggle recording the output to a file.
PANICnoneReload every window.
OPEN_EDITORkind, presetIDOpen the Effects or Visualizers editor on a preset. kind is effect or visualizer.

RECORD_TOGGLE is new in 6.0. When nothing is recording, mode chooses how it starts: now begins immediately, next-trigger arms it to begin on the next Clip trigger. When recording is already armed or running, the action disarms or stops it and mode is ignored.

Velocity

Actions that start a Clip carry an optional velocity field alongside params, from 0 to 127, matching a MIDI note-on. It applies to TRIGGER_CLIP_IN, PLAY_CLIP_IN, PLAY_CLIP_BY_INDEX_IN, and RESTART_CLIP_IN, and feeds the Clip’s Velocity Sensitivity setting. Omit it and the trigger counts as full velocity.

Counting from zero or one

Clip and Song positions are zero-based by default: the first Clip is 0. The Controller numbers them from one.

Send base: 1 alongside an action and Visibox subtracts one from the first parameter of PLAY_CLIP_BY_INDEX_IN, RELEASE_CLIP_BY_INDEX_IN, and SONG_SELECT_IN, so your integration can use the numbers your user sees. Those three are the only actions it touches, and it does not apply to edit parameters, which are always zero-based.

Send the release with the same base you sent the trigger with. A gate button whose press and release disagree on the base holds one Clip down and lets go of its neighbor.

MCP Tools Reference

The AI Assistants integration is powered by an MCP server exposing tools to AI clients. It is served from the same HTTP port at /mcp, with discovery at GET /.well-known/mcp.json. Three methods are registered on that path: POST sends a request, GET opens a server-sent-events stream for messages coming back, and DELETE ends the session. An MCP client library handles all three for you. For end-user setup, see the AI Assistants page. This section covers the tools themselves.

Query tools

ToolDescription
visibox_get_projectsList all open Projects.
visibox_get_projectFull data for a Project: Songs, Clips, files, Effects, Visualizers.
visibox_get_project_summaryNames and counts only, for a cheap overview.
visibox_get_active_projectThe active Project and its play state in one call.
visibox_get_playstatePlay state for a Project.
visibox_get_app_stateApp-level state: full screen, mute, volume.
visibox_get_songsList Songs in a Project.
visibox_get_songOne Song, including its timeline and lyrics.
visibox_get_clipsSeveral Clips by ID.
visibox_get_clipOne Clip.
visibox_get_effectsEffects in a Project.
visibox_get_visualizersVisualizers in a Project.
visibox_get_presetsList Effect and Visualizer presets.
visibox_get_presetOne preset by ID and kind.
visibox_get_preset_controlsThe parameters a preset exposes.

Edit tools

ToolDescription
visibox_clip_editAdd, move, duplicate, delete Clips, or update Clip options including filters and effects.
visibox_song_editAdd, move, duplicate, delete Songs, manage Song audio and titles, set Program Identifiers, and set a Song’s timeline.
visibox_project_editUndo, redo, display options, Background Clips, zoom.
visibox_effect_editAdd, update, remove, or copy Effects.
visibox_visualizer_editAdd, update, remove, or copy Visualizers.
visibox_preset_editAdd, update, or remove user Effects and Visualizers in the preset store.
visibox_file_editImport media files.
visibox_describe_editReturn the parameter schema for one edit name.
visibox_validate_presetCheck a preset before writing it.

Action tools

ToolDescription
visibox_playbackPlayback controls: play, stop, pause, resume, trigger Clips, navigate, seek, volume.
visibox_systemSystem controls: full screen, mute, recording, panic.
visibox_open_editorOpen the Effects or Visualizers editor on a given preset.
visibox_controlReal-Time Control: list the Controls, set one by letter, or set a parameter by Target ID.

The MCP tools cover most but not all of the action list. Anything missing can be driven over HTTP, WebSocket, or OSC.

Live editor updates

When visibox_effect_edit or visibox_visualizer_edit modifies a preset, the matching Editor window updates in real time if it is open. Code changes, parameter changes, and the live preview all reflect the edit as it happens.

Stream Deck Plugin

Visibox has an official Elgato Stream Deck plugin that connects through this API. See the Stream Deck page for full details.

Security

The API is designed for local network use:

  • All communication is unencrypted. Do not expose these ports to the public internet.
  • Localhost connections bypass authentication by design, for integrations on the same machine.
  • One-time pairing codes expire after 5 minutes.

Error Handling

HTTP status codes

CodeMeaning
400Bad request. Invalid parameters.
401Authentication required, or an invalid token.
403Your plan does not include API access.
404Resource not found.
500Server error, or the action was refused.
503Service unavailable. The API is not ready yet.

An action Visibox refuses comes back as a 500 whatever the reason, so read the error string rather than branching on the status code.

WebSocket error types

TypeDescription
INITIALIZATION_FAILEDThe server could not start.
CONNECTION_FAILEDThe connection could not be established.
AUTHENTICATION_FAILEDInvalid token.
ACTION_FAILEDThe action could not be executed.
INVALID_MESSAGEMalformed message.
RATE_LIMITEDToo many requests.
SERVER_ERRORInternal server error.