Integrate with Backstage via the REST API

Last updated 28 July 2026

How to Integrate with Backstage via the REST API

Backstage exposes an HTTP REST API that allows external systems to route NDI sources, serve interactive web pages, and integrate with show controllers. Use it to connect AMX, Crestron, Bitfocus Companion, custom web dashboards, or any device that can send HTTP requests.

Before you start

  • Backstage is running on the target server
  • The REST server is enabled (Settings > NDI > "Enable NDI Input Slots (HTTP / REST Port 8080)")
  • Port 8080 is open in Windows Firewall between the controller and the Backstage server
  • You know the IP address or hostname of the Backstage server

Steps

1. Enable the REST server

Open Settings in Backstage. Expand the NDI section. Check Enable NDI Input Slots (HTTP / REST Port 8080). The REST server starts immediately on port 8080.

The REST server is enabled by default. You only need to check this setting if it was previously disabled.

2. Confirm the server is reachable

Open a browser on the controller machine and navigate to:

http://<BACKSTAGE-IP>:8080/

You will be prompted for credentials. On success, the status page shows all configured NDI input slots.

3. Query available NDI input slots

Send a GET request to /api/inputs/get to retrieve the current NDI slot configuration as JSON:

curl -u <username>:<password> http://192.168.1.10:8080/api/inputs/get

Response:

{
  "slots": [
    {
      "id": "Slot 1",
      "source": "BIRDDOG (CAM)"
    },
    {
      "id": "Slot 2",
      "source": ""
    }
  ]
}

Each slot has an id (the slot name configured in Backstage) and a source (the currently routed NDI source, empty if unrouted).

4. Route an NDI source to a slot

Send a POST request to /api/inputs/route with a JSON body:

curl -u <username>:<password> -X POST \
  -H "Content-Type: application/json" \
  -d '{"id": "Slot 1", "source": "BIRDDOG (CAM)"}' \
  http://192.168.1.10:8080/api/inputs/route

Alternatively, use a GET request with query parameters (useful for controllers that only support GET):

curl -u <username>:<password> "http://192.168.1.10:8080/api/inputs/route?id=Slot%201&source=BIRDDOG%20(CAM)"

Spaces in slot names and source names must be percent-encoded as %20 in GET query parameters.

To unroute a slot (disconnect its NDI source), send an empty source value:

curl -u <username>:<password> -X POST \
  -H "Content-Type: application/json" \
  -d '{"id": "Slot 1", "source": ""}' \
  http://192.168.1.10:8080/api/inputs/route

5. Serve and interact with Local Pages

Backstage can serve interactive web pages built with the Local Page (Web Browser) asset. When you enable Serve on Web Server on a Web Browser asset and set a Serve Path (e.g., dashboard), the page becomes available at:

http://<BACKSTAGE-IP>:8080/dashboard

These pages support real-time two-way communication. The page automatically connects via WebSocket for live variable updates:

  • Variables changed in Backstage's Node editor push instantly to the browser

  • Click events on the page fire back into the Node editor

  • Stepper and Sequence control blocks on the page send transport commands back to Backstage

For programmatic access, you can also poll or push data via REST:

  • GET /api/pages/{path}/state — returns current variable values as JSON

  • POST /api/pages/{path}/event — send a click, stepper action, sequence action, or variable change

6. Connect via WebSocket for real-time updates

For live state synchronization, open a WebSocket connection:

ws://<BACKSTAGE-IP>:8080/ws/<serve-path>

On connection, the server sends an initial state message with all current variable values:

{
  "type": "state",
  "contentVersion": 3,
  "vars": {
    "myVar": { "type": "string", "value": "Hello" },
    "brightness": { "type": "number", "value": 0.75 },
    "tint": { "type": "color", "r": 255, "g": 128, "b": 0, "a": 255 }
  }
}

Subsequent updates arrive as var, stepperState, sequenceState, or reload messages. To send events from the client, send JSON frames:

{ "type": "click", "name": "myButton" }
{ "type": "stepperAction", "action": "next", "step": 0 }
{ "type": "sequenceAction", "action": "Play" }
{ "type": "varChange", "name": "brightness", "value": "0.5", "varType": "number" }

Endpoint Reference

All endpoints are served on port 8080 (the REST/API server). A separate web server on port 80 serves Backstage Viewer downloads and is not covered here.

Method

Endpoint

Description

GET

/

Status page — lists all NDI input slots and available sources

GET

/api

Built-in API documentation page (HTML)

GET

/api/inputs/get

Returns all NDI input slot configurations as JSON

GET / POST

/api/inputs/route

Route an NDI source to an input slot. POST accepts JSON body; GET accepts query parameters id and source

GET

/{serve-path}

Serves Local Page HTML content for a Web Browser asset

GET

/api/pages/{path}/state

Returns current variable values for a Local Page as JSON

POST

/api/pages/{path}/event

Send a click event, stepper/sequence action, or variable change to a Local Page

WS

/ws/{serve-path}

WebSocket for real-time Local Page variable push and event receive

WS

/ws/companion

WebSocket for Bitfocus Companion module integration

Options explained

Setting

Description

Values / Range

Enable NDI Input Slots (HTTP / REST Port 8080)

Starts or stops the REST/API HTTP server on port 8080. Also enables NDI advertisement of the API URL.

Checkbox (default: on)

Enable (HTTP Port 80)

Starts or stops the web server on port 80. Serves Backstage Viewer downloads and node-hosted web pages.

Checkbox (default: on)

Authentication username

Username for HTTP Basic Authentication on all API endpoints.

String

Authentication password

Password for HTTP Basic Authentication on all API endpoints.

String

Common Mistakes

  • Connection refused — The REST server uses port 8080, not 80. Port 80 is the separate web server for Viewer downloads. Make sure your controller is targeting the correct port.

  • 401 Unauthorized — All API endpoints require HTTP Basic Authentication. Include the Authorization header or use -u <username>:<password> with curl. Credentials are configured in the Backstage config file.

  • 400 Bad Request on route command — Check that your JSON body uses the correct field names: id and source at the root level. The slot ID must exactly match the name configured in Backstage (case-sensitive).

  • Firewall blocking connections — Windows Firewall must allow inbound TCP on port 8080. If connecting from another machine on the network, add an inbound rule for the port.

  • Spaces in GET query parameters — When using the GET method to route an NDI source, spaces must be encoded as %20 in the URL. For example: /api/inputs/route?id=Slot%201&source=BIRDDOG%20(CAM).

  • Duplicate route commands ignored — Backstage deduplicates consecutive identical route requests to prevent deadlocks. If the slot already has the requested source, the command returns 200 but takes no action.

Tips

  • Backstage advertises its API URL via NDI. Any NDI monitor application on the network can discover the server and display its web control URL automatically.

  • For simple controllers that only support GET requests (AMX, Crestron), use the query-parameter form of /api/inputs/route instead of POST with JSON.

  • Local Pages served via the REST API support both WebSocket (preferred) and REST polling. The built-in JavaScript bridge automatically falls back to polling if WebSocket is unavailable.

  • The Bitfocus Companion WebSocket endpoint at /ws/companion provides a dedicated integration path for Companion-based button panels and stream decks.

  • Test API calls from a browser by navigating to http://<IP>:8080/api for built-in documentation, or use curl from the command line with -u <username>:<password> for authentication.

Trigger Playback via UDP — Send UDP commands to control sequences from an external device.

Integrate with Conductor — Connect Backstage to Conductor for DMX and show control.

Your First Graph — Introduction to building automation graphs in the Node editor.

Sync to Timecode (LTC) — Synchronize playback with external timecode sources.