HTTP REST API
WATCHOUT exposes an HTTP API for programmatic show control, monitoring, and integration with third-party systems. This page is organized as a practical reference with one complete endpoint table and focused examples.
Base URLs and Ports
- External control API (main API):
http://{host}:3019 - Process Manager API (per node):
http://{node_host}:3017 - Asset Manager event stream (internal tooling/UI):
http://{asset_manager_host}:3023
Replace {host} with the IP address or hostname of the node running the relevant service. For local testing, use localhost or 127.0.0.1.
The Process Manager runs on every node. Each node answers on port 3017.
Enable/Disable
The HTTP API is gated by the WATCHOUT 7 protocol toggle. Enable it in the Nodes window, under Node Info → Protocols. The Web UI toggle controls the Asset Manager browser interface, not this API.
Interactive API Docs
WATCHOUT serves a built-in reference for the HTTP API. Open it in a web browser to see every endpoint with its parameters and example responses. You can also send live requests to a running node from the page, without writing any code. It is the quickest way to explore the API and test a command.
- Interactive docs —
http://{host}:3019/test. A browsable API console that lists every endpoint and lets you try requests against the node. It is rendered with RapiDoc, an open-source viewer for OpenAPI specifications. - OpenAPI spec —
http://{host}:3019/api-docs/openapi.json. The same API described in the OpenAPI format, a standard machine-readable specification. Import it into other API tools, or use it to generate client code.
Complete Endpoint Table
The table below lists all documented HTTP endpoints in WATCHOUT.
| Scope | Port | Method | Endpoint | Purpose | Notes |
|---|---|---|---|---|---|
| System | 3019 | GET | /info | Get build/version info | |
| Docs | 3019 | GET | /test | Interactive API documentation UI | RapiDoc |
| Docs | 3019 | GET | /api-docs/openapi.json | OpenAPI schema | |
| Playback | 3019 | GET | /v0/state | Get playback state for all timelines | |
| Playback | 3019 | POST | /v0/play | Change playback state for one timeline | Body: PlaybackStateChange JSON (see below) |
| Playback | 3019 | POST | /v0/play/{timeline_id} | Play one timeline | timeline_id is numeric |
| Playback | 3019 | POST | /v0/pause/{timeline_id} | Pause one timeline | timeline_id is numeric |
| Playback | 3019 | POST | /v0/stop/{timeline_id} | Stop one timeline and reset to start | timeline_id is numeric |
| Playback | 3019 | POST | /v0/jump-to-time/{timeline_id} | Jump timeline to time | Query: time (ms), optional state (play or pause, default pause) |
| Playback | 3019 | POST | /v0/jump-to-cue/{timeline_id}/{cue_id} | Jump timeline to cue start | Query: optional state (play or pause, default pause) |
| Show | 3019 | GET | /v0/show | Get full current show JSON | |
| Show | 3019 | POST | /v0/show | Load/replace show from JSON | Body: show JSON |
| Show | 3019 | POST | /v0/showfile | Load/replace show from binary .watch data | Body: binary |
| Show | 3019 | POST | /v0/showfile?showName={name} | Load .watch and set show name | Optional query variant |
| Show | 3019 | GET | /v0/timelines | List timelines | Includes IDs and names |
| Show | 3019 | GET | /v0/cues/{timeline_id} | List cues for timeline | Includes IDs and names |
| Inputs | 3019 | GET | /v0/inputs | Get all input variable specs | Includes keys and ranges |
| Inputs | 3019 | POST | /v0/inputs | Set multiple inputs (batch) | Body: JSON array of input updates |
| Inputs | 3019 | POST | /v0/input/{key} | Set one input | Query: value, optional duration (ms) |
| Cue Sets | 3019 | GET | /v0/cue-group-state/by-id | Get cue set states by IDs | |
| Cue Sets | 3019 | POST | /v0/cue-group-state/by-id | Set multiple cue set states by IDs | Body: JSON map (groupId -> variantId) |
| Cue Sets | 3019 | POST | /v0/cue-group-state/by-id/{group_id}/{variant_id} | Set one cue set by IDs | Path params |
| Cue Sets | 3019 | GET | /v0/cue-group-state/by-name | Get cue set states by names | |
| Cue Sets | 3019 | POST | /v0/cue-group-state/by-name | Set multiple cue set states by names | Body: JSON map (groupName -> variantName) |
| Cue Sets | 3019 | POST | /v0/cue-group-state/by-name/{group_name}/{variant_name} | Set one cue set by names | Path params |
| Interaction | 3019 | POST | /v0/hittest | Hit-test stage coordinates against cues | Body includes cues, x, y |
| MSC | 3019 | POST | /v0/msc | Send MIDI Show Control command(s) | Body: JSON array |
| Stream (SSE) | 3019 | GET | /v0/sse | Legacy SSE stream | Real-time updates |
| Stream (SSE) | 3019 | GET | /v1/sse | SSE stream with initial state | Real-time updates |
| Stream (SSE) | 3019 | GET | /v2/sse | Optimized SSE stream (diff-based playback updates) | Real-time updates |
| Stream (NDJSON) | 3019 | GET | /v0/ndjson | Legacy NDJSON stream | Same event model as /v0/sse |
| Stream (NDJSON) | 3019 | GET | /v1/ndjson | NDJSON stream with initial state | Same event model as /v1/sse |
| Stream (NDJSON) | 3019 | GET | /v2/ndjson | Optimized NDJSON stream | Same event model as /v2/sse |
| Process Mgmt | 3017 | POST | /v0/shutdown | Shut down target node OS | Sent to a specific node |
| Process Mgmt | 3017 | POST | /v0/reboot | Reboot target node OS | Sent to a specific node |
| Process Mgmt | 3017 | POST | /v0/services/restart | Restart WATCHOUT services on target node | Sent to a specific node |
| Asset Manager | 3023 | GET | /sse | Asset-state event stream used by tooling/UI | Not part of the main control API |
Request Body Formats
Playback state change (POST /v0/play)
This endpoint requires a JSON body. It changes the state of one timeline.
{
"timelineId": 0,
"state": "run",
"timelineTime": 6000
}
timelineId(number, required): numeric timeline ID.state(string, required):run,pause, orstop.timelineTime(number, optional): time in milliseconds.
Batch input update (POST /v0/inputs)
[
{"key": "brightness", "value": 100.0, "duration": 2000},
{"key": "volume", "value": 0.5}
]
key(string, required): external key mapped to a WATCHOUT variablevalue(number, required): numeric value to applyduration(number, optional): interpolation duration in milliseconds
Single input update (POST /v0/input/{key})
Use query parameters instead of JSON body:
/v0/input/brightness?value=100&duration=2000
Cue set batch update by name (POST /v0/cue-group-state/by-name)
{
"Language": "English",
"Sponsor": "BrandB"
}
Send {} to reset all cue sets to default variants.
Hit test (POST /v0/hittest)
{
"cues": ["1/42", "1/43"],
"x": 960.0,
"y": 540.0
}
Response includes hit_cues with IDs that contain the given point.
Hit testing supports only 2D visual media cues. A cue that uses conditional rendering is rejected. The request returns HTTP 400 instead of a result.
{
"hit_cues": ["1/42"]
}
MIDI Show Control (POST /v0/msc)
[
{"command": {"go": {}}}
]
Event Streams
WATCHOUT provides SSE and NDJSON endpoints for real-time updates.
| Stream | Endpoint | Typical events |
|---|---|---|
| SSE v0 | /v0/sse | PlaybackState, CueVisibility |
| SSE v1 | /v1/sse | PlaybackState, Inputs, ShowRevision, CueVisibility |
| SSE v2 | /v2/sse | PlaybackState (diff), TimelineCountdowns, Inputs, ShowRevision, CueVisibility |
| NDJSON v0 | /v0/ndjson | Same as SSE v0 |
| NDJSON v1 | /v1/ndjson | Same as SSE v1 |
| NDJSON v2 | /v2/ndjson | Same as SSE v2 |
The TimelineCountdowns event (v2 streams only) reports countdown status for each timeline. The status values are:
| Status | Meaning |
|---|---|
Pre | Timeline has not yet reached the countdown zone |
Last10 | Within 10 seconds (-10000 ms) of the target time |
Last5 | Within 5 seconds (-5000 ms) of the target time |
Reached | The target time has been reached |
Timeline and Cue IDs
Many endpoints require numeric timeline_id and cue_id values. Use Copy ID from timeline/cue context menus in Producer to retrieve stable IDs.
curl Examples
On Windows PowerShell, curl is an alias for Invoke-WebRequest. Call curl.exe to run real curl. Single-quoted JSON bodies fail in PowerShell. Use double quotes with escaped inner quotes, or curl.exe.
Get system info
curl http://localhost:3019/info
Play a timeline
curl -X POST http://localhost:3019/v0/play/0
Jump timeline and continue playing
curl -X POST "http://localhost:3019/v0/jump-to-time/0?time=6000&state=play"
Set one input
curl -X POST "http://localhost:3019/v0/input/Brightness?value=0.8&duration=500"
Set multiple inputs
curl -X POST -H "Content-Type: application/json" http://localhost:3019/v0/inputs --data '[{"key":"Brightness","value":0.8},{"key":"Volume","value":0.5}]'
Read cue set states by name
curl http://localhost:3019/v0/cue-group-state/by-name
Switch one cue set by name
curl -X POST http://localhost:3019/v0/cue-group-state/by-name/Language/English
Read v2 SSE stream
curl http://localhost:3019/v2/sse
Node reboot (target node API on port 3017)
curl -X POST http://192.168.1.12:3017/v0/reboot
Security and Access
By default, the HTTP API does not require authentication. Any client that can reach the service port can call endpoints.
- Keep control ports on a trusted network.
- Use firewall rules to restrict access.
- Avoid exposing ports 3019/3017 directly to untrusted networks.
Notes
- Inbound control endpoints are documented as
GETandPOST. PUT/DELETEare not part of the documented inbound control API.- HTTP Output cues send outbound
GET/POST/PUTrequests to external systems. This is separate from the inbound REST API described here.
Related
- External Control Overview — protocols and input model.
- Variables and Inputs — keys the
/v0/inputsendpoints set. - MIDI Show Control — the
/v0/msccommand set. - The Nodes Window — enable the WATCHOUT 7 protocol toggle.