HTTP API for managing workspaces, projects, scenes, and renders programmatically — same surface area the editor UI uses.
Base URL
https://app.typecut.ai/v1
Authentication
Bearer API keys. Create one in Settings → API keys (available on Creator plans and up), then send it on every request:
Authorization: Bearer tc_live_…
GET/projects
List projects
Returns the projects the authenticated API key can access. Account-level keys see all projects in the account; workspace-scoped keys see only projects in their workspace. Cursor-paginated (created_at DESC, id DESC).
Parameters
Name
In
Description
cursor
query
limit
query
Response — 200
Field
Type
Description
datarequired
Project[]
next_cursorrequired
string | null
200 A page of projects.400 Invalid query parameters.401 Missing or invalid API key.
POST/projects
Create a project
Create a new project. Mode-discriminated by `mode`:
- `templates` — runs the full plan → scaffold → generate pipeline from a template + a topic (`prompt`) or your own `script` (markdown-structured supported). The main path.
- `blank` — an empty project with one chapter, no planning; edit it via later API calls.
For `templates`, call GET /v1/projects/requirements first to learn the required inputs (and preview a script's parsed structure).
Request body
Variant 1 — CreateTemplateProjectRequest
Field
Type
Description
moderequired
"templates"
Creation mode "templates" runs the full plan → scaffold → generate pipeline from a template + a topic (prompt) or your own script.
templateSlugrequired
string
Template to generate from (its scene vocabulary + pacing). Required.
workspaceId
string | null
Workspace to place the project in. Required when the account has multiple workspaces (else a 422 lists the candidates); omitted for workspace-scoped keys.
prompt
string
A topic/brief — the model writes the script. Provide this OR `script`.
script
string
Your own finished narration, used as the source. Provide this OR `prompt`. May be a markdown document (see `scriptFormat`): `# Title`, `## Chapters`, paragraphs become beats. Text is used verbatim (see `scriptFidelity`).
scriptFidelity
"verbatim" | "adapt"
How faithfully to keep your `script`. 'verbatim' (segment only, never reword) or 'adapt' (default — the model may restructure/rephrase).
scriptFormat
"markdown" | "plaintext" | "auto"
How to parse `script` into chapters/blocks. 'auto' (default) detects markdown headings (`#`/`##`); 'markdown' forces it; 'plaintext' treats it as flat prose. With markdown headings, `##` define chapters and `#` becomes the project title.
name
string
Project name. Defaults to the script `# H1`, else the topic, else the template.
usePresets
boolean
Fill unset fields from the workspace presets (voice, captions, etc.). Default true.
bulkGenerate
boolean
Run generation (TTS + scenes) after scaffolding. Default true. False = plan only.
ttsPresetId
string | null
Voice (tts_presets id). Required unless the workspace has a default voice.
durationSeconds
integer
Target length (prompt mode). Ignored in verbatim script mode (length is implied).
aspectRatio
"16:9" | "9:16" | "4:3" | "1:1"
Aspect ratio. Defaults to the workspace preset, else 16:9.
musicTrackId
string | null
Optional background music (music_tracks id; see GET /v1/catalogs/music).
audio
object
Audio mix masters (0–2), mirroring the editor VO/Music/SFX faders. Each is applied multiplicatively in the render mix. Omit any to keep the editor-neutral default (vo 1, music 0.3, sfx 0.7). Read back via GET /v1/projects/{id} → `audio`.
logo
object
Channel logo / watermark — a static image pinned to a corner of every scene. `scale` is logo width as a fraction of video width (default 0.12). Omit to inherit the workspace branding preset. Read back via GET /v1/projects/{id} → `logo`.
Variant 2 — CreateBlankProjectRequest
Field
Type
Description
moderequired
"blank"
Creation mode. "blank" creates an empty project with one chapter, no LLM planning. Additional modes (e.g. "prompt") will be added in a future release.
name
string
Project name. Defaults to "Untitled Project".
workspaceId
string | null
Workspace to place the project in. Required for workspace-scoped API keys (may be omitted — the scoped workspace is used).
aspectRatio
"16:9" | "9:16" | "4:3" | "1:1"
Project aspect ratio. Defaults to "16:9".
ttsPresetId
string | null
Optional default TTS preset for the project.
Response — 201
Field
Type
Description
datarequired
object
201 Project created.400 Invalid request body.401 Missing or invalid API key.402 Plan limit reached (free tier project cap, lapsed subscription, etc).403 API key cannot create projects in the requested workspace.
GET/projects/{id}
Get a project
Fetch one project by id. Returns 404 (not 403) when the project exists but is not accessible by the API key — so callers cannot probe for existence.
Parameters
Name
In
Description
idrequired
path
Response — 200
Field
Type
Description
datarequired
Project
A video project. Belongs to one workspace (or workspace_id null). Status drives the FE lifecycle.
200 Project found.401 Missing or invalid API key.404 Project not found or not accessible.
GET/projects/{id}/trace
Get a project generation trace
A token-light audit of how a project was planned and generated — what template resolved, whether it drove the plan, the pacing decision, per-scene/model summaries, and LLM step summaries. Compact by default; opt into detail with ?include=raw (full structure_config/prompt_config/catalog + per-element model list) and/or ?include=prompts (full LLM prompt blobs). 404 (not 403) when not accessible.
Parameters
Name
In
Description
idrequired
path
include
query
Response — 200
Field
Type
Description
data
object
200 The project trace digest.401 Missing or invalid API key.404 Project not found or not accessible.
GET/workspaces
List workspaces
Returns the workspaces the API key can access. Account-level keys see all workspaces; workspace-scoped keys see only the one they are scoped to. Cursor-paginated.
Parameters
Name
In
Description
cursor
query
limit
query
Response — 200
Field
Type
Description
datarequired
Workspace[]
next_cursorrequired
string | null
200 A page of workspaces.400 Invalid query parameters.401 Missing or invalid API key.
GET/workspaces/{id}
Get a workspace
Fetch one workspace by id. Returns 404 (not 403) when the workspace exists but is not accessible by the API key.
Parameters
Name
In
Description
idrequired
path
Response — 200
Field
Type
Description
datarequired
Workspace
A workspace — per-show preset container. Holds defaults (voice, visual style, transitions, captions), brand assets, and editorial context. Projects belong to workspaces. (The underlying table is `channels`.)
200 Workspace found.401 Missing or invalid API key.404 Workspace not found or not accessible.
POST/discovery/search
Search open & archival assets
Entity-grounded asset search across open / archival sources (Wikimedia Commons, NASA, ...). Resolves the query to a real-world entity, fans out to the sources, filters to commercially-usable licenses, and returns ranked candidates with license + provenance. Read-only; no asset is downloaded or stored by this call.
Request body
Field
Type
Description
queryrequired
string
Subject to search — a topic, person, place, event, or object.
kind
"image" | "video"
Media kind. Defaults to "image" (entity-specific video is sparse).
limit
integer
Max results to return. Defaults to 24.
Response — 200
Field
Type
Description
datarequired
object
200 Ranked, license-cleared candidates.400 Invalid request body.401 Missing or invalid API key.502 Upstream discovery engine error.
POST/compositions
Create a scene from raw NJS
Submit a raw NJS scene script directly — no prompt, no LLM. The script is transpiled server-side; any declared gen elements (gen:image / gen:video / gen:stock-image / gen:stock-video / gen:html) resolve asynchronously. Returns the scene id and a public `share_url` that renders the scene live as those elements resolve. Intended for agents that already produce NJS (see the NJS reference at njs.typecut.ai). The public viewer and its polling endpoint (`GET /api/share/{token}`) need no authentication.
Request body
Field
Type
Description
njsrequired
string
A raw NJS scene script. Transpiled server-side; declared gen elements (gen:image / gen:video / gen:stock-image / gen:stock-video / gen:html) resolve asynchronously after the scene is created.
workspace_id
string | null
Workspace (channel) to create the scene in. Required for account-level API keys; workspace-scoped keys may omit it (the scoped workspace is used).
settings
object
Optional render settings; each field overrides the matching value in the NJS `config:` block.
Response — 201
Field
Type
Description
datarequired
object
201 Scene created; gen elements (if any) are resolving asynchronously.400 Invalid request body.401 Missing or invalid API key.402 Plan limit reached.403 API key cannot create scenes in the requested workspace.422 NJS failed to transpile — diagnostics are in the error `detail`.
GET/projects/{id}/render
Get render status
Poll the latest render job for a project: phase, per-scene progress, stitch progress, and the final MP4 URL (`render_url` / `job.output_url`) once completed.
Parameters
Name
In
Description
idrequired
path
Response — 200
Field
Type
Description
datarequired
object
200 Current render status.404 Project not found or not accessible.
POST/projects/{id}/render
Render a project to video
Trigger a full project video render. Validates readiness first: every chapter must have TTS audio and every scene must have visual content. On readiness failure the 422 response carries machine-readable `blockers` (chapter ids missing audio, scene ids missing visuals) so callers can resolve them programmatically. Credits are deducted up front and refunded automatically if the render cannot be queued. Poll GET /projects/{id}/render for progress and the final MP4 URL.
Parameters
Name
In
Description
idrequired
path
Request body
Field
Type
Description
renderMode
"canvas" | "hyperframe"
Render backend. Defaults to hyperframe.
Response — 202
Field
Type
Description
datarequired
object
202 Render queued.402 Insufficient credits.404 Project not found or not accessible.409 Project is already rendering.422 Project not ready to render — `blockers` lists the chapters missing audio and scenes missing visuals.503 Render queue unavailable (credits were refunded).
GET/projects/{id}/resolution
Get resolution status
What's resolved vs unresolved in a project, and the estimated credits to resolve the rest. A scene is resolved once it has renderable content; voice-over is tracked per chapter. Read-only counterpart to POST /projects/{id}/resolve — the counts match the editor's readiness UI exactly (shared logic).
Parameters
Name
In
Description
idrequired
path
Response — 200
Field
Type
Description
datarequired
object
200 Resolution status + cost quote.404 Project not found or not accessible.
POST/projects/{id}/resolve
Resolve (generate) unresolved work
Generate everything unresolved in a scope — its unresolved scenes (composition) plus voice-over. Mirrors the editor's "Generate everything" actions; each underlying generation charges and refunds itself. Scenes with nothing to generate from are skipped (`skipped_unresolvable`). Pass `dryRun:true` for the credit quote without firing anything (identical numbers to GET /projects/{id}/resolution).
Parameters
Name
In
Description
idrequired
path
Request body
Field
Type
Description
scope
"project" | "chapter" | "block"
What to resolve. `chapter` requires `chapterId`; `block` requires `blockId`.
chapterId
string
blockId
string
dryRun
boolean
When true, returns the credit quote without firing any generation.
Response — 200
Field
Type
Description
datarequired
object
200 Dry-run quote — nothing was fired.202 Resolution started — generations were queued.400 Invalid scope (e.g. chapter scope without chapterId).403 Subscription inactive (past_due / unpaid).404 Project, chapter, or block not found.
GET/catalogs/{catalog}
List a value catalog
The discoverability layer: every value project creation/editing accepts by id or slug is listable here, straight from the live registries. Catalogs: `transitions` (scene transition slugs + render mode + default duration), `caption-styles` (caption style ids + preview clips), `voices` (TTS presets — system + your own), `music` (published music tracks + license info). Pass the returned slug/id values to the matching creation or editing fields.
Parameters
Name
In
Description
catalogrequired
path
Response — 200
Field
Type
Description
datarequired
object[]
Catalog rows; the shape depends on the catalog (see description).
200 Catalog rows.404 Unknown catalog.
POST/scenes/{sceneId}/attach-media
Attach media to a scene
Set a scene's background to an image or video URL. The first editor-mutation primitive on the API: it shares the editor's media-attach service, so the change appears live in any open editor (via Realtime, applied in place) and behaves identically to picking media in the UI. Scene ids are globally unique, so the flat path is unambiguous.
Parameters
Name
In
Description
sceneIdrequired
path
Request body
Field
Type
Description
media_urlrequired
string
Public URL of the image or video to use as the scene background.
is_video
boolean
Set true when media_url points to a video.
thumbnail_url
string | null
Optional pre-generated thumbnail written to the scene chip.
Response — 200
Field
Type
Description
datarequired
object
200 Media attached; scene background updated.400 Invalid request body.401 Missing or invalid API key.403 Plan does not include API access.404 Scene not found or not accessible.
Prefer a conversation?
The same capabilities are coming to agents over MCP.