Download OpenAPI specification:
Uniform contract for every /api/v1/* route exposed by DjMirrorPulse's HTTP
configuration server (HttpConfigServer). Every response is wrapped in the
same envelope ({ok, data, error, meta}) where meta.revision is a
monotonic live-config counter. Exceptions: GET /config/subscribe (long-poll
event shape) and binary download routes (raw bytes, no envelope).
This file is the single source of truth for the /api/v1 surface: every
route the server registers has an operation here, each with a unique
operationId. docs_tech/docs_http_ws/README_HTTP_API_REFERENCE.md keeps
the design notes. The legacy, unversioned surface (ad-hoc per-endpoint
shapes) is intentionally out of scope here; with an API key set it needs
the same credentials as /api/v1.
Vendor extensions used in this file:
x-edition (operation): the minimum license edition (professional,
enterprise) needed to switch the feature on or start it. Reading its
state always works; a refused call answers 403 EDITION_REQUIRED. The
editions are listed by GET /license.x-internal (operation): not part of the supported contract (test-only
routes); leave them out of published documentation.x-websocket-events (root): the events pushed over the WebSocket,
which OpenAPI cannot describe.Authentication is the user's choice: with no API key ("apiKey" in config.json, or DJMIRROR_API_TOKEN, which wins) every route answers without credentials. With one, every route needs the API key or the deviceToken of a phone paired by QR, except the pairing routes that declare their own security below.
Pushed over ws://localhost:<httpPort+1> (with an API key, add ?token=
| Event | When | data |
|---|---|---|
config.changed |
The live config changed. Same body as the long-poll event; also pushed over the WebSocket as eventType config.changed (not custom.event). | the changed fragment |
ping |
Heartbeat every 30 s while at least one client is connected. | none |
license.changed |
The edition in force changed (a pairing or activation changed it). | LicenseInfo-like object |
recording.started |
A recording started. | as POST /recording/start |
recording.stopped |
A recording stopped. | as POST /recording/stop |
recording.snapshot |
A snapshot was captured. | as POST /recording/snapshot |
spout.started |
The Spout output started. | SpoutStatus |
spout.stopped |
The Spout output stopped. | SpoutStatus |
spout.updated |
Its settings changed (at most once per 150 ms). | SpoutConfig |
spout.error |
The output failed (for instance a source that gives no texture). | {code, message} |
spout.layout.started |
The Spout layout service started. | SpoutLayoutStatus |
spout.layout.stopped |
The Spout layout service stopped. | SpoutLayoutStatus |
spout.layout.updated |
Its settings or the reloaded file changed (at most once per 150 ms). | SpoutLayoutConfig |
spout.layout.error |
A service-level failure, such as a bad layout file. One output's own failure only shows in the status. | {code, message} |
ndi.started |
The NDI bridge started. | NdiStatus |
ndi.stopped |
The NDI bridge stopped. | NdiStatus |
ndi.updated |
Its settings changed (at most once per 150 ms). | NdiSettings |
ndi.error |
The bridge exited on its own while expected to keep running. | {code: EXITED, message} |
dmx.fixtures.updated |
The fixture list changed on disk or through the API. | none |
dmx.scenes.updated |
The scenes changed. | none |
dmx.fixtureProfiles.updated |
The fixture profiles changed. | none |
dmx.movementPatterns.updated |
The movement patterns changed. | none |
dmx.laserPatterns.updated |
The laser patterns changed. | none |
dmx.config.updated |
The DMX configuration changed. | none |
dmx.runtime.changed |
Live DMX output changed (scene applied, channels set). | optional, event-specific |
dmx.blackout.changed |
Blackout switched. | {active} |
dmx.silence.changed |
The silence state or its fade settings changed. | {active, fadeMs, curve} |
dmx.macro.triggered |
A macro was triggered. | event-specific |
dmx.playall.changed |
Play All switched (POST /dmx/runtime/playall). | {running} |
dmx.scenemode.changed |
The forced scene mode changed (POST /dmx/runtime/scene-mode). | {mode} |
dmx.autoconnect.changed |
The DMX auto-connect setting changed. | event-specific |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "status": "ok",
- "realtimeWsPort": 0
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "apiVersion": "v1",
- "auth": "bearer_or_x_api_key",
- "supportsLongPoll": true,
- "supportsWebSocket": true,
- "routesPrefix": "/api/v1",
- "spout": {
- "available": true,
- "unavailableReason": "string"
}
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}The edition in force on this computer and, for every feature that is not in all editions, whether it is included. A paired phone sees the desktop's license.
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "edition": "professional",
- "isActive": true,
- "isTrial": false,
- "trialDaysRemaining": 0,
- "features": {
- "abletonLink": true,
- "timecode": true,
- "mcpServer": true,
- "spoutOutput": true,
- "ndiOutput": true,
- "spoutLayout": false,
- "ndiLayout": false
}
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": { },
- "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| property name* additional property | any |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{ }{- "ok": true,
- "data": { },
- "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "defaultColor": "#000000",
- "globalOutputBrightness": 1,
- "globalOutputContrast": 1,
- "globalOutputSaturation": 1,
- "globalOutputBlur": 0,
- "globalVideoAudioEnabled": true,
- "globalVideoStretchMode": 0,
- "globalVideoAudioOutputDevice": "System Default",
- "globalCaptureInputVolume": 1,
- "screenScale": 1.3,
- "language": "en",
- "sources": {
- "visualizer": {
- "devicePattern": "Array",
- "fallbackPattern": "Microphone"
}
}, - "dmxAutoConnect": true
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| defaultColor | string |
| globalOutputBrightness | number |
| globalOutputContrast | number |
| globalOutputSaturation | number |
| globalOutputBlur | number |
| globalVideoAudioEnabled | boolean |
| globalVideoStretchMode | integer |
| globalVideoAudioOutputDevice | string |
| globalCaptureInputVolume | number |
| screenScale | number |
| language | string |
object | |
| sources.visualizer.devicePattern | string |
| sources.visualizer.fallbackPattern | string |
| dmxAutoConnect | boolean |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "defaultColor": "string",
- "globalOutputBrightness": 0,
- "globalOutputContrast": 0,
- "globalOutputSaturation": 0,
- "globalOutputBlur": 0,
- "globalVideoAudioEnabled": true,
- "globalVideoStretchMode": 0,
- "globalVideoAudioOutputDevice": "string",
- "globalCaptureInputVolume": 0,
- "screenScale": 0,
- "language": "string",
- "sources": {
- "visualizer": {
- "devicePattern": "string",
- "fallbackPattern": "string"
}
}, - "sources.visualizer.devicePattern": "string",
- "sources.visualizer.fallbackPattern": "string",
- "dmxAutoConnect": true
}{- "ok": true,
- "data": {
- "defaultColor": "#000000",
- "globalOutputBrightness": 1,
- "globalOutputContrast": 1,
- "globalOutputSaturation": 1,
- "globalOutputBlur": 0,
- "globalVideoAudioEnabled": true,
- "globalVideoStretchMode": 0,
- "globalVideoAudioOutputDevice": "System Default",
- "globalCaptureInputVolume": 1,
- "screenScale": 1.3,
- "language": "en",
- "sources": {
- "visualizer": {
- "devicePattern": "Array",
- "fallbackPattern": "Microphone"
}
}, - "dmxAutoConnect": true
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
| data required | Array of strings Items Enum: "imagesBackgroundView" "avatarsBackgroundView" "videoBackgroundView" "vinylDiscView" "lightingView" "waveFormView" "artistCardView" "marqueeTextView" "maskView" "waveFormView.waveformVisualizer" "waveFormView.particleWaveVisualizer" "waveFormView.analogWaveVisualizer" "waveFormView.spectrumVisualizer" "waveFormView.xyVisualizer" "lightingView.midi" "lightingView.particles" "lightingView.spotlights" "lightingView.strobes" Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": [
- "imagesBackgroundView"
], - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": { },
- "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| layerId required | string (LayerId) Enum: "imagesBackgroundView" "avatarsBackgroundView" "videoBackgroundView" "vinylDiscView" "lightingView" "waveFormView" "artistCardView" "marqueeTextView" "maskView" "waveFormView.waveformVisualizer" "waveFormView.particleWaveVisualizer" "waveFormView.analogWaveVisualizer" "waveFormView.spectrumVisualizer" "waveFormView.xyVisualizer" "lightingView.midi" "lightingView.particles" "lightingView.spotlights" "lightingView.strobes" Any addressable layer or sub-layer id, as returned by GET /config/layer-ids. |
| enabled required | boolean |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "layerId": "imagesBackgroundView",
- "enabled": true
}{- "ok": true,
- "data": { },
- "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| layerId required | string (TopLevelLayerId) Enum: "imagesBackgroundView" "avatarsBackgroundView" "videoBackgroundView" "vinylDiscView" "lightingView" "waveFormView" "artistCardView" "marqueeTextView" "maskView" One of the 9 layer ids with their own full-object GET/PATCH endpoint. |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": { },
- "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| layerId required | string (TopLevelLayerId) Enum: "imagesBackgroundView" "avatarsBackgroundView" "videoBackgroundView" "vinylDiscView" "lightingView" "waveFormView" "artistCardView" "marqueeTextView" "maskView" One of the 9 layer ids with their own full-object GET/PATCH endpoint. |
| property name* additional property | any |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{ }{- "ok": true,
- "data": { },
- "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
required | Array of objects Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": [
- {
- "id": "string",
- "source": "custom",
- "customText": "string",
- "enabled": true
}
], - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| source required | string (MarqueeMessageSource) Enum: "custom" "artistName" "artistDescription" |
| customText | string |
| enabled | boolean Default: true |
{- "source": "custom",
- "customText": "string",
- "enabled": true
}{- "ok": true,
- "data": {
- "id": "string",
- "source": "custom",
- "customText": "string",
- "enabled": true
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Registered before the {messageId} route so this exact path is matched instead of being captured as an id.
| order required | Array of strings Exact permutation of the current message ids (same size, each id present exactly once). |
| ok required | boolean Value: true |
required | Array of objects Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "order": [
- "string"
]
}{- "ok": true,
- "data": [
- {
- "id": "string",
- "source": "custom",
- "customText": "string",
- "enabled": true
}
], - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| messageId required | string |
| source | string (MarqueeMessageSource) Enum: "custom" "artistName" "artistDescription" |
| customText | string |
| enabled | boolean |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "source": "custom",
- "customText": "string",
- "enabled": true
}{- "ok": true,
- "data": {
- "id": "string",
- "source": "custom",
- "customText": "string",
- "enabled": true
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| messageId required | string |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "deleted": true,
- "id": "string"
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Visual style listing, the (orphaned) config.styles block, and individual style content management.
Disconnected from actual style file content. See /visuals/styles/{name} below for the real thing.
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": { },
- "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Disconnected from actual style file content. See PUT /visuals/styles/{name} below to modify a style's real content.
| property name* additional property | any |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{ }{- "ok": true,
- "data": { },
- "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Captures defaultColor/currentImageFile/currentVideoFile/currentAvatarFile (resolved the same way GET /config/global resolves them) and the full current elements tree under a new name.
| name required | string non-empty Must not contain '..', '/' or ''. |
object (StyleMetadata) | |
| overwrite | boolean Default: false |
| defaultColor | string Optional override; otherwise resolved from live config. |
| currentImageFile | string |
| currentVideoFile | string |
| currentAvatarFile | string |
{- "name": "string",
- "metadata": {
- "author": "",
- "description": "",
- "version": "1.0",
- "isInstalled": true,
- "downloadUrl": ""
}, - "overwrite": false,
- "defaultColor": "string",
- "currentImageFile": "string",
- "currentVideoFile": "string",
- "currentAvatarFile": "string"
}{- "ok": true,
- "data": {
- "metadata": {
- "author": "",
- "description": "",
- "version": "1.0",
- "isInstalled": true,
- "downloadUrl": ""
}, - "defaultColor": "#000000",
- "currentImageFile": "default.txt",
- "currentVideoFile": "default.txt",
- "currentAvatarFile": "default.txt",
- "elements": { }
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Individual Style Management -- distinct from GET /visuals/styles above (names only) and from currentStyle (GET/PATCH /config), which only tracks which name is active.
| name required | string Style name (matches a Visuals/Styles/ |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "metadata": {
- "author": "",
- "description": "",
- "version": "1.0",
- "isInstalled": true,
- "downloadUrl": ""
}, - "defaultColor": "#000000",
- "currentImageFile": "default.txt",
- "currentVideoFile": "default.txt",
- "currentAvatarFile": "default.txt",
- "elements": { }
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| name required | string Style name (matches a Visuals/Styles/ |
object (StyleMetadata) | |
| defaultColor | string |
| currentImageFile | string |
| currentVideoFile | string |
| currentAvatarFile | string |
object (ElementsTree) Raw |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "metadata": {
- "author": "",
- "description": "",
- "version": "1.0",
- "isInstalled": true,
- "downloadUrl": ""
}, - "defaultColor": "string",
- "currentImageFile": "string",
- "currentVideoFile": "string",
- "currentAvatarFile": "string",
- "elements": { }
}{- "ok": true,
- "data": {
- "metadata": {
- "author": "",
- "description": "",
- "version": "1.0",
- "isInstalled": true,
- "downloadUrl": ""
}, - "defaultColor": "#000000",
- "currentImageFile": "default.txt",
- "currentVideoFile": "default.txt",
- "currentAvatarFile": "default.txt",
- "elements": { }
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Edits Visuals/Styles/{name}.json without touching the live config -- counterpart to PUT (full replace) and POST .../apply (load onto live). MCP equivalent: patch_style(name, fragment).
| name required | string Style name (matches a Visuals/Styles/ |
object (StyleMetadata) | |
| defaultColor | string |
| currentImageFile | string |
| currentVideoFile | string |
| currentAvatarFile | string |
object (ElementsTree) Raw |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "metadata": {
- "author": "",
- "description": "",
- "version": "1.0",
- "isInstalled": true,
- "downloadUrl": ""
}, - "defaultColor": "string",
- "currentImageFile": "string",
- "currentVideoFile": "string",
- "currentAvatarFile": "string",
- "elements": { }
}{- "ok": true,
- "data": {
- "metadata": {
- "author": "",
- "description": "",
- "version": "1.0",
- "isInstalled": true,
- "downloadUrl": ""
}, - "defaultColor": "#000000",
- "currentImageFile": "default.txt",
- "currentVideoFile": "default.txt",
- "currentAvatarFile": "default.txt",
- "elements": { }
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}The "default" style is protected and cannot be deleted (checked before existence).
| name required | string Style name (matches a Visuals/Styles/ |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "deleted": true,
- "name": "string"
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Sets currentStyle, visualization.{defaultColor,currentImageFile, currentVideoFile,currentAvatarFile}, and elements together in a single update -- unlike PATCH /config with { currentStyle: name }, which only flips the active-name pointer and relies on the desktop app to notice and reload the style from disk on its own, asynchronously. If overrides is given, it's deep-merged onto the style's own content before that atomic apply. Auto-download: if the style is only a stub (metadata.isInstalled === false with a metadata.downloadUrl set -- e.g. listed via a catalog but never fetched by this client), the package is downloaded and installed first (unzipped into Visuals/Styles, Images, Videos and Avatars, the same flow the desktop UI runs when an uninstalled style tile is clicked) before applying it. The request blocks for the duration of the download/install (up to 60s).
| name required | string Style name (matches a Visuals/Styles/ |
object (StyleOverrides) Deep-merged onto the style's own content before the atomic apply. |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "overrides": {
- "defaultColor": "string",
- "currentImageFile": "string",
- "currentVideoFile": "string",
- "currentAvatarFile": "string",
- "elements": { }
}
}{- "ok": true,
- "data": {
- "currentStyle": "string",
- "defaultColor": "string",
- "currentImageFile": "string",
- "currentVideoFile": "string",
- "currentAvatarFile": "string",
- "elements": { }
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": { },
- "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| property name* additional property | any |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{ }{- "ok": true,
- "data": { },
- "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "artists": [
- {
- "id": "string",
- "name": "string",
- "logo": "",
- "description": ""
}
]
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}required | Array of objects or object |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "artists": [
- { }
]
}{- "ok": true,
- "data": {
- "artists": [
- {
- "id": "string",
- "name": "string",
- "logo": "",
- "description": ""
}
]
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Granular alternative to PATCH above -- appends one artist instead of replacing the whole list.
| name required | string non-empty |
| logo | string |
| description | string |
{- "name": "string",
- "logo": "string",
- "description": "string"
}{- "ok": true,
- "data": {
- "id": "string",
- "name": "string",
- "logo": "",
- "description": ""
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Registered before the {artistId} route so this exact path is matched instead of being captured as an id. Adjusts artist.currentArtistIndex so the same artist (by id) stays "current" across the reorder.
| order required | Array of strings Exact permutation of the current artist ids (same size, each id present exactly once). |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "order": [
- "string"
]
}{- "ok": true,
- "data": {
- "artists": [
- {
- "id": "string",
- "name": "string",
- "logo": "",
- "description": ""
}
]
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| artistId required | string |
| name | string non-empty |
| logo | string |
| description | string |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "name": "string",
- "logo": "string",
- "description": "string"
}{- "ok": true,
- "data": {
- "id": "string",
- "name": "string",
- "logo": "",
- "description": ""
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Adjusts artist.currentArtistIndex to keep pointing at the same logical artist.
| artistId required | string |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "deleted": true,
- "id": "string"
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
| data | Array of strings Absent when the value was never set. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": [
- "string"
], - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
| data required | Array of strings Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
[- "string"
]{- "ok": true,
- "data": [
- "string"
], - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
| data | Array of strings Absent when the value was never set. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": [
- "string"
], - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
| data required | Array of strings Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
[- "string"
]{- "ok": true,
- "data": [
- "string"
], - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
| data | Array of strings Absent when the value was never set. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": [
- "string"
], - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
| data required | Array of strings Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
[- "string"
]{- "ok": true,
- "data": [
- "string"
], - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
| data required | Array of strings Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": [
- "string"
], - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
| data required | Array of strings Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": [
- "string"
], - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
| data required | Array of strings Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": [
- "string"
], - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
| data required | Array of strings Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": [
- "string"
], - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
| data required | Array of strings Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": [
- "string"
], - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
required | Array of objects Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": [
- {
- "filename": "sunset.jpg",
- "path": "C:/Users/.../Documents/Visuals/Images/sunset.jpg",
- "size": 245678,
- "modified": "2026-08-10T14:22:03"
}
], - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
required | Array of objects Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": [
- {
- "filename": "sunset.jpg",
- "path": "C:/Users/.../Documents/Visuals/Images/sunset.jpg",
- "size": 245678,
- "modified": "2026-08-10T14:22:03"
}
], - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
required | Array of objects Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": [
- {
- "filename": "sunset.jpg",
- "path": "C:/Users/.../Documents/Visuals/Images/sunset.jpg",
- "size": 245678,
- "modified": "2026-08-10T14:22:03"
}
], - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Lightweight bulk listing (name, isInstalled, downloadUrl) instead of the full style content GET /visuals/styles/{name} returns, so a client can show the install state of every style without one fetch per name.
| ok required | boolean Value: true |
required | Array of objects Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": [
- {
- "name": "Neon Tunnel",
- "isInstalled": true,
- "downloadUrl": ""
}
], - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| q required | string |
| page | integer >= 1 Default: 1 |
| perPage | integer Default: 0 |
| service | string Default: "both" Enum: "pixabay" "pexels" "both" |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "query": "string",
- "results": [
- { }
]
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| url required | string <uri> |
| fileName | string Must not contain '..', '/' or ''. Auto-generated from tags/timestamp when omitted. |
| tags | string |
object Optional raw provider item, forwarded to the download service. |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "fileName": "string",
- "tags": "string",
- "item": { }
}{- "ok": true,
- "data": {
- "fileName": "string",
- "filePath": "string",
- "playlist": "default.txt"
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| q required | string |
| page | integer >= 1 Default: 1 |
| perPage | integer Default: 0 |
| service | string Default: "both" Enum: "pixabay" "pexels" "both" |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "query": "string",
- "results": [
- { }
]
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| url required | string <uri> |
| fileName | string Must not contain '..', '/' or ''. Auto-generated from tags/timestamp when omitted. |
| tags | string |
object Optional raw provider item, forwarded to the download service. |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "fileName": "string",
- "tags": "string",
- "item": { }
}{- "ok": true,
- "data": {
- "fileName": "string",
- "filePath": "string",
- "playlist": "default.txt"
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| q required | string |
| page | integer >= 1 Default: 1 |
| perPage | integer Default: 0 |
| service | string Default: "both" Enum: "pixabay" "pexels" "both" |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "query": "string",
- "results": [
- { }
]
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| url required | string <uri> |
| fileName | string Must not contain '..', '/' or ''. Auto-generated from tags/timestamp when omitted. |
| tags | string |
object Optional raw provider item, forwarded to the download service. |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "fileName": "string",
- "tags": "string",
- "item": { }
}{- "ok": true,
- "data": {
- "fileName": "string",
- "filePath": "string",
- "playlist": "default.txt"
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}DMX fixtures, scenes, movement/laser patterns, fixture profiles, runtime control, and export/import.
| ok required | boolean Value: true |
required | Array of objects Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": [
- { }
], - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| property name* additional property | any |
| ok required | boolean Value: true |
required | Array of objects Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
[ ]{- "ok": true,
- "data": [
- { }
], - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}required | Array of objects (DmxFixture) |
| ok required | boolean Value: true |
required | Array of objects Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "fixtures": [
- { }
]
}{- "ok": true,
- "data": [
- { }
], - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": { },
- "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| property name* additional property | any |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{ }{- "ok": true,
- "data": { },
- "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}If the body includes a scenes key, the entire scenes array is replaced, not appended to -- there is no per-scene merge.
| property name* additional property | any |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{ }{- "ok": true,
- "data": { },
- "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": { },
- "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| property name* additional property | any |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{ }{- "ok": true,
- "data": { },
- "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": { },
- "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| property name* additional property | any |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{ }{- "ok": true,
- "data": { },
- "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}If the DMX runtime helper isn't available, responds 200 with { "profiles": [] } rather than an error.
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "profiles": [
- { }
]
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| property name* additional property | any |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
[ ]{- "ok": true,
- "data": {
- "profiles": [
- { }
]
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Patch behaves as replace for now (same as PUT), to keep parity with list semantics.
| property name* additional property | any |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
[ ]{- "ok": true,
- "data": {
- "profiles": [
- { }
]
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}object Full scene object, applied directly. | |
| sceneId | string Looked up in dmx_scenes.json. |
| progress | number [ 0 .. 1 ] If present and >= 0, applies with progress instead of instantly. |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "scene": { },
- "sceneId": "string",
- "progress": 0
}{- "ok": true,
- "data": {
- "applied": true
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| universe | integer Default: 0 |
required | Array of objects |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "universe": 0,
- "channels": [
- {
- "channel": 0,
- "value": 0
}
]
}{- "ok": true,
- "data": {
- "updated": 0
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| active | boolean Default: true |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "active": true
}{- "ok": true,
- "data": {
- "active": true
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "active": true,
- "fadeMs": 0,
- "curve": "linear"
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| active | boolean |
| fadeMs | integer [ 0 .. 5000 ] |
| curve | string Enum: "linear" "smooth" "easeIn" "easeOut" |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "active": true,
- "fadeMs": 0,
- "curve": "linear"
}{- "ok": true,
- "data": {
- "active": true,
- "fadeMs": 0,
- "curve": "linear"
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| enabled | boolean |
| globalSpeed | number |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "enabled": true,
- "globalSpeed": 0
}{- "ok": true,
- "data": {
- "ok": true
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| enabled | boolean Toggles auto-dimmer mode. |
| autoValue | integer [ 0 .. 255 ] Level used while auto-dimmer mode is on. |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "enabled": true,
- "autoValue": 0
}{- "ok": true,
- "data": {
- "ok": true
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| macro required | string (DmxMacroName) Enum: "fog" "haze" "laser-blackout" "strobe" |
| intensity | number Default: 1 No range validation applied. |
| durationMs | integer fog only. Burst duration in ms, server-clamped to [50, 30000]. Omit (or send <= 0) for the default short burst (~900ms); pass several thousand ms for a long burst. |
| color | string strobe only. Hex flash color, e.g. #FFFFFF. Invalid/empty defaults to white. |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "intensity": 1,
- "durationMs": 0,
- "color": "string"
}{- "ok": true,
- "data": {
- "triggered": "fog"
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Always succeeds -- missing files degrade to empty defaults, not errors.
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "fixtures": [
- { }
], - "scenes": { },
- "movementPatterns": { },
- "laserPatterns": { },
- "fixtureProfiles": {
- "profiles": [
- { }
]
}
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}An entirely empty body {} is accepted and is effectively a no-op success. See DmxImportRequest for the merge-vs-replace and scenes-shape caveats.
| mode | string 'merge' merges fixtures/scenes by id (incoming wins); anything else (including omitted) is a full replace. movementPatterns/laserPatterns/fixtureProfiles are always a full replace regardless of mode. |
| dryRun | boolean Default: false When true, validation still runs but nothing is written or reloaded. |
Array of objects (DmxFixture) | |
Array of objects | |
object (DmxPatternFile) Raw contents of a movement/laser pattern file. No schema validation is applied -- written/read as-is. | |
object (DmxPatternFile) Raw contents of a movement/laser pattern file. No schema validation is applied -- written/read as-is. | |
Array of objects |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "mode": "merge",
- "dryRun": false,
- "fixtures": [
- { }
], - "scenes": [
- { }
], - "movementPatterns": { },
- "laserPatterns": { },
- "fixtureProfiles": [
- { }
]
}{- "ok": true,
- "data": {
- "imported": true,
- "mode": "string",
- "dryRun": true
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Pure coordination: nothing is stored on the server. It fans running out to every connected client (WebSocket event dmx.playall.changed), so a client that connects later sees false until the next change.
| running | boolean Default: false |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "running": true
}{- "ok": true,
- "data": {
- "running": true
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Pure coordination, same as /dmx/runtime/playall (WebSocket event dmx.scenemode.changed). Any value other than auto, manual or mixto is stored as perScene (each scene plays its own saved mode).
| mode | string Enum: "auto" "manual" "mixto" "perScene" Any other value is answered as perScene. |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "mode": "auto"
}{- "ok": true,
- "data": {
- "mode": "auto"
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "connected": true,
- "connectedPortName": "COM5",
- "connectedUniverseCount": 1,
- "packetCount": 18342,
- "blackoutActive": false,
- "movementEngineEnabled": true,
- "movementGlobalSpeed": 1,
- "dimmerAutoMode": false,
- "autoDimmerValue": 255,
- "fixtureStrobesEnabled": true,
- "audioSilent": false,
- "silenceFadeMs": 400,
- "silenceFadeCurve": "smooth"
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Addresses channels as the absolute DMX channels the fixture occupies (the way the desktop's per-fixture fine-control panel does), so a client does not have to duplicate the fixture to port/universe routing. Only channels inside 1-512 are listed.
| fixtureId required | string Fixture id, as in GET /dmx/fixtures. |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "fixtureId": "par-1",
- "channels": [
- {
- "channel": 1,
- "role": "dimmer",
- "value": 255
}, - {
- "channel": 2,
- "role": "red",
- "value": 0
}
]
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Same addressing as the GET. Broadcasts dmx.runtime.changed.
| fixtureId required | string Fixture id, as in GET /dmx/fixtures. |
required | Array of objects |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "channels": [
- {
- "channel": 2,
- "value": 128
}
]
}{- "ok": true,
- "data": {
- "fixtureId": "string",
- "updated": 0
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Start/stop/status/list/download of MP4 recordings of the main application window, plus single-frame PNG snapshots.
Only one recording can be active at a time. maxDurationSec enforces an auto-stop safety net since this can be triggered remotely with no on-screen recording indicator. Audio is recorded automatically from whichever input device is currently selected for audio analysis (falling back to the system default input); there is no separate toggle for it.
| fps | integer Default: 20 Clamped to [5, 60]. |
| maxDurationSec | integer Default: 1800 Clamped to [5, 7200]; the recording auto-stops when reached. |
| fileName | string Sanitized against path traversal; .mp4 appended if missing; auto-generated timestamped name if omitted. |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "fps": 20,
- "maxDurationSec": 1800,
- "fileName": "string"
}{- "ok": true,
- "data": {
- "recording": true,
- "fileName": "string",
- "fps": 0,
- "maxDurationSec": 0,
- "hasAudio": true
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Blocks briefly server-side (up to ~5s) until the encoder confirms the file is fully written before responding.
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "recording": false,
- "fileName": "string",
- "sizeBytes": 0,
- "durationSec": 0,
- "hasAudio": true
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "recording": true,
- "fileName": "string",
- "elapsedSec": 0,
- "fps": 0,
- "hasAudio": true
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "recordings": [
- {
- "fileName": "string",
- "sizeBytes": 0,
- "modified": "2019-08-24T14:15:22Z"
}
]
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Returns the raw MP4 bytes, not the standard ok/data envelope -- fileName is sanitized against path traversal.
| fileName required | string |
{- "ok": false,
- "data": { },
- "error": {
- "code": "string",
- "message": "string",
- "hint": "string",
- "details": { }
}, - "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Independent of any in-progress video recording -- can be called whether or not /recording/start is active.
| fileName | string Sanitized against path traversal; .png appended if missing; auto-generated timestamped name if omitted. |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "fileName": "string"
}{- "ok": true,
- "data": {
- "fileName": "string",
- "width": 0,
- "height": 0,
- "sizeBytes": 0
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "snapshots": [
- {
- "fileName": "string",
- "sizeBytes": 0,
- "modified": "2019-08-24T14:15:22Z"
}
]
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Returns the raw PNG bytes, not the standard ok/data envelope -- fileName is sanitized against path traversal.
| fileName required | string |
{- "ok": false,
- "data": { },
- "error": {
- "code": "string",
- "message": "string",
- "hint": "string",
- "details": { }
}, - "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Spout output (Windows only, builds with the Spout SDK): share the visual output as a texture with OBS, Resolume, TouchDesigner, VJ apps... on the same computer, with no encoding. Status, settings, start/stop and the list of senders registered on the machine.
Always answers, also on a build without the SDK (available: false). A stopped output has null for everything that comes from a frame.
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "available": true,
- "unavailableReason": "string",
- "running": true,
- "stalled": true,
- "path": "gpu",
- "degraded": true,
- "degradedReason": "string",
- "renderingApi": "direct3d11",
- "senderName": "string",
- "effectiveSource": "output",
- "effectiveFps": 0,
- "outputSize": {
- "width": 0,
- "height": 0
}, - "framesSent": 0,
- "lastFrameAgeMs": 0,
- "adapterName": "string",
- "lastError": "string",
- "config": {
- "available": true,
- "unavailableReason": "string",
- "senderName": "string",
- "fps": 0,
- "scale": 0.1,
- "width": 0,
- "height": 0,
- "source": "output",
- "mode": "auto",
- "adapterIndex": -1,
- "adapters": [
- "string"
], - "autoStart": true
}
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "available": true,
- "unavailableReason": "string",
- "senderName": "string",
- "fps": 0,
- "scale": 0.1,
- "width": 0,
- "height": 0,
- "source": "output",
- "mode": "auto",
- "adapterIndex": -1,
- "adapters": [
- "string"
], - "autoStart": true
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Persists the change (the same store as the Settings > Spout Output panel). Works while the output is stopped or running: see SpoutConfigPatch for what applies live and what recreates the sender. The answer is the resulting settings.
| senderName | string |
| fps | integer |
| scale | number |
| width | integer |
| height | integer |
string or integer | |
string or integer | |
| adapterIndex | integer |
| autoStart | boolean |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "senderName": "string",
- "fps": 0,
- "scale": 0,
- "width": 0,
- "height": 0,
- "source": "output",
- "mode": "auto",
- "adapterIndex": 0,
- "autoStart": true
}{- "ok": true,
- "data": {
- "available": true,
- "unavailableReason": "string",
- "senderName": "string",
- "fps": 0,
- "scale": 0.1,
- "width": 0,
- "height": 0,
- "source": "output",
- "mode": "auto",
- "adapterIndex": -1,
- "adapters": [
- "string"
], - "autoStart": true
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}The body is optional. Sending settings starts with them and stores them only if the output really starts. The GPU path needs the application window to be shown: a hidden or minimised window renders nothing, so the output would report stalled. A receiver must run on the same GPU as the sender (with several GPUs use mode cpu and adapterIndex).
| senderName | string |
| fps | integer |
| scale | number |
| width | integer |
| height | integer |
string or integer | |
string or integer | |
| adapterIndex | integer |
| autoStart | boolean |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "senderName": "string",
- "fps": 0,
- "scale": 0,
- "width": 0,
- "height": 0,
- "source": "output",
- "mode": "auto",
- "adapterIndex": 0,
- "autoStart": true
}{- "ok": true,
- "data": {
- "available": true,
- "unavailableReason": "string",
- "running": true,
- "stalled": true,
- "path": "gpu",
- "degraded": true,
- "degradedReason": "string",
- "renderingApi": "direct3d11",
- "senderName": "string",
- "effectiveSource": "output",
- "effectiveFps": 0,
- "outputSize": {
- "width": 0,
- "height": 0
}, - "framesSent": 0,
- "lastFrameAgeMs": 0,
- "adapterName": "string",
- "lastError": "string",
- "config": {
- "available": true,
- "unavailableReason": "string",
- "senderName": "string",
- "fps": 0,
- "scale": 0.1,
- "width": 0,
- "height": 0,
- "source": "output",
- "mode": "auto",
- "adapterIndex": -1,
- "adapters": [
- "string"
], - "autoStart": true
}
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Removes the sender from Spout. The settings are kept.
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "available": true,
- "unavailableReason": "string",
- "running": true,
- "stalled": true,
- "path": "gpu",
- "degraded": true,
- "degradedReason": "string",
- "renderingApi": "direct3d11",
- "senderName": "string",
- "effectiveSource": "output",
- "effectiveFps": 0,
- "outputSize": {
- "width": 0,
- "height": 0
}, - "framesSent": 0,
- "lastFrameAgeMs": 0,
- "adapterName": "string",
- "lastError": "string",
- "config": {
- "available": true,
- "unavailableReason": "string",
- "senderName": "string",
- "fps": 0,
- "scale": 0.1,
- "width": 0,
- "height": 0,
- "source": "output",
- "mode": "auto",
- "adapterIndex": -1,
- "adapters": [
- "string"
], - "autoStart": true
}
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}To check that a receiver can see this application (its own sender is listed when running).
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "senders": [
- "string"
]
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Tolerant read (an output with unusable data is dropped or falls back; it never rejects the file). valid/validationErrors report the strict check PUT would apply to this same file. A file that is not a JSON object at all is 422 INVALID_PAYLOAD.
| path | string Layout file, relative to the application folder or absolute. Default spout_config/spout_layout_config.example.json. |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "path": "C:/DjMirrorPulse/spout_config/my_layout.json",
- "valid": true,
- "warnings": [ ],
- "outputs": [
- {
- "name": "Left",
- "crop": {
- "enabled": true,
- "x": 0,
- "y": 0,
- "width": 640,
- "height": 1080
}, - "rotate": 0,
- "mask": {
- "enabled": false
}, - "spout": {
- "enabled": true,
- "alpha_mode": "straight",
- "scale": 1
}, - "level": "a",
- "size": {
- "width": 640,
- "height": 1080
}, - "active": true
}
]
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}The whole layout is validated strictly (unique non-empty names, at most 16 outputs, a valid shape per mask type...) and refused as one if anything is wrong: no partial save. Written exactly as sent; if path is the running layout it is reloaded at once. Broadcasts spout.layout.updated.
| path | string Layout file, relative to the application folder or absolute. Default spout_config/spout_layout_config.example.json. |
required | Array of objects (LayoutOutput) <= 16 items |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "outputs": [
- {
- "name": "Left",
- "crop": {
- "enabled": true,
- "x": 0,
- "y": 0,
- "width": 640,
- "height": 1080
}
}
]
}{- "ok": true,
- "data": {
- "path": "C:/DjMirrorPulse/spout_config/my_layout.json",
- "valid": true,
- "warnings": [ ],
- "outputs": [
- {
- "name": "Left",
- "crop": {
- "enabled": true,
- "x": 0,
- "y": 0,
- "width": 640,
- "height": 1080
}, - "rotate": 0,
- "mask": {
- "enabled": false
}, - "spout": {
- "enabled": true,
- "alpha_mode": "straight",
- "scale": 1
}, - "level": "a",
- "size": {
- "width": 640,
- "height": 1080
}, - "active": true
}
]
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "available": true,
- "running": true,
- "path": "gpu",
- "degraded": false,
- "layoutPath": "C:/DjMirrorPulse/spout_config/my_layout.json",
- "textureSize": {
- "width": 1920,
- "height": 1080
}, - "outputCount": 1,
- "activeSenderCount": 1,
- "outputs": [
- {
- "name": "Left",
- "level": "a",
- "sent": true,
- "realName": "Left",
- "error": null,
- "framesSent": 5231,
- "lastFrameAgeMs": 9
}
], - "lastError": null
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}The service's own settings, not the layout file's content.
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "available": true,
- "unavailableReason": "string",
- "layoutPath": "string",
- "mode": "auto",
- "source": "output",
- "fps": 0,
- "adapterIndex": -1,
- "adapters": [
- "string"
], - "autoStart": true
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Unlike PATCH /spout/config every field applies immediately (a layoutPath change reloads a running layout in place). An empty patch is 422 EMPTY_PATCH. Broadcasts spout.layout.updated.
| layoutPath | string |
| mode | string Enum: "auto" "gpu" "cpu" |
| source | string Enum: "output" "window" |
| fps | integer [ 0 .. 120 ] |
| adapterIndex | integer >= -1 |
| autoStart | boolean |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "fps": 30,
- "autoStart": true
}{- "ok": true,
- "data": {
- "available": true,
- "unavailableReason": "string",
- "layoutPath": "string",
- "mode": "auto",
- "source": "output",
- "fps": 0,
- "adapterIndex": -1,
- "adapters": [
- "string"
], - "autoStart": true
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}The body is optional, with the same fields as PATCH /spout/layout/config; they apply immediately even if the start then fails. Broadcasts spout.layout.started.
| layoutPath | string |
| mode | string Enum: "auto" "gpu" "cpu" |
| source | string Enum: "output" "window" |
| fps | integer [ 0 .. 120 ] |
| adapterIndex | integer >= -1 |
| autoStart | boolean |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "fps": 30,
- "autoStart": true
}{- "ok": true,
- "data": {
- "available": true,
- "running": true,
- "path": "gpu",
- "degraded": false,
- "layoutPath": "C:/DjMirrorPulse/spout_config/my_layout.json",
- "textureSize": {
- "width": 1920,
- "height": 1080
}, - "outputCount": 1,
- "activeSenderCount": 1,
- "outputs": [
- {
- "name": "Left",
- "level": "a",
- "sent": true,
- "realName": "Left",
- "error": null,
- "framesSent": 5231,
- "lastFrameAgeMs": 9
}
], - "lastError": null
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Broadcasts spout.layout.stopped.
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "available": true,
- "running": true,
- "path": "gpu",
- "degraded": false,
- "layoutPath": "C:/DjMirrorPulse/spout_config/my_layout.json",
- "textureSize": {
- "width": 1920,
- "height": 1080
}, - "outputCount": 1,
- "activeSenderCount": 1,
- "outputs": [
- {
- "name": "Left",
- "level": "a",
- "sent": true,
- "realName": "Left",
- "error": null,
- "framesSent": 5231,
- "lastFrameAgeMs": 9
}
], - "lastError": null
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Instead of waiting for the 500 ms watch. If the file went missing or stopped parsing the previous layout keeps running.
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "available": true,
- "running": true,
- "path": "gpu",
- "degraded": false,
- "layoutPath": "C:/DjMirrorPulse/spout_config/my_layout.json",
- "textureSize": {
- "width": 1920,
- "height": 1080
}, - "outputCount": 1,
- "activeSenderCount": 1,
- "outputs": [
- {
- "name": "Left",
- "level": "a",
- "sent": true,
- "realName": "Left",
- "error": null,
- "framesSent": 5231,
- "lastFrameAgeMs": 9
}
], - "lastError": null
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Base names (no extension) of the .json files under spout_config/, to build a ?path= picker. Empty, not an error, before the folder has anything in it.
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "files": [
- "my_layout",
- "stage_left_right"
]
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Ableton Link (desktop builds with the Link SDK): shares tempo and bar phase over the LAN with Traktor, Ableton Live, Resolume and other Link apps. DjMirrorPulse only follows the session, it never changes the session tempo. Live state and settings.
Read-only. Also answers on a build without the SDK (available false, everything else 0 / false).
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "available": true,
- "enabled": true,
- "connected": true,
- "peerCount": 0,
- "bpm": 0,
- "phase": 0,
- "beatInBar": 0,
- "quantum": 0,
- "phaseOffsetMs": 0,
- "barOffsetBeats": 0,
- "clockSource": 0,
- "clockSourceName": "audio",
- "beatPolicy": 0,
- "beatPolicyName": "linkGrid",
- "fallbackActive": true,
- "bpmSource": "link",
- "effectiveBpm": 0,
- "otherSessionSeen": true,
- "rejoinAttempts": 0
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "available": true,
- "unavailableReason": "string",
- "enabled": true,
- "quantum": 1,
- "phaseOffsetMs": -500,
- "barOffsetBeats": 0,
- "clockSource": 0,
- "clockSourceName": "audio",
- "beatPolicy": 0,
- "beatPolicyName": "linkGrid",
- "mirrorLinkBeatsToLegacySignal": true,
- "beatWindowMs": 10,
- "tempoSmoothingMs": 0,
- "fallbackToAudioOnDisconnect": true,
- "beatsDuringSilence": true
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Persists the change (the same store as the Settings > Ableton Link panel) and applies it live. The answer is the resulting settings.
| enabled | boolean |
| quantum | integer [ 1 .. 32 ] |
| phaseOffsetMs | integer [ -500 .. 500 ] |
| barOffsetBeats | integer [ 0 .. 31 ] |
string or integer | |
string or integer | |
| mirrorLinkBeatsToLegacySignal | boolean |
| beatWindowMs | integer [ 10 .. 200 ] |
| tempoSmoothingMs | integer [ 0 .. 2000 ] |
| fallbackToAudioOnDisconnect | boolean |
| beatsDuringSilence | boolean |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "enabled": true,
- "quantum": 1,
- "phaseOffsetMs": -500,
- "barOffsetBeats": 0,
- "clockSource": "audio",
- "beatPolicy": "linkGrid",
- "mirrorLinkBeatsToLegacySignal": true,
- "beatWindowMs": 10,
- "tempoSmoothingMs": 0,
- "fallbackToAudioOnDisconnect": true,
- "beatsDuringSilence": true
}{- "ok": true,
- "data": {
- "available": true,
- "unavailableReason": "string",
- "enabled": true,
- "quantum": 1,
- "phaseOffsetMs": -500,
- "barOffsetBeats": 0,
- "clockSource": 0,
- "clockSourceName": "audio",
- "beatPolicy": 0,
- "beatPolicyName": "linkGrid",
- "mirrorLinkBeatsToLegacySignal": true,
- "beatWindowMs": 10,
- "tempoSmoothingMs": 0,
- "fallbackToAudioOnDisconnect": true,
- "beatsDuringSilence": true
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Call it when you hear the first beat of the bar (a little before or after is fine): the Link beat nearest to now becomes beat 1, which sets barOffsetBeats. It persists and applies live, and only shifts this application's own bar count: the session tempo and the other apps are untouched. It needs a live session, so with Link off, alone or without a valid tempo the answer is 409 NO_CLOCK and nothing changes.
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "available": true,
- "unavailableReason": "string",
- "enabled": true,
- "quantum": 1,
- "phaseOffsetMs": -500,
- "barOffsetBeats": 0,
- "clockSource": 0,
- "clockSourceName": "audio",
- "beatPolicy": 0,
- "beatPolicyName": "linkGrid",
- "mirrorLinkBeatsToLegacySignal": true,
- "beatWindowMs": 10,
- "tempoSmoothingMs": 0,
- "fallbackToAudioOnDisconnect": true,
- "beatsDuringSilence": true
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}The beat clock: the musical time base that effects and cues build on the Ableton Link session (beat line, position in the bar and the phrase, phrase anchor, effect tempo multiplier). Read-mostly: it has no clock of its own, so with Link off or alone in the session it reports valid false.
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "valid": true,
- "bpm": 0,
- "effectBpm": 0,
- "tempoMultiplier": 0.25,
- "quantum": 1,
- "beatInBar": 0,
- "bar": 0,
- "beatsSinceAnchor": 0,
- "barPhase": 0,
- "phraseAnchor": {
- "manual": true,
- "beat": 0
}, - "timeline": {
- "timeMs": 0,
- "beat": 0,
- "bpm": 0
}
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "tempoMultiplier": 0.25
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Persists the change and applies it live. The answer is the resulting settings.
| tempoMultiplier | number Enum: 0.25 0.5 1 2 4 |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "tempoMultiplier": 0.25
}{- "ok": true,
- "data": {
- "tempoMultiplier": 0.25
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}The downbeat nearest to now becomes bar 0 and bars are counted from there (a little before or after the downbeat is fine). Changing barOffsetBeats or the quantum, or losing the session, puts the anchor back to automatic. Without a beat clock the answer is 409 NO_CLOCK and nothing changes.
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "valid": true,
- "bpm": 0,
- "effectBpm": 0,
- "tempoMultiplier": 0.25,
- "quantum": 1,
- "beatInBar": 0,
- "bar": 0,
- "beatsSinceAnchor": 0,
- "barPhase": 0,
- "phraseAnchor": {
- "manual": true,
- "beat": 0
}, - "timeline": {
- "timeMs": 0,
- "beat": 0,
- "bpm": 0
}
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Bars are counted again from the bar in progress. Harmless when there is no beat clock.
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "valid": true,
- "bpm": 0,
- "effectBpm": 0,
- "tempoMultiplier": 0.25,
- "quantum": 1,
- "beatInBar": 0,
- "bar": 0,
- "beatsSinceAnchor": 0,
- "barPhase": 0,
- "phraseAnchor": {
- "manual": true,
- "beat": 0
}, - "timeline": {
- "timeMs": 0,
- "beat": 0,
- "bpm": 0
}
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Timecode sync (MTC over MIDI, LTC over an audio channel, or an internal manual clock) and the cue list that fires ActionDispatcher actions when the timecode crosses a cue. Live status, device settings, manual transport and cue CRUD/import/export.
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "enabled": true,
- "entries": [
- {
- "enabled": true,
- "name": "string",
- "hours": 0,
- "minutes": 0,
- "seconds": 0,
- "frames": 0,
- "action": "spawnShape",
- "target": "string",
- "value": null,
- "direction": null,
- "id": "string"
}
]
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Applies live and persists (the same store as the desktop Timecode Cues editor). Cue items are validated before anything is applied.
| enabled | boolean |
Array of objects (TimecodeCueInput) |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "enabled": true,
- "entries": [
- {
- "enabled": true,
- "name": "string",
- "hours": 0,
- "minutes": 0,
- "seconds": 0,
- "frames": 0,
- "action": "spawnShape",
- "target": "string",
- "value": null,
- "direction": null
}
]
}{- "ok": true,
- "data": {
- "enabled": true,
- "entries": [
- {
- "enabled": true,
- "name": "string",
- "hours": 0,
- "minutes": 0,
- "seconds": 0,
- "frames": 0,
- "action": "spawnShape",
- "target": "string",
- "value": null,
- "direction": null,
- "id": "string"
}
]
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "entries": [
- {
- "enabled": true,
- "name": "string",
- "hours": 0,
- "minutes": 0,
- "seconds": 0,
- "frames": 0,
- "action": "spawnShape",
- "target": "string",
- "value": null,
- "direction": null,
- "id": "string"
}
]
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}The id is always generated by the server (one sent in the body is dropped). enabled defaults to true and frames to 0.
| enabled | boolean Default: true |
| name | string Optional label shown in the desktop editor. |
| hours required | integer [ 0 .. 23 ] |
| minutes required | integer [ 0 .. 59 ] |
| seconds required | integer [ 0 .. 59 ] |
| frames | integer [ 0 .. 29 ] Default: 0 |
| action required | string Enum: "spawnShape" "style" "artist" "imagePlaylist" "avatarPlaylist" "videoPlaylist" "playlistStep" "dmxScene" "layerVisibility" "maskStep" "setConfigValue" "setFromInput" "beatAnchor" "markDownbeat" |
| target | string What the action applies to (style name, artist, playlist, scene, layer...); depends on action. |
| value | any Action argument; type depends on action. beatAnchor: mark (default) or clear. markDownbeat takes neither a target nor a value. |
| direction | any playlistStep only: which way to step. |
| property name* additional property | any |
{- "enabled": true,
- "name": "string",
- "hours": 0,
- "minutes": 0,
- "seconds": 0,
- "frames": 0,
- "action": "spawnShape",
- "target": "string",
- "value": null,
- "direction": null
}{- "ok": true,
- "data": {
- "enabled": true,
- "name": "string",
- "hours": 0,
- "minutes": 0,
- "seconds": 0,
- "frames": 0,
- "action": "spawnShape",
- "target": "string",
- "value": null,
- "direction": null,
- "id": "string"
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Registered before the {entryId} route so this exact path is matched instead of being captured as an id.
| order required | Array of strings Every current cue id, each exactly once, in the new order. |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "order": [
- "string"
]
}{- "ok": true,
- "data": {
- "entries": [
- {
- "enabled": true,
- "name": "string",
- "hours": 0,
- "minutes": 0,
- "seconds": 0,
- "frames": 0,
- "action": "spawnShape",
- "target": "string",
- "value": null,
- "direction": null,
- "id": "string"
}
]
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| entryId required | string |
| enabled | boolean |
| name | string |
| hours | integer [ 0 .. 23 ] |
| minutes | integer [ 0 .. 59 ] |
| seconds | integer [ 0 .. 59 ] |
| frames | integer [ 0 .. 29 ] |
| action | string Enum: "spawnShape" "style" "artist" "imagePlaylist" "avatarPlaylist" "videoPlaylist" "playlistStep" "dmxScene" "layerVisibility" "maskStep" "setConfigValue" "setFromInput" "beatAnchor" "markDownbeat" |
| target | string |
| value | any |
| direction | any |
| property name* additional property | any |
| ok required | boolean Value: true |
required | object (TimecodeCue) Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "enabled": true,
- "name": "string",
- "hours": 0,
- "minutes": 0,
- "seconds": 0,
- "frames": 0,
- "action": "spawnShape",
- "target": "string",
- "value": null,
- "direction": null
}{- "ok": true,
- "data": {
- "enabled": true,
- "name": "string",
- "hours": 0,
- "minutes": 0,
- "seconds": 0,
- "frames": 0,
- "action": "spawnShape",
- "target": "string",
- "value": null,
- "direction": null,
- "id": "string"
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| entryId required | string |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "deleted": true,
- "id": "string"
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Runs the same synchronous ActionDispatcher path as POST /actions/execute, ignoring the incoming timecode; handy to test a new cue. The dispatch context carries source "timecode" and the cue id.
| entryId required | string |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "dispatched": true,
- "entryId": "string",
- "action": "string",
- "target": "string"
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}For a client with no filesystem access of its own (a phone) that wants a picker; rebuild the path as timecode_cues/
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "files": [
- "string"
]
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Writes {enabled, entries} to disk, the server-side counterpart of the desktop editor's Save. Accepts an arbitrary path (relative to the application folder, or absolute), like the editor.
| path | string |
| ok required | boolean Value: true |
required | object (TimecodeCuesFileResult) Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "path": "string"
}{- "ok": true,
- "data": {
- "enabled": true,
- "entries": [
- {
- "enabled": true,
- "name": "string",
- "hours": 0,
- "minutes": 0,
- "seconds": 0,
- "frames": 0,
- "action": "spawnShape",
- "target": "string",
- "value": null,
- "direction": null,
- "id": "string"
}
], - "path": "string"
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Replaces the whole live cue list with the file's {enabled, entries}, the server-side counterpart of the desktop editor's Load. Every entry is validated first; nothing is applied if one fails.
| path | string |
| ok required | boolean Value: true |
required | object (TimecodeCuesFileResult) Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "path": "string"
}{- "ok": true,
- "data": {
- "enabled": true,
- "entries": [
- {
- "enabled": true,
- "name": "string",
- "hours": 0,
- "minutes": 0,
- "seconds": 0,
- "frames": 0,
- "action": "spawnShape",
- "target": "string",
- "value": null,
- "direction": null,
- "id": "string"
}
], - "path": "string"
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Read-only; what is being decoded right now, as opposed to /timecode/config (what can be configured).
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "enabled": true,
- "sourceMode": 0,
- "activeSource": "",
- "connected": true,
- "timecode": "00:12:34:05",
- "hours": 0,
- "minutes": 0,
- "seconds": 0,
- "frames": 0,
- "dropFrame": true,
- "reversed": true,
- "fps": 0,
- "frameRateLabel": "29.97 fps (DF)",
- "totalSeconds": 0,
- "ltcSignalConfidence": 0
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "enabled": true,
- "sourceMode": 0,
- "selectedMidiInput": -1,
- "availableMidiInputs": [
- "string"
], - "selectedAudioInput": -1,
- "availableAudioInputs": [
- "string"
], - "ltcChannelIndex": 0
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Same store as the desktop Settings > Timecode panel; applies live. See TimecodeConfigPatch for the order and the fact that it is not atomic.
| sourceMode | integer [ 0 .. 4 ] |
| selectedMidiInput | integer >= -1 Index in availableMidiInputs, -1 = none. |
| selectedAudioInput | integer >= -1 Index in availableAudioInputs, -1 = none. |
| ltcChannelIndex | integer >= 0 |
| enabled | boolean |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "sourceMode": 0,
- "selectedMidiInput": -1,
- "selectedAudioInput": -1,
- "ltcChannelIndex": 0,
- "enabled": true
}{- "ok": true,
- "data": {
- "enabled": true,
- "sourceMode": 0,
- "selectedMidiInput": 0,
- "selectedAudioInput": 0,
- "ltcChannelIndex": 0
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "availableMidiInputs": [
- "string"
]
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "availableAudioInputs": [
- "string"
]
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "running": true,
- "frameRate": 0
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| running | boolean |
| frameRate | number > 0 |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "running": true,
- "frameRate": 1
}{- "ok": true,
- "data": {
- "running": true,
- "frameRate": 0
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Does not fire the cues it skips (the next position is not compared against the previous one).
| hours required | integer |
| minutes required | integer |
| seconds required | integer |
| frames required | integer |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "hours": 0,
- "minutes": 0,
- "seconds": 0,
- "frames": 0
}{- "ok": true,
- "data": {
- "totalSeconds": 0,
- "timecode": "00:12:34:05"
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Does not fire the cues it skips (the next position is not compared against the previous one).
| deltaSeconds required | number Relative jump: positive = forward, negative = back (clamped at 00:00:00:00). |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "deltaSeconds": 0
}{- "ok": true,
- "data": {
- "totalSeconds": 0,
- "timecode": "00:12:34:05"
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Programming schedule: actions fired at a time of day on chosen weekdays (the desktop Schedule editor's data), entry CRUD, JSON file import/export and a simulated clock to test it.
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "enabled": true,
- "entries": [
- {
- "id": "5b0c8a52-6f0e-4e43-9a3b-0c1d2e3f4a5b",
- "enabled": true,
- "name": "Opening style",
- "hour": 21,
- "minute": 30,
- "second": 0,
- "daysOfWeek": [
- 5,
- 6
], - "action": "style",
- "target": "Neon Tunnel"
}
]
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Applies live and persists (prefs.programmingSchedule, the same data the desktop Schedule editor edits). entries REPLACES the list; every entry is validated first and one bad entry refuses the patch. An empty object is 422 EMPTY_PATCH.
| enabled | boolean |
Array of objects (ScheduleEntryInput) |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "enabled": true,
- "entries": [
- {
- "enabled": true,
- "name": "Opening style",
- "hour": 21,
- "minute": 30,
- "second": 0,
- "daysOfWeek": [
- 5,
- 6
], - "action": "style",
- "target": "Neon Tunnel"
}
]
}{- "ok": true,
- "data": {
- "enabled": true,
- "entries": [
- {
- "id": "5b0c8a52-6f0e-4e43-9a3b-0c1d2e3f4a5b",
- "enabled": true,
- "name": "Opening style",
- "hour": 21,
- "minute": 30,
- "second": 0,
- "daysOfWeek": [
- 5,
- 6
], - "action": "style",
- "target": "Neon Tunnel"
}
]
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "entries": [
- {
- "id": "5b0c8a52-6f0e-4e43-9a3b-0c1d2e3f4a5b",
- "enabled": true,
- "name": "Opening style",
- "hour": 21,
- "minute": 30,
- "second": 0,
- "daysOfWeek": [
- 5,
- 6
], - "action": "style",
- "target": "Neon Tunnel"
}
]
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}The id is always generated by the server (one sent in the body is dropped). enabled defaults to true and second to 0.
| enabled | boolean Default: true |
| name | string Optional label shown in the desktop editor. |
| hour required | integer [ 0 .. 23 ] |
| minute required | integer [ 0 .. 59 ] |
| second | integer [ 0 .. 59 ] Default: 0 |
| daysOfWeek required | Array of integers non-empty [ items [ 0 .. 6 ] ] Days it fires, Sunday = 0. |
| action required | string Enum: "spawnShape" "style" "artist" "imagePlaylist" "avatarPlaylist" "videoPlaylist" "playlistStep" "dmxScene" "layerVisibility" "maskStep" "setConfigValue" "setFromInput" "beatAnchor" "markDownbeat" |
| target | string |
| value | any Action argument; type depends on action. |
| direction | any playlistStep only: which way to step. |
| property name* additional property | any |
{- "enabled": true,
- "name": "Opening style",
- "hour": 21,
- "minute": 30,
- "second": 0,
- "daysOfWeek": [
- 5,
- 6
], - "action": "style",
- "target": "Neon Tunnel"
}{- "ok": true,
- "data": {
- "id": "5b0c8a52-6f0e-4e43-9a3b-0c1d2e3f4a5b",
- "enabled": true,
- "name": "Opening style",
- "hour": 21,
- "minute": 30,
- "second": 0,
- "daysOfWeek": [
- 5,
- 6
], - "action": "style",
- "target": "Neon Tunnel"
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Registered before the {entryId} route so this exact path is matched instead of being captured as an id.
| order required | Array of strings Every current entry id, each exactly once, in the new order. |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "order": [
- "string"
]
}{- "ok": true,
- "data": {
- "entries": [
- {
- "id": "5b0c8a52-6f0e-4e43-9a3b-0c1d2e3f4a5b",
- "enabled": true,
- "name": "Opening style",
- "hour": 21,
- "minute": 30,
- "second": 0,
- "daysOfWeek": [
- 5,
- 6
], - "action": "style",
- "target": "Neon Tunnel"
}
]
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Any subset of the entry fields, merged into the stored entry (id is ignored). The merged entry is validated. Nothing to change once id is ignored is 422 EMPTY_PATCH.
| entryId required | string |
| enabled | boolean |
| name | string |
| hour | integer [ 0 .. 23 ] |
| minute | integer [ 0 .. 59 ] |
| second | integer [ 0 .. 59 ] |
| daysOfWeek | Array of integers non-empty [ items [ 0 .. 6 ] ] |
| action | string |
| target | string |
| value | any |
| property name* additional property | any |
| ok required | boolean Value: true |
required | object (ScheduleEntry) Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "enabled": true,
- "name": "string",
- "hour": 0,
- "minute": 0,
- "second": 0,
- "daysOfWeek": [
- 0
], - "action": "string",
- "target": "string",
- "value": null
}{- "ok": true,
- "data": {
- "id": "5b0c8a52-6f0e-4e43-9a3b-0c1d2e3f4a5b",
- "enabled": true,
- "name": "Opening style",
- "hour": 21,
- "minute": 30,
- "second": 0,
- "daysOfWeek": [
- 5,
- 6
], - "action": "style",
- "target": "Neon Tunnel"
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| entryId required | string |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "deleted": true,
- "id": "string"
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Runs the entry's action through the same synchronous ActionDispatcher path as POST /actions/execute, ignoring its hour/minute/days. The dispatch context carries source "schedule" and the entry id.
| entryId required | string |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "dispatched": true,
- "entryId": "5b0c8a52-6f0e-4e43-9a3b-0c1d2e3f4a5b",
- "action": "style",
- "target": "Neon Tunnel"
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Writes {enabled, entries} to disk, the server-side counterpart of the desktop editor's Export. path defaults to programming_schedule/programming_schedule.json; a relative path is resolved against the application folder and an absolute one is used as is.
| path | string |
| ok required | boolean Value: true |
required | object (ScheduleFileResult) Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "path": "string"
}{- "ok": true,
- "data": {
- "enabled": true,
- "entries": [
- {
- "id": "5b0c8a52-6f0e-4e43-9a3b-0c1d2e3f4a5b",
- "enabled": true,
- "name": "Opening style",
- "hour": 21,
- "minute": 30,
- "second": 0,
- "daysOfWeek": [
- 5,
- 6
], - "action": "style",
- "target": "Neon Tunnel"
}
], - "path": "string"
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Replaces the whole live schedule with the file's {enabled, entries}. Every entry is validated first; nothing is applied if one fails. A file that is not a JSON object with an entries array is 422 INVALID_JSON.
| path | string |
| ok required | boolean Value: true |
required | object (ScheduleFileResult) Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "path": "string"
}{- "ok": true,
- "data": {
- "enabled": true,
- "entries": [
- {
- "id": "5b0c8a52-6f0e-4e43-9a3b-0c1d2e3f4a5b",
- "enabled": true,
- "name": "Opening style",
- "hour": 21,
- "minute": 30,
- "second": 0,
- "daysOfWeek": [
- 5,
- 6
], - "action": "style",
- "target": "Neon Tunnel"
}
], - "path": "string"
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Runtime only: the offset is never persisted, so a forgotten offset cannot survive a restart and fire the real schedule at the wrong time.
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "offsetSeconds": 3600,
- "realNow": "2026-10-13T20:30:00",
- "simulatedNow": "2026-10-13T21:30:00"
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Send offsetSeconds (absolute) and/or jumpSeconds (relative, added after offsetSeconds when both are sent). One of the two is required. Useful to test a schedule without waiting for its hour.
| offsetSeconds | number Absolute offset. |
| jumpSeconds | number Relative shift of the current offset. |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "jumpSeconds": 600
}{- "ok": true,
- "data": {
- "offsetSeconds": 3600,
- "realNow": "2026-10-13T20:30:00",
- "simulatedNow": "2026-10-13T21:30:00"
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Run one ActionDispatcher action now, the same path the schedule, the timecode cues and the MIDI/OSC/HID controllers use.
Fire-and-forget: the same synchronous path the Programming Schedule, the timecode cues and the MIDI/OSC/HID controllers use, so an action launched here behaves identically. The dispatch context carries source "api". The vocabulary of action/target/value is the one of the Programming Schedule entries.
| action required | string Enum: "spawnShape" "style" "artist" "imagePlaylist" "avatarPlaylist" "videoPlaylist" "playlistStep" "dmxScene" "layerVisibility" "maskStep" "setConfigValue" "setFromInput" "beatAnchor" "markDownbeat" |
| target | string What the action applies to (style name, artist, playlist, scene, layer...); depends on action. |
| value | any Action argument; type depends on action. |
object Extra named arguments (playlistStep reads direction here when value is empty). |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "action": "style",
- "target": "Neon Tunnel"
}{- "ok": true,
- "data": {
- "dispatched": true,
- "action": "style",
- "target": "Neon Tunnel"
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}NDI output through the separate DjMirrorPulseNdiBridge process: the layout file it follows (outputs[]) and the control of the process itself (start/stop/status/settings).
Returns the file's own JSON object plus path. Unlike the Spout layout GET it does not parse outputs[]: the bridge process is the tolerant reader. A file that exists but is not valid JSON is 500 INVALID_JSON.
| path | string Layout file, relative to the application folder or absolute. Default ndi_config/ndi_bridge_config.example.json. |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "path": "string",
- "outputs": [
- {
- "name": "string",
- "crop": {
- "enabled": true,
- "x": 0,
- "y": 0,
- "width": 0,
- "height": 0
}, - "rotate": 0,
- "mask": {
- "enabled": true
}, - "spout": {
- "enabled": true,
- "alpha_mode": "string",
- "scale": 0
}
}
]
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}outputs must be present and an array, with no per-field validation. Written exactly as sent. DjMirror Pulse holds no live state for it: the bridge re-reads the file by itself while it runs.
| path | string Layout file, relative to the application folder or absolute. Default ndi_config/ndi_bridge_config.example.json. |
required | Array of objects (LayoutOutput) |
| property name* additional property | any |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "outputs": [
- {
- "name": "Left",
- "crop": {
- "enabled": true,
- "x": 0,
- "y": 0,
- "width": 960,
- "height": 1080
}
}
]
}{- "ok": true,
- "data": {
- "path": "string",
- "outputs": [
- {
- "name": "string",
- "crop": {
- "enabled": true,
- "x": 0,
- "y": 0,
- "width": 0,
- "height": 0
}, - "rotate": 0,
- "mask": {
- "enabled": true
}, - "spout": {
- "enabled": true,
- "alpha_mode": "string",
- "scale": 0
}
}
]
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Process-only: the bridge has no IPC channel back to the app, so this means "the process is alive", never frames sent or receivers connected.
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "available": true,
- "running": true,
- "pid": 18420,
- "startedAt": "2026-10-13T10:15:00Z",
- "lastError": null,
- "autoStart": false,
- "statusDetail": "process-only"
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}No body: it always uses what GET /ndi/settings has. Broadcasts ndi.started.
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "available": true,
- "running": true,
- "pid": 18420,
- "startedAt": "2026-10-13T10:15:00Z",
- "lastError": null,
- "autoStart": false,
- "statusDetail": "process-only"
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Abrupt: a kill(), not an orderly shutdown (the windowless process ignores terminate()). Broadcasts ndi.stopped.
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "available": true,
- "running": true,
- "pid": 18420,
- "startedAt": "2026-10-13T10:15:00Z",
- "lastError": null,
- "autoStart": false,
- "statusDetail": "process-only"
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Not the layout file's content: that is /ndi/config.
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "autoStart": false,
- "bridgeExecutablePath": "",
- "effectiveExecutablePath": "C:/DjMirrorPulse/DjMirrorPulseNdiBridge.exe",
- "singleWindowMode": true,
- "windowTitle": "",
- "sourceName": "DjMirror Pulse Main",
- "fps": 0,
- "scale": 1,
- "width": 0,
- "height": 0
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Persists across restarts and never starts or stops the bridge by itself: call POST /ndi/start after. An empty patch is 422 EMPTY_PATCH. Broadcasts ndi.updated (at most once per 150 ms).
| autoStart | boolean Launch the bridge when the application starts. |
| bridgeExecutablePath | string For a nonstandard install. Empty = auto-detect. |
| singleWindowMode | boolean false = the next start follows the layout file; true = one uncropped source for the whole window. |
| windowTitle | string singleWindowMode only. Empty = the bridge's default. |
| sourceName | string singleWindowMode only. Empty = the bridge's default. |
| fps | integer singleWindowMode only. 0 = the bridge's default (60). |
| scale | number [ 0.1 .. 1 ] singleWindowMode only. |
| width | integer [ 16 .. 16384 ] singleWindowMode only; set together with height. 0 = follow the window. |
| height | integer [ 16 .. 16384 ] singleWindowMode only; set together with width. |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "singleWindowMode": true,
- "sourceName": "Main",
- "scale": 0.5
}{- "ok": true,
- "data": {
- "autoStart": false,
- "bridgeExecutablePath": "",
- "effectiveExecutablePath": "C:/DjMirrorPulse/DjMirrorPulseNdiBridge.exe",
- "singleWindowMode": true,
- "windowTitle": "",
- "sourceName": "DjMirror Pulse Main",
- "fps": 0,
- "scale": 1,
- "width": 0,
- "height": 0
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Base names (no extension) of the .json files under ndi_config/, to build a ?path= picker. Empty, not an error, before the folder has anything in it.
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "files": [
- "my_layout",
- "stage_left_right"
]
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Held open until the next config change; the server then writes a single event and the connection closes (client must re-subscribe). NOT wrapped in the standard ok/data envelope on success -- see SubscribeEvent. DMX-related changes are not delivered here; connect the WebSocket (ws://localhost:<httpPort+1>) for those.
| type required | string Value: "event" |
| eventType required | string Value: "config.changed" |
| resource required | string Value: "config" |
| action required | string Value: "updated" |
required | object |
| requestId required | string |
| timestamp required | string <date-time> |
{- "type": "event",
- "eventType": "config.changed",
- "resource": "config",
- "action": "updated",
- "data": { },
- "requestId": "string",
- "timestamp": "2019-08-24T14:15:22Z"
}Mobile app pairing by QR code (docs_tech/docs_mobile/PLAN_MOBILE_QR_PAIRING.md). The phone has no license of its own: it claims a one-use code shown on the desktop, gets a deviceToken and inherits the desktop license. Management routes (QR, confirmation, device list) need the API key when there is one; without an API key they are only accepted from the computer itself (loopback). A deviceToken never manages pairing (403 FORBIDDEN).
Public: the one-use code authenticates it. The code expires after 3 minutes and is locked after 5 wrong attempts; at most 10 claims per minute per address. If the desktop asks for confirmation (the default), the response waits up to 30 s for the user to accept.
| code | string 26-character base32 Crockford code from the QR (c=). |
| shortCode | string XXXX-XXXX code shown under the QR. |
| deviceId required | string <= 64 characters ^[A-Za-z0-9_.{}-]+$ Stable id of the phone install. |
| deviceName | string |
| platform | string |
| appVersion | string |
| protocol required | integer Value: 1 |
| ok required | boolean Value: true |
required | object (PairingClaimData) Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "code": "string",
- "shortCode": "7K3M-Q9TZ",
- "deviceId": "string",
- "deviceName": "Pixel 8",
- "platform": "android",
- "appVersion": "string",
- "protocol": 1
}{- "ok": true,
- "data": {
- "device": {
- "deviceId": "string",
- "name": "string"
}, - "desktop": {
- "id": "string",
- "name": "string",
- "appVersion": "string",
- "httpPort": 0,
- "wsPort": 0
}, - "license": {
- "edition": "none",
- "isActive": true,
- "isTrial": true,
- "trialDaysRemaining": 0,
- "trialEndsAt": "2019-08-24",
- "mobileDevicesLimit": 0,
- "mobileDevicesUsed": 0,
- "features": { }
}, - "attestation": {
- "kind": "djmp2",
- "key": "string",
- "machineId": "string",
- "distributorId": "string"
}, - "deviceToken": "string"
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Public. Lets a paired phone recognise its desktop after an IP change, without revealing anything the QR does not already say.
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "protocol": 1,
- "id": "string",
- "name": "string"
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Always needs the phone's deviceToken, also without an API key. Records when and from where the phone was last seen.
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "device": {
- "deviceId": "string",
- "name": "string"
}, - "desktop": {
- "id": "string",
- "name": "string",
- "appVersion": "string",
- "httpPort": 0,
- "wsPort": 0
}, - "license": {
- "edition": "none",
- "isActive": true,
- "isTrial": true,
- "trialDaysRemaining": 0,
- "trialEndsAt": "2019-08-24",
- "mobileDevicesLimit": 0,
- "mobileDevicesUsed": 0,
- "features": { }
}, - "attestation": {
- "kind": "djmp2",
- "key": "string",
- "machineId": "string",
- "distributorId": "string"
}
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "unpaired": true
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Replaces the previous code, if any. The body is optional.
| requireConfirmation | boolean Default: the desktop setting (Settings > Mobile app). |
{- "requireConfirmation": true
}{- "ok": true,
- "data": {
- "active": true,
- "uri": "djmirror://pair?v=1&h=192.168.1.20&p=8080&c=...&id=1a2b3c4d&n=Studio&e=1791300000",
- "shortCode": "string",
- "expiresAt": 0,
- "hosts": [
- "string"
], - "port": 0,
- "desktopId": "string",
- "requireConfirmation": true
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "active": true,
- "uri": "djmirror://pair?v=1&h=192.168.1.20&p=8080&c=...&id=1a2b3c4d&n=Studio&e=1791300000",
- "shortCode": "string",
- "expiresAt": 0,
- "hosts": [
- "string"
], - "port": 0,
- "desktopId": "string",
- "requireConfirmation": true
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}A phone waiting for confirmation gets 410 PAIRING_CODE_EXPIRED.
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "active": false
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "pending": true,
- "deviceName": "string",
- "platform": "string"
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| action required | string Enum: "approve" "reject" |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "action": "approve"
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "devices": [
- {
- "deviceId": "string",
- "name": "string",
- "platform": "string",
- "appVersion": "string",
- "lastIp": "string",
- "createdAt": 0,
- "lastSeenAt": 0
}
], - "limit": 0,
- "used": 0
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}Its token stops working (401 DEVICE_REVOKED) and its WebSocket is closed.
| deviceId required | string |
| ok required | boolean Value: true |
required | object Unconstrained here; each operation's response narrows this via allOf. |
| error required | object or null Always null on success. |
required | object (Meta) |
{- "ok": true,
- "data": {
- "unpaired": "string"
}, - "error": { },
- "meta": {
- "apiVersion": "v1",
- "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",
- "timestamp": "2019-08-24T14:15:22Z",
- "revision": 0
}
}