Skip to main content
Bitfocus Companion turns a Stream Deck, or any other Companion surface, into a control panel for the Core. This page uses Companion’s Generic HTTP module and the Core API v2.
For most studios the VRA Core module for Companion is the easier choice: actions, tally feedback, variables and presets made from your studio, with no URLs to type. Use the Generic HTTP recipe below for a custom setup.
Companion’s Generic TCP/UDP and Generic OSC modules work too, once the Core’s TCP line protocol or OSC is switched on: send a route such as studio/onair as a TCP line, or /vra/studio/onair as an OSC message.

What the Generic HTTP module can do

  • Send GET, POST and other requests, with headers given as JSON. That covers every Core API route and the device token header.
  • Store a response in a custom variable.
  • It has no feedbacks that poll a URL, and it cannot pick a field out of a JSON response.
  • A non-2xx answer marks the connection with a warning.
So: use the Core’s plain-text routes, which answer one bare value such as onair, and poll them with a Companion trigger.

Create a device token

Open Studio settings → Core API in VRA Cloud, click Add device and name it, for example Companion studio. Copy the Companion header:
The token is shown only once. See Authentication and LAN access.
Does Companion run on the Core machine itself? Then use http://localhost:3002 and leave the header out. Calls from the Core machine need no token.

Add the connection

Add a Generic HTTP connection and set its Base URL to the plain-text routes of your Core:
Every action then only needs the rest of the path, like studio/onair. To avoid pasting the header into every action, create a custom variable, for example vra_auth, with the header JSON as its value. Reference that variable in the header field of each action.

Buttons that act

Add a GET action from the connection to a button. Set the URI to the route and the header to the Companion header. break-lamp stands for one of your signal identifiers. Macros are addressed by id or name. 2 is a camera number (a camera name or id works too) and Guest close one of its angles. live stands for a BOOLEAN user input variable of the station; variable writes go through VRA Cloud and need the Core’s internet connection. See Routes for all routes. The control routes are idempotent: Studio on air on a studio that is already on air answers OK and changes nothing. A toggle is fine on a button that shows the state. On a button without state, prefer explicit routes like /onair and /offair.

Buttons that show state

Generic HTTP has no polled feedback, so keep the state in custom variables and refresh them with a trigger.
1

Create a custom variable

Create a custom variable per value you want to show, for example vra_studio.
2

Create a polling trigger

Add a trigger with a Time Interval event, every 1 to 5 seconds, and optionally a Startup event. Give it a GET action from the connection with the URI studio/status and the Companion header. Store the response in vra_studio through JSON Response Data Variable. Leave JSON Stringify Result off.
3

Show the value

Put the variable in the button text. It now reads onair, recording or offair.
4

Color the button

Use Companion’s internal feedback that checks a variable value. For example: when vra_studio equals onair, set a red background.
Useful routes to poll: For a tally on a camera button, poll cameras/2/on-air into a variable such as vra_cam2 and set a red background when vra_cam2 equals 1. After the action of a button, add the same GET that writes the same variable, so the button updates at once instead of at the next poll.

When something does not work

A warning on the connection means the Core answered with an error. Open the route in a browser without /plain in the path: the JSON answer names the error, for example "error":"unauthorized". On the Core machine, http://localhost:3002/api/v2/requests lists the last calls with their status and error code. See Errors and status codes.

Existing setups with the legacy routes

Older Companion pages call Core v1 routes, such as /api/state/state, with the EXTERNAL_APP Basic header in a variable. The Core keeps answering those, see Legacy routes. Move them to a device token and the /api/v2/plain routes when you can.