CueStrideSign up free
Docs menu

The API in your tools

Set up the CueStride API in Companion, a Stream Deck, vMix, QLab, OBS, Zapier, Make, n8n, Apple Shortcuts, and Home Assistant, and what to avoid in each.

Last checked against CueStride on 28 October 2026.

Each section below sets up one tool to press Next in a room. You need a key from Make an API key, and the room’s id: the letters and digits at the end of the room’s controller address, or the id that your first requests list. Every other command works the same way, with its own address and, for a command with options, a body: the reference lists them all.

Before you start

  • Give each tool its own key. In the key’s form, under Reach, choose One room. Under What it may do, choose Read the rooms for a tool that only shows the time, or Read and run the show for buttons. Most tools keep the key in their files, and some in their logs, as each section says. Then, if one tool’s key may have been seen, you replace only that key, and the other tools keep working. If your plan holds fewer keys than you have tools, tools share a key: see where each tool keeps the key before you replace it.
  • Type the whole address, with https://. An address that starts with http:// is redirected to https://, and most tools drop the key or the body on the way, so the command is refused or arrives without its options. Some tools put http:// in front of an address typed without it.
  • Send the key in the header wherever the tool can, with POST. Every tool here can, except the Stream Deck’s Website action and vMix’s shortcuts, which can only open an address. Tick Allow in links only for a key that goes in such a button link.
The Make an API key form, filled in for a Stream Deck: its label, one room, read and run the show, and Allow in links ticked.
A key for a Stream Deck's Website action: one room, allowed to run the show, and allowed in links.

The request

Most tools ask for the same parts, each in its own field: the method, the address, the header’s name and value, and, for some commands, a body. In every example on this page, put your room’s id in place of K7QW3ND2XA, and your key’s whole secret in place of csk_….

The request for Next is:

POST https://app.cuestride.com/api/v1/rooms/K7QW3ND2XA/playback/next
Authorization: Bearer csk_…

Next stops the running timer and cues the following one, paused at its full length, as the controller’s Next does. A second press cues the one after; it does not start the timer. For a button that also starts it, send {"autostart": true}:

POST https://app.cuestride.com/api/v1/rooms/K7QW3ND2XA/playback/next
Authorization: Bearer csk_…
Content-Type: application/json

{"autostart": true}

Every tool below that takes a body takes this one the same way, and a button link takes it in its address, as autostart=true. On the last timer, Next changes nothing, and its answer is still 200, with "changed": false, so the tool shows a success.

A command with options sends them as JSON. The request for Add a minute is:

POST https://app.cuestride.com/api/v1/rooms/K7QW3ND2XA/playback/add
Authorization: Bearer csk_…
Content-Type: application/json

{"amount": "1m"}

A tool that shows the time reads the status:

GET https://app.cuestride.com/api/v1/rooms/K7QW3ND2XA/status
Authorization: Bearer csk_…

Its answer holds running (true while the timer runs), remainingMs (the time left, in milliseconds), and timer.name (the loaded timer’s name). The reference lists the rest. remainingMs is below zero when the timer runs over time, and null, with timer also null, when no timer is loaded. Read the status once a second at most.

If a press is refused, the answer says why. 403 API_OFF means the room’s Let API keys reach this room is unticked in its Room settings. 403 SCOPE_FORBIDDEN means the key may not run the show. 404 ROOM_NOT_FOUND means the key does not reach that room, and 401 KEY_INVALID that the secret is wrong, replaced, revoked, or expired.

Companion

Companion sends the request with its HTTP Requests connection. The labels below are those of the connection’s version 3.2.0 or later, which needs Companion 4.3 or later; you pick the version when you add the connection.

Press Next

  1. In Connections, search for HTTP Requests and add it. Leave its Base URL empty and its Authentication at None.
  2. Choose a button, and under Press actions add the connection’s POST action.
  3. URL: https://app.cuestride.com/api/v1/rooms/K7QW3ND2XA/playback/next.
  4. Body: leave it as {}, or {"autostart": true} to start the timer too. To add a minute, the address ends in playback/add and the body is {"amount": "1m"}.
  5. header input(JSON): {"Authorization": "Bearer csk_…"}, typed with straight quotes. Curly quotes, which some editors put in when you paste, are not JSON, and Companion sends nothing.
  6. Leave Content Type at application/json, and press the button.

Use the POST action, never a button link in a GET. Companion sends a GET again by itself, up to twice, when the answer is an error such as 429, 500, 502, or 503, or when the connection drops, and a command sent again runs again. A POST is sent once.

Don’t put a fixed Command-Id in the header either: for about 10 minutes after the first press, every later press with that id does nothing.

Show the time left on a button

  1. In Variables, under Create custom variable, make one named cs_status.
  2. Add a trigger. Its event is Time Interval: Fixed, every 1 second. Its action is the connection’s GET, with the status address, the same header input(JSON), cs_status as its JSON Response Data Variable, and Store result as text unticked. Then turn the trigger on: a new trigger starts off.
  3. On a button, switch the text to Expression and enter msToTimestamp($(custom:cs_status)['remainingMs'], 'n[mm]:ss'). It shows a minus sign over time, and minutes past the hour as minutes: 75:00. It can read one second less than the room’s screen, which rounds up, so its minus shows in the first second over, while the screen still reads 0:00. With no timer loaded, it reads 00:00.

Companion may send this read twice. That is safe: a read changes nothing. Never put a button link in the Image from URL feedback, which loads its address whenever Companion draws the button, and again on every tick of its poll.

Companion keeps the header in its configuration, so every export and backup of it holds the key.

A Stream Deck

With the Website action

The Stream Deck’s own Website action can only open an address, so it presses with a button link, from a key made with Allow in links:

  1. Set it up when no show is running in the room. The Stream Deck app may load the address while you type or change it, and a load is a press. Use version 7.0 or later, which fixed a bug that sent the address as soon as it was typed.
  2. From System, drag Website onto a key.
  3. URL: paste the whole button link in one go: https://app.cuestride.com/api/v1/rooms/K7QW3ND2XA/playback/next?api_key=csk_…. To start the timer too, it is https://app.cuestride.com/api/v1/rooms/K7QW3ND2XA/playback/next?autostart=true&api_key=csk_….
  4. Open with: choose GET request in background, so no browser opens on the computer.

A key on Stream Deck Mobile runs the same action from the computer, which must be on with the Stream Deck app open. The link, and the key in it, is kept in the profile, in its exports, and in the backup the app makes at each update.

With a plugin

A plugin that sends web requests can send the POST with the header, so the key is in no address. Web Requests (Mac and Windows) and API Ninja (Windows) are free, and take the method, the address, and the header: Web Requests takes it as Authorization: Bearer csk_…, one header a line. If a press with the header shows the alert, use the button link above.

  • Web Requests writes each request’s headers, the key with them, to the Stream Deck’s log files. Don’t share those logs.
  • Some plugins also send their request when the key appears, when you change the page, and on a timer: Fetcher, and API Monkey’s main request. Give those only the status address. To show the loaded timer’s name on a key, Fetcher reads the status with Source Type set to JSON, JSON Path timer.name, Headers {"Authorization": "Bearer csk_…"}, and Refresh Interval (seconds) 5.

vMix

vMix HD and Basic HD

Their shortcuts open an address in a Web Browser input, so they press with a button link:

  1. Add a Web Browser input to open the links in. On Basic HD it is one of the edition’s four inputs.
  2. In Settings, Shortcuts, choose Add. Pick the key, the function BrowserNavigate, that input, and as its value the button link: https://app.cuestride.com/api/v1/rooms/K7QW3ND2XA/playback/next?api_key=csk_…. To start the timer too, the link has autostart=true before api_key, as on a Stream Deck.

The input loads the link once for each press. Anything that loads the page again presses again: BrowserReload, a change to the input’s address, or opening the preset. The link is kept in the vMix settings, or in the preset for a shortcut of the preset only. A saved preset may also hold it as the Web Browser input’s address, and so do the exports of both.

vMix 4K and above

Scripts send the header with POST. In Settings, Scripting, add a VB.NET script named CueStride next:

Dim client As New System.Net.WebClient()
client.Headers.Add("Authorization", "Bearer csk_…")
client.UploadString("https://app.cuestride.com/api/v1/rooms/K7QW3ND2XA/playback/next", "POST", "")

Then add a shortcut with the function ScriptStart and the script’s name. The script, with the key, is kept in the vMix settings, or in the preset for a script of the preset only.

Show the time

A vMix Data Source cannot send a key, so it cannot read a room. To show the countdown, show the room’s own screen in a Web Browser input. On the room’s controller, choose Links, and Share a screen opens: on the Timer card, choose Copy link, and give that link to the input. It is a screen, not a command, so a reload presses nothing. Never use the Controller card’s link, which gives full control of the room.

QLab

QLab sends no web request of its own. Both ways below need a QLab licence: Network cues and Script cues need one of any kind.

Through Companion

The key stays in Companion. Make the button in Companion, then:

  1. In Companion’s Settings, Protocols, turn on OSC Listener. Its port is 12321 unless you change it.
  2. In QLab’s Workspace Settings, Network, add a network patch: Type OSC Message, Network UDP, and as Destination the Companion computer’s address and port 12321, or 127.0.0.1 when Companion runs on the same Mac (localhost stays inside QLab).
  3. Add a Network cue with that patch, and type the button’s place: /location/1/0/0/press for page 1, row 0, column 0. Companion counts rows and columns from 0.

OSC needs no password, so anyone on the show network can press Companion’s buttons. Keep it on a network of its own.

With a Script cue

A Script cue runs curl. Keep the key in the Mac’s keychain, not in the cue, which is saved in the workspace file. Once, in Terminal, store it, and paste the key when asked. -T /usr/bin/security lets the cue’s security read it:

security add-generic-password -a qlab -s cuestride-api -T /usr/bin/security -w

The cue’s script then reads it and sends the header to curl from its input, so it is in no command line:

do shell script "/usr/bin/security find-generic-password -a qlab -s cuestride-api -w | /usr/bin/sed 's/^/Authorization: Bearer /' | /usr/bin/curl -sS --fail -m 5 -X POST -H @- https://app.cuestride.com/api/v1/rooms/K7QW3ND2XA/playback/next"

Run the cue once before the show, at the Mac. If macOS asks whether security may use the item, choose Always Allow: until someone answers, the cue waits, and curl’s time limit has not started. On a refusal, curl fails, and so does the cue, with the status in its error. The keychain item is on that Mac only: store it on each Mac that runs the show.

OBS

OBS sends a request with the free Advanced Scene Switcher plugin, from Tools, Advanced Scene Switcher:

  1. On its General tab, choose Start, and set On startup of OBS to Always start the scene switcher. Leave Log level at Default: at Log performed actions and Verbose logging, each request’s headers, the key with them, go into the OBS log.
  2. On the Macro tab, add a macro. Its condition is Hotkey, pressed. Bind its key in OBS’s Settings, Hotkeys.
  3. Its action is HTTP: send POST to the URL https://app.cuestride.com/api/v1/rooms/K7QW3ND2XA/playback/next, typed with https://, since the plugin follows no redirect.
  4. Tick Set headers and add one: Header name Authorization, Header value Bearer csk_….
  5. Empty Message body, which starts with the text --enter text--: that is not JSON, and the command is refused. Set Timeout to 5 seconds.

The plugin keeps the header in the scene collection file and in its exports. Never put a button link in a Browser source: it loads again when OBS starts, when the source’s settings change, when its page is refreshed, and, with Refresh browser when scene becomes active or Shutdown source when not visible ticked, each time its scene opens or it is shown. To show the countdown, give a Browser source the Timer card’s link, as for vMix.

Zapier, Make, and n8n

Each sends the request from a step of a workflow. Each can also run a step again by itself, and a command sent again runs again: the steps below turn that off.

Zapier

Webhooks by Zapier needs a paid Zapier plan.

  1. Add an action: Webhooks by Zapier, event Custom Request. The POST event is not the one: with its Data empty, it sends every field of the step before.
  2. Method POST, and the URL.
  3. Headers: Authorization with the value Bearer csk_…. For a command with options, add Content-Type with application/json, and put the JSON in Data.
  4. In the Zap’s advanced settings, set Autoreplay override? to Never replay. When Autoreplay is on for the account, a run that failed is otherwise run again, as many as five times, hours later.

Make

  1. Add HTTP, Make a request, with Authentication type set to API key.
  2. Under Credentials, add a key: Key Bearer csk_…, API key placement In the header, API key parameter name Authorization. Make keeps it in Keys, apart from the scenario.
  3. URL and Method POST. For a command with options, Body content type application/JSON, Body input method JSON string, and the JSON in Body content.
  4. Right-click the module, choose Add error handler, and pick Ignore. When a request times out or its connection drops, the run then ends, and Make does not send it again by itself, a minute or hours later.

After a timeout, the command may still have run: look at the room before you press again.

n8n

  1. Add an HTTP Request node: Method POST, and the URL.
  2. Authentication: Generic Credential Type, then Header Auth, with a credential whose Name is Authorization and Value Bearer csk_…. n8n keeps it out of the file a workflow downloads as.
  3. For a command with options, turn on Send Body: Body Content Type JSON, Specify Body Using JSON, and the JSON.
  4. In the node’s settings, turn on Execute Once, so a trigger that brings several items presses once, and leave Retry On Fail off.

Apple Shortcuts

A shortcut presses from Siri, a widget, the Apple Watch, or the Action button.

  1. Add Get Contents of URL, with the address.
  2. Choose Show More. Set the method to POST, and add a header: Authorization, with the value Bearer csk_….
  3. For a command with options, Request Body JSON, with a field for each: amount, 1m.
  4. Name the shortcut with words Siri cannot mistake for one of its own commands, such as “CueStride next”.

The key is saved in the shortcut. A shortcut you share, by its iCloud link or as a file, carries it, so don’t share one that holds a key: each person makes their own.

Home Assistant

Put the header in secrets.yaml, with the word Bearer:

cuestride_auth: "Bearer csk_…"

Then, in configuration.yaml, a command, and a sensor of the seconds left:

rest_command:
  cuestride_next:
    url: "https://app.cuestride.com/api/v1/rooms/K7QW3ND2XA/playback/next"
    method: post
    headers:
      Authorization: !secret cuestride_auth

sensor:
  - platform: rest
    name: "CueStride seconds left"
    resource: "https://app.cuestride.com/api/v1/rooms/K7QW3ND2XA/status"
    headers:
      Authorization: !secret cuestride_auth
    scan_interval: 5
    value_template: "{{ ((value_json.remainingMs | default(0, true)) / 1000) | round(0, 'ceil') | int }}"
    availability: "{{ value_json is defined and 'remainingMs' in value_json }}"
    unit_of_measurement: "s"

After a restart, rest_command.cuestride_next is an action for a dashboard’s button or an automation. A command is sent once; when it times out, look at the room before you press again. A refused command shows no error on the button, only a warning in Home Assistant’s log, so press it once before the show and look at the room. The sensor shows the seconds left, 0 when no timer is loaded, and Unavailable when the read is refused. secrets.yaml is a plain file in the configuration folder and its backups, and debug logging of rest_command writes the header, the key with it, to the log.

A button link runs its command every time it is loaded. Put it only where one press loads it once, never in:

  • A page that is shown: an OBS Browser source, or a vMix Web Browser input that reloads. Each load, refresh, or restart presses.
  • A spreadsheet cell: Google Sheets loads an address in IMPORTDATA again every hour.
  • Anything that refreshes or polls: Companion’s Image from URL, a Stream Deck plugin that refreshes its key, or a Home Assistant sensor. Give those the status address and the header.

To show a room’s countdown, use the Timer card’s link from Share a screen instead, as for vMix.

Where each tool keeps the key

  • Companion: its configuration, and every export and backup of it.
  • Stream Deck: the profile, its exports, and its backups. Web Requests also writes it to the logs.
  • vMix: the settings and the preset, and their exports.
  • QLab: the workspace file, unless the script reads it from the keychain.
  • OBS: the scene collection file and its exports, and the log at Log performed actions or Verbose logging.
  • Zapier: the Zap’s step and its run history, which anyone who can open the Zap sees.
  • Make, n8n: Make’s Keys and n8n’s credentials, apart from the scenario or workflow.
  • Apple Shortcuts: the shortcut, and any copy of it you share.
  • Home Assistant: secrets.yaml and its backups, and the log with debug logging on.

Next

Every command, its options, and its refusals are in the API reference.

Where it's used

Your next show, on time.

Put a room's link on a screen and run the show; sign up free when you want to keep it.