Getting started

What is Rundown Studio?Create an account

Rundown

Rundown basicsColumnsTemplatesSettingsGaps and overlapsTrashCell historyMentionsText variablesRunning a showSub-timersImport CSV rundown

Event

Event basicsSharing events

API

Getting startedAPI reference ↗Build a rundown from CSVWorking with cell contentLive updates over SSESub-timers (experimental)Advanced usageError referenceMigrating from v0API v0 (deprecated)

Integrations

Companion ModuleBitfocus ButtonsOBS StudioOnTheAir VideoProPresenterQLab

Sharing and outputs

Read-only rundownEditable rundownQuick access codeOutputPrompterPDF exportCSV export

Account

Your teamSubscription and invoices

Updates

Changelog
Docs → API →

Sub-timers

Sub-timers

List a rundown's sub-timers, run them from the control plane, and read their live state from status and countdown.

Experimental. The sub-timer endpoints may change or be removed without notice. They’re marked with an Experimental badge in the API reference.

Sub-timers are extra timers on a cue - up to 20 per cue. The API can list them, start, pause and reset them, and report their live state. Their settings (name, direction, duration and so on) are read-only over the API. Create and edit them in the dashboard.

Find a sub-timer’s ID

Every sub-timer action needs the cue_id and the sub_timer_id. Either list them over the API (below), or copy them in the dashboard: open the cue’s settings (cog) menu, choose API, and click Copy “<name>” ID under Sub-timers.

List sub-timers

curl -H "Authorization: Bearer $TOKEN" \
  https://api-v1.rundownstudio.app/rundowns/YOmm4UG2SGSomuOci44c/sub-timers
{
  "ok": true,
  "message": "Returned 2 sub-timers",
  "data": {
    "items": [
      {
        "id": "tK3m9QzVw2LxR7bN4pHs",
        "name": "Q&A",
        "cue_id": "myA2WwGus2YAqE4yY6qq",
        "cue_title": "Keynote",
        "direction": "down",
        "duration_ms": 300000,
        "end_action": "continue",
        "auto_start": false,
        "show_on_output": true
      }
    ],
    "count": 2
  }
}
  • The list is not paginated. It is ordered by show order, then by each cue’s own timer order.
  • direction is down or up. end_action is stop or continue (the dashboard’s Stop / Keep counting). auto_start is Start with cue.
  • This is a data-plane endpoint: use the Authorization header. Any token that can read the rundown works.

Start, pause and reset

Three control-plane actions, each taking the same body:

POST /rundowns/:id/action:start-sub-timer
POST /rundowns/:id/action:pause-sub-timer
POST /rundowns/:id/action:reset-sub-timer
curl -X POST \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"cue_id": "myA2WwGus2YAqE4yY6qq", "sub_timer_id": "tK3m9QzVw2LxR7bN4pHs"}' \
  https://api-v1.rundownstudio.app/rundowns/YOmm4UG2SGSomuOci44c/action:start-sub-timer
  • Role: SHOWCALL or higher (SHOWCALL, EDIT or OWNER tokens). Viewer tokens get 403.
  • Auth: like the other control actions, these accept the ?token= query parameter for hardware that can’t set headers.
  • Response: the usual status snapshot, the same as the other action:* endpoints.
  • Idempotent: starting a running timer, pausing a stopped one, or resetting one that’s already reset returns 200 with an empty side_effects. A real change adds a runner.sub_timer_changed side effect.
  • The show must have started. Sub-timers run on the show’s runner, so before the first action:start these return 409 runner.not_started. Once started, they work whether the show is running, paused or ended.

There is no toggle action. Read the timer’s state from status and send start or pause.

Taking manual control of a Start with cue timer works the same as in the dashboard: after the first start, pause or reset, it runs independently of its cue.

Live state in status and countdown

GET /rundowns/:id/status now includes a sub_timers array (always present, [] when empty). It lists every sub-timer that isn’t in its reset state - running, paused or finished. Start with cue timers are included while their cue is active.

"sub_timers": [
  {
    "id": "tK3m9QzVw2LxR7bN4pHs",
    "name": "Q&A",
    "cue_id": "myA2WwGus2YAqE4yY6qq",
    "cue_title": "Keynote",
    "started_at": 1747000000000,
    "paused_at": null,
    "duration_ms": 300000
  }
]

Elapsed time is (paused_at ?? server_time) - started_at, the same local-clock approach as the cue countdown. For a countdown, remaining time is duration_ms - elapsed.

A countdown set to Stop that has finished still appears here. If you compute time yourself, cap elapsed at duration_ms for these timers, or use countdown below.

GET /rundowns/:id/countdown includes the same timers, already formatted for display:

"sub_timers": [
  {
    "id": "tK3m9QzVw2LxR7bN4pHs",
    "name": "Q&A",
    "cue_id": "myA2WwGus2YAqE4yY6qq",
    "cue_title": "Keynote",
    "direction": "down",
    "running": true,
    "display_ms": 184000,
    "display": {
      "is_overtime": false,
      "prefix": "",
      "days": 0,
      "hours": 0,
      "minutes": 3,
      "seconds": 4,
      "formatted": "03:04"
    }
  }
]

Countdowns round up to the second and count-ups round down. Overtime sets is_overtime and a + prefix.

Live updates

There is no separate sub-timer event on the live updates stream. Sub-timer changes arrive in the always-on status event, which carries the same sub_timers array as GET /status.

Errors

StatusCodeWhen
404sub_timers.not_foundThe sub-timer ID isn’t on that cue
404cues.not_foundThe cue doesn’t exist or was deleted
409runner.not_startedThe show hasn’t been started yet
403forbiddenThe token’s role is below SHOWCALL