Getting started
What is Rundown Studio?Create an accountRundown
Rundown basicsColumnsTemplatesSettingsTrashCell historyMentionsText variablesRunning a showImport CSV rundownEvent
Event basicsSharing eventsAPI
Getting startedAPI reference ↗Build a rundown from CSVWorking with cell contentLive updates over SSEAdvanced usageError referenceMigrating from v0API v0 (deprecated)Integrations
Companion ModuleQLabSharing and outputs
Read-only rundownEditable rundownOutputPrompterPDF exportCSV exportAccount
Your teamSubscription and invoicesUpdates
ChangelogAPI
Programmatic access to the rundowns that drive your live shows — built for scripts, automations, and AI agents.
The Rundown Studio API gives you full programmatic access to your rundowns: build and edit shows, write cells, and run the show itself — start, pause, advance — over plain HTTPS with JSON. It is designed to be driven by scripts, automations, and AI agents as readily as by people: predictable JSON, snake_case everywhere, and errors that tell you how to fix them.
Base URL: https://api-v1.rundownstudio.app
API reference
The complete endpoint-by-endpoint reference lives on the hosted API documentation page, generated straight from the OpenAPI spec — it is always in sync with the live API:
📖 API reference https://api-v1.rundownstudio.app/docs →The raw OpenAPI 3.1 spec is available at https://api-v1.rundownstudio.app/openapi.yml — feed it to your code generator or your AI agent.
The pages in this section cover everything the reference doesn’t: getting a token, worked examples, the error catalog, and migrating from the v0 API.
Two surfaces
- Data plane — REST/JSON CRUD over rundowns, cues, columns, cells, mentions, and text variables. This is where you build and edit a show:
GET /rundowns,POST /rundowns/:id/cues,PATCH /rundowns/:id/cues/:cue_id/cells, and so on. - Rundown control — live show control: read
status,countdown, andoutput-message, then drive the show withPOST /rundowns/:id/action:start,action:pause,action:next, and friends. Reads areGET; actions arePOST, so a speculative request can never start a show by accident.
Conventions
Success envelope. Every success response has the same shape:
{
"ok": true,
"message": "OK",
"data": { },
"meta": {
"request_id": "req_8f4c2b6d9e1a7c3b5d8e2f01",
"server_time": 1747000000000,
"side_effects": []
}
}
datais the primary resource alone. Related resources requested via?include=arrive in a siblingincludedobject.meta.server_time(epoch milliseconds) rides on every response — trust it over the client clock for show timing.meta.side_effectslists downstream effects your request caused (e.g. the runner re-timing after a cue edit). It is always present, often empty.
Errors. Every error is an RFC 9457 application/problem+json document. The detail field says what went wrong and how to fix it; code is a stable, dot-namespaced identifier you can branch on; type links to the error reference entry for that code.
Naming and time. snake_case on the wire. Timing fields are epoch milliseconds; audit fields (created_at, updated_at, …) are ISO 8601 strings.
Pagination. Cursor-based: ?cursor=&limit=, id-ascending. Large lists return { items, next_cursor, has_more }. The default page size is 25, the maximum 100.
Stability. The wire shape is a contract: fields are only ever added, never removed or renamed. Breaking changes ship as a new major version.
Rate limits and caps
Requests are bucketed per team — all tokens belonging to one team share the budget.
| Limit | Value |
|---|---|
| Requests per minute (free plan) | 20 |
| Requests per minute (paid plans) | 120 |
| Request body size | 1 MB |
Items per :bulk request | 500 |
| Cues per rundown | 1,000 |
| Columns per rundown | 50 |
| Mentions per rundown | 100 |
| Text variables per rundown | 100 |
Every response carries RateLimit-Limit, RateLimit-Remaining, and RateLimit-Reset headers so your client can pace itself. Exceeding the limit returns 429 Too Many Requests with a Retry-After header.
What about the v0 API?
The previous API remains available at /api-v0 until July 1, 2028, but it is deprecated and new integrations should not use it. See Migrating from v0 for the timeline and an endpoint-by-endpoint mapping.