Skip to main content

Getting Started

The Vidocu API lets you upload videos, generate subtitles, translate content, create voiceovers, and export finished videos — all programmatically.

Quick start

1. Get your API key

Create an API key from the Vidocu Dashboard. Keys use the format vdo_live_....

API keys are available on every Vidocu plan. Prefer to drive Vidocu from Claude instead? The MCP integration connects with OAuth, no key needed.

2. Upload a video

# Get a presigned upload URL
curl -X POST https://api.vidocu.ai/v1/videos/upload \
-H "Authorization: Bearer vdo_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"filename": "demo.mp4",
"contentType": "video/mp4",
"name": "Product Demo"
}'

Response:

{
"id": "vid_1708300000000_abc1234",
"uploadUrl": "https://storage.vidocu.ai/...",
"videoUrl": "https://storage.vidocu.ai/..."
}

Upload the file to the presigned URL:

curl -X PUT "UPLOAD_URL_FROM_ABOVE" \
-H "Content-Type: video/mp4" \
--data-binary @demo.mp4

3. Analyze the video

curl -X POST https://api.vidocu.ai/v1/videos/vid_.../analyze \
-H "Authorization: Bearer vdo_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{}'

This returns a job ID. Analysis runs asynchronously — poll the job to track progress:

curl https://api.vidocu.ai/v1/jobs/analysis_... \
-H "Authorization: Bearer vdo_live_your_key_here"

4. Get the subtitles

Once analysis completes, fetch the generated subtitles:

curl https://api.vidocu.ai/v1/videos/vid_.../subtitles \
-H "Authorization: Bearer vdo_live_your_key_here"
{
"videoId": "vid_...",
"language": "en",
"subtitles": [
{ "startTime": 0.5, "endTime": 3.2, "text": "Welcome to the demo" }
]
}

Response shapes

Three shapes, applied everywhere:

A single resource is the object itself - not wrapped in an envelope.

{ "id": "vid_abc123", "name": "Product demo", "status": "completed" }

A collection is named, alongside its paging cursor.

{ "videos": [ ... ], "nextCursor": "eyJ0IjoiMjAy..." }

An action returns what it did, not the resource - a deletion confirms, an async job returns something to poll.

{ "deleted": true, "id": "vid_abc123" }
{ "jobId": "export_1786...", "status": "processing" }

A call that returns more than one thing names each part. GET /v1/brand-kit answers with the kit and a summary of what's in it; GET /v1/videos/:id/article answers with the article, the format it was rendered in, and the style applied. These are not envelopes around one resource - every key carries something.

{ "brandKit": { ... }, "counts": { "skills": 2, "glossary": 0 } }

Errors are always {"error": {"code": "...", "message": "..."}}; see Error handling. Some carry extra fields alongside those two - a rejected AI Recorder prompt adds a suggestion - so read code rather than matching on the shape.

What's next