Developers

Typecut API reference

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

NameInDescription
cursorquery
limitquery

Response — 200

FieldTypeDescription
datarequiredProject[]
next_cursorrequiredstring | 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
FieldTypeDescription
moderequired"templates"Creation mode "templates" runs the full plan → scaffold → generate pipeline from a template + a topic (prompt) or your own script.
templateSlugrequiredstringTemplate to generate from (its scene vocabulary + pacing). Required.
workspaceIdstring | nullWorkspace to place the project in. Required when the account has multiple workspaces (else a 422 lists the candidates); omitted for workspace-scoped keys.
promptstringA topic/brief — the model writes the script. Provide this OR `script`.
scriptstringYour 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.
namestringProject name. Defaults to the script `# H1`, else the topic, else the template.
usePresetsbooleanFill unset fields from the workspace presets (voice, captions, etc.). Default true.
bulkGeneratebooleanRun generation (TTS + scenes) after scaffolding. Default true. False = plan only.
ttsPresetIdstring | nullVoice (tts_presets id). Required unless the workspace has a default voice.
durationSecondsintegerTarget 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.
musicTrackIdstring | nullOptional background music (music_tracks id; see GET /v1/catalogs/music).
audioobjectAudio 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`.
logoobjectChannel 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
FieldTypeDescription
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.
namestringProject name. Defaults to "Untitled Project".
workspaceIdstring | nullWorkspace 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".
ttsPresetIdstring | nullOptional default TTS preset for the project.

Response — 201

FieldTypeDescription
datarequiredobject

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

NameInDescription
idrequiredpath

Response — 200

FieldTypeDescription
datarequiredProjectA 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

NameInDescription
idrequiredpath
includequery

Response — 200

FieldTypeDescription
dataobject

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

NameInDescription
cursorquery
limitquery

Response — 200

FieldTypeDescription
datarequiredWorkspace[]
next_cursorrequiredstring | 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

NameInDescription
idrequiredpath

Response — 200

FieldTypeDescription
datarequiredWorkspaceA 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

FieldTypeDescription
queryrequiredstringSubject to search — a topic, person, place, event, or object.
kind"image" | "video"Media kind. Defaults to "image" (entity-specific video is sparse).
limitintegerMax results to return. Defaults to 24.

Response — 200

FieldTypeDescription
datarequiredobject

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

FieldTypeDescription
njsrequiredstringA 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_idstring | nullWorkspace (channel) to create the scene in. Required for account-level API keys; workspace-scoped keys may omit it (the scoped workspace is used).
settingsobjectOptional render settings; each field overrides the matching value in the NJS `config:` block.

Response — 201

FieldTypeDescription
datarequiredobject

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

NameInDescription
idrequiredpath

Response — 200

FieldTypeDescription
datarequiredobject

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

NameInDescription
idrequiredpath

Request body

FieldTypeDescription
renderMode"canvas" | "hyperframe"Render backend. Defaults to hyperframe.

Response — 202

FieldTypeDescription
datarequiredobject

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

NameInDescription
idrequiredpath

Response — 200

FieldTypeDescription
datarequiredobject

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

NameInDescription
idrequiredpath

Request body

FieldTypeDescription
scope"project" | "chapter" | "block"What to resolve. `chapter` requires `chapterId`; `block` requires `blockId`.
chapterIdstring
blockIdstring
dryRunbooleanWhen true, returns the credit quote without firing any generation.

Response — 200

FieldTypeDescription
datarequiredobject

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

NameInDescription
catalogrequiredpath

Response — 200

FieldTypeDescription
datarequiredobject[]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

NameInDescription
sceneIdrequiredpath

Request body

FieldTypeDescription
media_urlrequiredstringPublic URL of the image or video to use as the scene background.
is_videobooleanSet true when media_url points to a video.
thumbnail_urlstring | nullOptional pre-generated thumbnail written to the scene chip.

Response — 200

FieldTypeDescription
datarequiredobject

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.

Typecut MCP