Skip to main content
Every call to the Core API comes from one of these callers. The Core checks them in this order and the first match wins:
  1. This machine. Calls from the Core machine itself (loopback) are always allowed, with full control.
  2. A device token. A token you created for a device in VRA Cloud.
  3. Legacy authorization. Core v1’s EXTERNAL_APP Basic header, while Allow legacy authorization is on. It only opens the legacy routes.
  4. LAN access. An address the studio lets in without a token.
Anything else gets 401 unauthorized. A token that belongs to a revoked device, or to a device with a fixed IP address used from another address, ends the check at step 2 with 401. It does not fall through to legacy authorization or LAN access, even when those would let the caller in without the token. You manage all of this in VRA Cloud under Studio settings → Core API. The page has three sections: Access, Features and Devices. Changes reach the Core within moments and need no restart.

Devices and tokens

Give every Stream Deck, Companion instance, SKAARHOJ panel or script its own device. You can then see which device did what, limit it, and revoke it without touching the others.
1

Add the device

Open Studio settings → Core API and click Add device in the Devices section.
2

Set what it may do

  • Name: shows up in the request log, for example Stream Deck studio desk.
  • Access: Read only or Read and control.
  • Station: pin the device to one station. See Station safety.
  • Fixed IP address: the token only works from this address.
  • Limit to features: leave empty for every feature, or pick the features the device may use.
3

Copy the token

VRA Cloud shows the token once, together with a ready-made Stream Deck URL, Companion header and SKAARHOJ URL. Copy what you need. The token is not stored, only a hash of it. Lost it? Revoke the device and add a new one.
A token looks like vra_ followed by 32 lowercase letters and digits. Revoke stops the token at once and keeps the device in the list: the revoked token answers 401, whatever LAN access allows. Delete stops the token and removes the device. Each device in the list shows when it last called the Core, and from which address. The Core reports this to VRA Cloud about once a minute, so the time can be up to a minute behind. Without an internet connection the Core keeps the report and sends it once the cloud is back. A device that has never called shows never.

Sending the token

The Core accepts the token in three ways. Use whichever your device supports.
  • Bearer header: Companion, scripts and anything else that can send headers.
  • Query string: the native Stream Deck Website action and other devices that can only open a URL. The Core never writes the token to its request log, but the URL may end up in the device’s own history.
  • Basic password: SKAARHOJ and other devices that support HTTP Basic authentication. The username is ignored.

Access and feature limits

Access without a token

Access without a token in the Access section decides which LAN callers need no token at all. Callers let in this way get Read and control access to every feature that is switched on. A browser page cannot use this access, see Browser guard.
Whole LAN lets anyone on the studio network change the Core and the studio state. Prefer device tokens, or Listed devices with fixed addresses for the panels that cannot send a token.

Legacy authorization

Core v1 used one shared HTTP Basic header for all callers. The Core keeps accepting it while Allow legacy authorization is on, which is the default, so existing integrations keep working. The legacy header is:
  • username EXTERNAL_APP,
  • password: the base64 of the Core’s server id (the base64 of the studio id also works).
Click Generate Authorization in Studio settings → Core Settings to see the username, the password and the full header.
A legacy header opens the legacy routes only: /api/..., /status and /. It never opens /api/v2: a v2 route called with a legacy header answers 403 forbidden. The password is made from the server id, which GET / hands out to anyone, so it cannot protect the v2 routes. On the legacy routes it gets full control.
The legacy rules are weak, like on Core v1. From a private network address, EXTERNAL_APP is accepted with any password. From a private network address, other VRA app type names, like OUTPUT_PLAYER, are also accepted as username without a password; from a public address they are refused. Move your devices to tokens, then switch Allow legacy authorization off.
Legacy authorization is checked before LAN access. A device on a LAN address that still sends the EXTERNAL_APP header is identified as a legacy caller, so its /api/v2 calls answer 403 forbidden even when the studio has LAN access. Remove the header, or replace it with a device token, before you move such a device to /api/v2.

Browser guard

A web page open in a browser on the Core machine or on the studio LAN could otherwise fire Core API calls, for example an image with the source http://192.168.1.50:3002/api/v2/studio/offair. Every action is a GET, so the browser would send it without asking. For callers that are let in by their address only, the Core therefore refuses requests that a browser marks as coming from another site:
  • the request carries Sec-Fetch-Site: cross-site or Sec-Fetch-Site: same-site, or
  • the request carries an Origin header that is not the Core’s own address, including Origin: null.
Such a request answers 403 forbidden (Forbidden on the legacy routes). This applies to calls from the Core machine itself (loopback) and to calls let in through Access without a token.
  • Stream Deck, Companion, SKAARHOJ, monitoring tools and curl send neither header and are not affected.
  • The reference page the Core serves at /api/v2/docs is on the Core’s own address, so its calls pass.
  • Calls with a device token are not checked: the token already shows the caller is meant to be there. A web tool that must call the Core needs its own device token.

Refused calls

Every 401 carries WWW-Authenticate: Basic realm="VRASERVERCOREAPI", so a browser shows its login prompt. Type any username and the token as the password.
See Errors and status codes for the full list.

Switching the API or features off

  • API enabled in the Access section switches the whole API off for the studio. /api/v2 routes then answer 403 feature_disabled and legacy routes answer 403 Forbidden.
  • The Features section has a Read and a Control switch per feature: System, Core, Studio, Station, Signals, Macros, Automations, Outputs, Cameras, Variables and Legacy routes. A switched-off feature answers 403 feature_disabled and disappears from GET /api/v2, openapi.json and /api/v2/docs.

No authentication needed

These routes answer without a token: GET /api/v2/health, GET /api/v2/openapi.json, GET /api/v2/docs, and the legacy GET /status, GET /status/health and GET /. They stay up when the API is switched off. Switching off Read for the System feature also closes /api/v2/health.

Finding out why a call failed

GET /api/v2/requests lists the last 100 calls, newest first: time, address, caller, method, path, status and error code. The caller shows how the Core identified it: loopback, device:<name>, legacy:EXTERNAL_APP or lan:<label>. Tokens in the path are replaced with ***.
Run it on the Core machine, where no token is needed, or with a device that may read the System feature.