Skip to main content

Studio

Studio is the multi-track editor: tracks, clips, media and a canvas. This API manages those projects - listing them, creating them, copying them, and sharing them.

The timeline is writable, so you can assemble a video programmatically - generate a script, place the clips, then open it in the editor or render it.

Projects

GET /v1/studio/projects · POST /v1/studio/projects · GET /v1/studio/projects/:id · PATCH /v1/studio/projects/:id · DELETE /v1/studio/projects/:id

curl -X POST https://api.vidocu.ai/v1/studio/projects \
-H "Authorization: Bearer vdo_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"name": "Q3 launch cut"}'

Creating gives you an empty project with the editor's default canvas and one track.

The list is cursor-paginated, searchable by name, and returns counts rather than the timeline:

{
"id": "...",
"name": "Q3 launch cut",
"canvas": { "width": 1920, "height": 1080, "ratio": "16:9", "fps": 30 },
"totalDuration": 84.5,
"counts": { "tracks": 3, "clips": 12, "media": 5 },
"shared": false,
"isSharePublic": false
}

Fetch a single project to get tracks, clips and media in full.

Projects built by importing a video from the app (Edit in Studio) also carry sourceVideoId, the id of that video. It is informational: the video is a separate object that Studio does not own, it is unaffected by anything you do to the project, and it may since have been deleted. The field is null on every other project, is set once when the project is created, and is not writable.

PATCH covers the name, project folder and canvas settings (canvasWidth, canvasHeight, canvasRatio, fps). The timeline has its own endpoint.

Deleting removes the project. A video already exported from it is a separate object and is kept.

The timeline

PUT /v1/studio/projects/:id/timeline

Whole-document replacement. Send tracks, clips and media in full - read the project first and send the modified document back, not a fragment. Replacement rather than patching is deliberate: the three lists reference each other, and patching a graph piecemeal is how you end up with a clip pointing at a track that no longer exists.

curl -X PUT https://api.vidocu.ai/v1/studio/projects/std_123/timeline \
-H "Authorization: Bearer vdo_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"tracks": [
{"id": "t1", "type": "main", "name": "Main", "order": 0,
"locked": false, "visible": true, "volume": 100}
],
"media": [
{"id": "m1", "name": "intro.mp4", "type": "video",
"url": "https://storage.vidocu.ai/..."}
],
"clips": [
{"id": "c1", "type": "video", "trackId": "t1", "mediaId": "m1",
"startOnTimeline": 0, "duration": 12.5,
"sourceStartTime": 0, "sourceEndTime": 12.5,
"speed": 1, "volume": 100, "opacity": 100}
]
}'

What's checked

Beyond the field types:

RuleWhy
Every clip.trackId exists in tracksA clip on a missing track opens to an empty editor
video/image/audio clips have a mediaId that exists in mediaSame - the clip renders nothing
No duplicate ids within tracks, clips or mediaAmbiguous references
sourceEndTime is after sourceStartTimeA zero or negative source range

Failures name the offending clip - Clip c4 is on track t9, which isn't in tracks - rather than just rejecting the document.

totalDuration is computed from the clips, not taken from the request, so the editor and the renderer can't disagree about where the video ends.

Media must already be uploaded; register the URL you get from POST /v1/upload-url.

Duplicate

POST /v1/studio/projects/:id/duplicate

Copies the timeline into a new project, named <original> (copy) unless you pass a name.

The copy never inherits the original's share link or export state. A share token maps to one project forever, so a clone carrying it would be reachable at a URL its owner never created. Duplicating a shared project is safe.

POST /v1/studio/projects/:id/share

{ "shareUrl": "https://vidocu.ai/share/8f2a...", "isPublic": true }

Anyone with the URL can view the project, so treat creating one as publishing.

Minting is idempotent - a project keeps the same token forever, and calling again returns the existing link. {"isPublic": false} revokes visibility without changing the URL, so re-enabling it later restores the same link rather than breaking anything already shared.

A project's shared and isSharePublic flags appear on reads; the token itself is never returned in a list or a get.

Templates

GET /v1/studio/templates · POST /v1/studio/templates/:id/use

Templates the workspace can start from: its own, plus Vidocu's global gallery (marked global: true). Using one creates a new project and leaves the template untouched.

Export

POST /v1/studio/projects/:id/export

Renders the timeline to a video on Remotion Lambda.

{ "jobId": "...", "renderId": "...", "status": "processing" }

Returns 202. Rendering takes minutes - poll GET /v1/jobs/:jobId until it completes, then read exportedVideoUrl from the project.

The render runs server-side to completion, so nothing is lost if the client disconnects.

Each export counts as one against the plan's allowance regardless of length; 402 when that's exhausted. Free plans get the Vidocu watermark baked in.

This is the same render the editor runs - both call the same function, so a project exports identically whichever surface starts it.

Errors

StatusCodeCause
404not_foundNo such project or template in this workspace
400validation_errorA clip references a missing track or media item, or a field is out of range
409conflictNothing on the timeline to work with