DEVELOPER DOCS

Build with elevideo

Add captions and AI-powered overlays to any video with a single API call. Send a URL, pick a style, get back a polished MP4.

Welcome

elevideo turns raw videos into captioned and AI-edited content through a simple REST API, CLI, or MCP integration. Here's what you can do:

  • Add captions — upload any video and get back styled, word-timed captions in 30+ visual styles
  • Apply AI edits — let AI analyze your video's transcript and generate overlay graphics (property listings, product demos, podcast clips, and more)
  • Re-style for free — once a video is transcribed, re-run it with any other style at no extra cost

New here? Start with the Quickstart below — you'll have a captioned video in under 5 minutes.

Quickstart

Get your first captioned video in under 5 minutes.

  1. Get an API key — create one below or on your account page
  2. Caption your video — call POST /api/v1/captions with any public video_url and optional style_id. You'll get back a run ID immediately while we process it in the background.
  3. Wait for it — call GET /api/v1/render/:id until status is "completed". Your captions are ready.
  4. Download your video — call POST /api/v1/render/:id/export, then poll until export_status is "completed" and grab the download_url.

Here's the complete flow:

# 1. Add captions to a video
curl -X POST https://api.elevideo.dev/v1/captions \
  -H "X-API-Key: ck_your_key" \
  -H "Content-Type: application/json" \
  -d '{"video_url": "https://example.com/video.mp4", "style_id": "holographic"}'

# 2. Poll status (repeat until status = "completed")
curl https://api.elevideo.dev/v1/render/run_abc123 \
  -H "X-API-Key: ck_your_key"

# 3. Trigger export
curl -X POST https://api.elevideo.dev/v1/render/run_abc123/export \
  -H "X-API-Key: ck_your_key"

# 4. Poll again until export_status = "completed", then use download_url

# 5. Try a different style (free — no re-transcription)
curl -X POST https://api.elevideo.dev/v1/render/run_abc123/rerun \
  -H "X-API-Key: ck_your_key" \
  -H "Content-Type: application/json" \
  -d '{"style_id": "beast"}'

Once you have this working, try applying a different style — see Browse Styles for all 32 options.

How It Works

The pipeline

Upload Video ──▶ POST /captions ──▶ Transcription ──▶ Composition Built
                    or POST /ai-edits                     status: "completed"
                                                                │
                                                                ▼
                                                    POST /render/:id/export
                                                         (async)
                                                                │
                                                                ▼
                                                      Server-side Render
                                                                │
                                                                ▼
                                                    Upload to CDN ──▶ download_url
  1. You provide a video URL and optionally a style ID
  2. The API transcribes your video with word-level timing
  3. For caption styles: builds a composition with styled captions overlaid on your video
  4. For AI edit styles: also uses AI to extract highlights, quotes, or structured data from the transcript
  5. Once the composition is built, you trigger an export which renders a final MP4 on our servers
  6. The rendered MP4 is uploaded to CDN and a download URL is returned

What's a composition?

Every completed render produces a composition object — the full set of rendering instructions including captions, timing, styles, and overlays. You can retrieve any render's composition via GET /api/v1/render/:id. It contains:

  • segments — video clips with timing, transitions, animations
  • captions — word-level caption data with style configuration
  • transcriptionWords — raw word timing from transcription
  • audioUrl — extracted audio track
  • styleParams — video effects (zoom, pan, blur)
  • aiEditTemplate — AI-extracted overlay data (for AI edit styles)

Every video you render is effectively a reusable template. Process the same video with different styles and get different outputs — all from a single transcription.

Tracking progress

Both render and export operations are asynchronous. The API responds immediately and processes in the background. Poll the render endpoint to track progress.

Status transitions:

processing ──▶ completed ──▶ (trigger export) ──▶ rendering ──▶ uploading ──▶ completed
     │                                                         │
     ▼                                                         ▼
   failed                                                    failed
  • processing — transcription + composition in progress
  • completed — composition ready, can view or export
  • failed — processing error (check error_message)
  • rendering — server-side export in progress
  • uploading — rendered MP4 uploading to CDN
  • export_status: "completed"download_url available

Re-runs: change styles for free

Once a video is transcribed, you can re-run it with any other style at no cost using POST /render/:id/rerun. Caption re-runs complete instantly. AI edit re-runs only need a brief LLM step. No credits charged.

Now that you understand the flow, explore Add Captions or Apply AI Edits.

CLI

Prefer working from the terminal? The elevideo CLI handles uploads, rendering, and downloads in one command.

Install with npm:

npm install -g @elevideo/cli

Set your API key:

elevideo auth --key ck_your_key

Then render a video:

elevideo render ./video.mp4 --style bold --flow captions
# ✓ Uploaded  (12.4 MB)
# ✓ Rendering … done
# ✓ Exported  → video-bold.mp4

elevideo styles captions # list available caption styles
elevideo renders         # list past renders
elevideo status <run-id> # check render status

MCP Integration

Let AI agents render videos on your behalf. The elevideo MCP server connects to Claude Desktop, Cursor, or any MCP-compatible client — your agent calls the tools, we handle the rest.

Install the server:

npm install -g @elevideo/mcp-server

Claude Desktop — add to ~/Library/Application Support/Claude/claude_desktop_config.json

{
  "mcpServers": {
    "elevideo": {
      "command": "elevideo-mcp",
      "env": {
        "ELEVIDEO_API_KEY": "ck_your_key"
      }
    }
  }
}

Cursor — add to .cursor/mcp.json in your project

{
  "mcpServers": {
    "elevideo": {
      "command": "elevideo-mcp",
      "env": {
        "ELEVIDEO_API_KEY": "ck_your_key"
      }
    }
  }
}

Available tools:

  • render_video — render a video with a template
  • check_render_status — poll render progress
  • export_render — trigger MP4 export
  • list_templates — list all caption styles and AI templates
  • get_account — check credit balance

Authentication

Every API request needs to be authenticated so we know who's making it and which credit balance to use. Pass your API key in the X-API-Key header:

curl -H "X-API-Key: ck_your_key_here" \
  https://api.elevideo.dev/v1/account

Keep your key private — anyone with it can use your credits. If a key is compromised, revoke it immediately from the Account & Keys section below.

Bearer token authentication (Authorization: Bearer <token>) is also supported for browser-based integrations.

Your API Keys

Loading keys...

Add Captions

Turn any video into a captioned video. Send a URL and a style, and we'll transcribe the audio, generate word-timed captions, and build a composition you can export as MP4.

POST/api/v1/captions

Send a video URL and get back styled, word-timed captions. The response comes back immediately with a run ID — check its status with GET /render/:id.

Request body

{
  "video_url": "https://example.com/video.mp4",  // required — public URL or R2 upload URL
  "style_id": "holographic",                      // optional (default "classic") — see GET /styles/captions
  "duration_seconds": 60,                          // optional (default 30) — for credit calc
  "auto_render": true                              // optional — trigger export automatically after composition is built
}

Response

{
  "id": "run_abc123",
  "status": "processing",
  "flow_type": "captions",
  "style_id": "holographic",
  "created_on": "2026-03-25T12:00:00.000Z"
}

Returns 402 if insufficient credits. Returns 400 for invalid style_id. Credits: 0.3 per 30-second chunk (minimum 0.3). When auto_render is true, poll GET /render/:id until export_status = "completed" for the download_url.

32 caption styles across 4 categories: minimal, bold, animated, and elegant. Each controls fonts, colors, animations, and effects. Call GET /api/v1/styles/captions for the full list.

Popular styles:

"classic"       — Traditional subtitles with dark background (minimal)
"holographic"   — Cyan holographic glow with uppercase text (animated)
"beast"         — Impact font with yellow box on active word (bold)
"elegance"      — Serif script with alternating cursive words (elegant)

Want a different look? You can re-run with a new style for free after the first render.

Apply AI Edits

Transform a video with an AI-generated overlay. We transcribe the audio, then use AI to pull out the most relevant content — quotes, features, stats, or highlights — and build a styled overlay on top. Pick a style that matches your use case.

POST/api/v1/ai-edits

Transcribe a video, extract structured data with AI, and render a styled overlay. Returns immediately with a run ID — check status with GET /render/:id.

Request body

{
  "video_url": "https://example.com/video.mp4",  // required
  "style_id": "property_showcase",                // required — see GET /styles/ai-edits
  "duration_seconds": 60,                          // optional (default 30)
  "auto_render": true                              // optional — trigger export automatically after composition is built
}

Response

{
  "id": "run_abc123",
  "status": "processing",
  "flow_type": "ai_edit",
  "style_id": "property_showcase",
  "created_on": "2026-03-25T12:00:00.000Z"
}

Returns 402 if insufficient credits. Returns 400 for invalid or missing style_id.

32 AI edit overlay styles organized by industry: real estate, SaaS, personal brand, trendy, podcast, news, reviews, local business, e-commerce, and finance. Each uses AI to extract relevant data from your video's transcript. Call GET /api/v1/styles/ai-edits for the full list.

Popular styles:

"property_showcase"  — Property listing with price + features (real_estate)
"product_demo"       — SaaS product walkthrough (saas)
"tiktok_title"       — Trendy short-form content (trendy)
"podcast_clip"       — Interview clips with standout quote (podcast)

Browse Styles

Browse all available visual styles before starting a render. Each style has a unique ID you'll pass to the captions or AI edits endpoint.

GET/api/v1/styles/captions

List all 32 available caption styles. Use the style id as the style_id parameter in POST /captions.

Response

{
  "styles": [
    {
      "id": "holographic",
      "name": "Holographic",
      "description": "Cyan holographic glow with uppercase text",
      "category": "animated"
    }
  ]
}
GET/api/v1/styles/ai-edits

List all 32 available AI edit styles. Use the style id as the style_id parameter in POST /ai-edits.

Response

{
  "styles": [
    {
      "id": "property_showcase",
      "label": "Property Showcase",
      "description": "Elegant property listing with price, features, and CTA",
      "category": "real_estate"
    }
  ]
}

Export & Download

Once your composition is ready, trigger an export to produce a downloadable MP4. The export runs on our servers and typically takes 1–8 minutes depending on video length.

POST/api/v1/render/:id/export

Kick off the final MP4 render. Your composition must be ready (status = 'completed') before you can export. Poll GET /render/:id for export_status and download_url.

Parameters

:id — The render run ID

Response

{
  "render_id": "run_abc123",
  "export_status": "rendering"
}

Returns 400 if render is not yet completed. Export takes 1-8 minutes depending on video length. Poll GET /render/:id for export_status.

Re-run a Style

Try a different style without re-processing your video. Since we've already transcribed the audio, switching styles is instant for captions and takes just a few seconds for AI edits. Best of all, re-runs are free — no credits charged.

POST/api/v1/render/:id/rerun

Apply a new style to an existing render. Reuses the stored transcription — instant for captions, a few seconds for AI edits. Free, no credits charged.

Parameters

:id — The original render run ID (must be completed)

Request body

{
  "style_id": "beast"   // new style to apply (same flow type as original)
}

Response

{
  "id": "run_def456",
  "status": "completed",           // instant for captions
  "flow_type": "captions",
  "style_id": "beast",
  "parent_run_id": "run_abc123",   // links to original
  "created_on": "2026-03-25T12:00:00.000Z"
}

Returns 400 if original render is not completed or has no stored transcription. Style must match the same flow type (caption styles for captions, AI edit styles for AI edits).

Check Status

Track your render jobs and check where they are in the pipeline. Use these endpoints to poll for completion, view compositions, and list your render history.

GET/api/v1/render/:id

Check where a render is in the pipeline. Returns the current status, the full composition (once ready), and the download URL (once exported).

Parameters

:id — The render run ID returned from POST /captions or POST /ai-edits

Response

{
  "id": "run_abc123",
  "status": "completed",
  "flow_type": "captions",
  "style_id": "holographic",
  "parent_run_id": null,           // set if this is a re-run
  "composition": { ... },          // full composition when status = "completed"
  "current_stage": null,           // active processing stage: "transcribing" | "building" | "rendering" | "uploading" | null
  "download_url": "https://cdn.elevideo.dev/renders/...",
  "export_status": "completed",    // null until export triggered
  "export_progress": 1.0,          // 0–1 float during rendering, null otherwise
  "export_error": null,
  "error_message": null,
  "created_on": "2026-03-25T12:00:00.000Z"
}
GET/api/v1/renders

List all your render jobs, newest first. Includes both caption and AI edit renders.

Response

{
  "renders": [
    {
      "id": "run_abc123",
      "status": "completed",
      "flow_type": "captions",
      "style_id": "holographic",
      "source_file_name": "video.mp4",
      "created_on": "2026-03-25T12:00:00.000Z"
    }
  ]
}

Webhooks

Instead of polling for render status, have us notify you. Register a webhook URL and we'll send an HTTP POST whenever a render starts, completes, fails, or finishes exporting. This is especially useful for background automations, CI/CD pipelines, and AI agent workflows where you don't want to sit in a polling loop.

Webhook events:

"render.started"          — job began processing
"render.completed"        — composition ready (status = "completed")
"render.failed"           — job failed
"render.export_completed" — MP4 export done, download_url available
"render.export_failed"    — export failed

Payload example:

{
  "event": "render.completed",
  "data": {
    "id": "run_abc123",
    "status": "completed",
    "flow_type": "captions",
    "style_id": "holographic",
    "created_on": "2026-03-25T12:00:00.000Z"
  }
}
GET/api/v1/account/webhooks

List your registered webhooks and their current status.

Response

{
  "webhooks": [
    {
      "id": "wh_abc123",
      "url": "https://your-server.com/webhook",
      "events": ["render.completed", "render.failed"],
      "active": true,
      "created_on": "2026-03-25T12:00:00.000Z"
    }
  ]
}
POST/api/v1/account/webhooks

Register a webhook URL to receive render event notifications. You can have up to 5 webhooks per account.

Request body

{
  "url": "https://your-server.com/webhook",
  "events": ["render.completed", "render.export_completed", "render.failed"]
}

Response

{
  "id": "wh_abc123",
  "url": "https://your-server.com/webhook",
  "events": ["render.completed", "render.export_completed", "render.failed"],
  "active": true,
  "created_on": "2026-03-25T12:00:00.000Z"
}

Returns 400 if URL is invalid or events list is empty. Returns 409 if you already have 5 webhooks.

DELETE/api/v1/account/webhooks/:id

Deactivate and remove a webhook. It will stop receiving events immediately.

Parameters

:id — The webhook ID

Response

{ "id": "wh_abc123", "active": false }
POST/api/v1/account/webhooks/:id/test

Send a test payload to your webhook URL to verify it's reachable. Useful for debugging delivery issues.

Parameters

:id — The webhook ID

Response

{ "success": true, "status_code": 200 }

Returns 200 even if your server returned an error — check status_code in the response.

GET/api/v1/account/webhooks/:id/deliveries

View the last 20 delivery attempts for a webhook. Helpful for debugging failed deliveries or confirming events are arriving.

Parameters

:id — The webhook ID

Response

{
  "deliveries": [
    {
      "id": "del_abc",
      "event": "render.completed",
      "success": true,
      "status_code": 200,
      "created_on": "2026-03-25T12:00:00.000Z"
    }
  ]
}

Account & Keys

Manage your API keys and check your credit balance. You can create multiple keys for different environments (development, staging, production) and revoke any key instantly.

GET/api/v1/account

Check how many credits you have left. Useful for showing a balance in your UI or gating renders before they fail with a 402.

Response

{
  "user_id": "user_123",
  "credits_remaining": 42.5
}
POST/api/v1/account/api-keys

Create a new API key. The full key is only returned once — store it securely. You won't be able to see the full key again.

Request body

{
  "name": "My Production Key"   // optional (default "Unnamed Key")
}

Response

{
  "id": "key_abc",
  "key": "ck_live_abc123...",
  "name": "My Production Key",
  "created_on": "2026-03-25T12:00:00.000Z"
}
GET/api/v1/account/api-keys

List your API keys. Keys are masked for security — only the prefix is shown.

Response

{
  "api_keys": [
    {
      "id": "key_abc",
      "name": "My Production Key",
      "key_prefix": "ck_live...",
      "active": true,
      "created_on": "2026-03-25T12:00:00.000Z"
    }
  ]
}
DELETE/api/v1/account/api-keys/:id

Revoke an API key immediately. Any requests using this key will start failing right away.

Parameters

:id — The API key ID

Response

{
  "id": "key_abc",
  "active": false
}
GET/api/v1/account/purchases

View your credit purchase history, including amounts and dates.

Response

{
  "purchases": [
    {
      "id": "purchase_abc",
      "credits": 50,
      "price_cents": 500,
      "created_on": "2026-03-25T12:00:00.000Z"
    }
  ]
}

Buy Credits

Purchase credits programmatically via Stripe. This is useful if you're building a platform on top of elevideo and want to manage billing from your backend.

GET/api/v1/billing/packages

List available credit packages and their prices. Use these values when creating a checkout session.

Response

{
  "packages": [
    { "price_cents": 500,   "price_display": "$5.00",   "credits": 50 },
    { "price_cents": 2000,  "price_display": "$20.00",  "credits": 250 },
    { "price_cents": 5000,  "price_display": "$50.00",  "credits": 700 },
    { "price_cents": 10000, "price_display": "$100.00", "credits": 1500 }
  ]
}
POST/api/v1/billing/checkout

Create a Stripe checkout session for purchasing credits. Redirect your user to the returned URL to complete payment.

Request body

{
  "price_cents": 500,
  "success_url": "https://elevideo.dev/account?checkout=success",
  "cancel_url": "https://elevideo.dev/account?checkout=cancel"
}

Response

{
  "sessionId": "cs_live_...",
  "url": "https://checkout.stripe.com/..."
}

Returns 400 if price_cents does not match a valid package.

Error Codes

All errors return a JSON body with error (machine-readable code) and message (human-readable description). Here's what each code means and when you might see it:

HTTPError CodeMeaning
400missing_video_urlNo video_url in request body
400missing_template_idNo template_id in request body
400invalid_templateTemplate ID not found
400not_readyRender not completed (cannot export yet)
400missing_fieldsRequired fields missing (checkout)
400file_too_largeFile exceeds 500MB limit
400checkout_failedStripe checkout session failed
401missing_authorizationNo auth header provided
401invalid_tokenBearer token is invalid
401missing_api_keyNo X-API-Key header
401invalid_api_keyAPI key not found or inactive
402insufficient_creditsNot enough credits for this render
404not_foundResource not found or not owned by you
429rate_limitedRate limit exceeded (100/min)
500lambda_errorServer-side rendering failed
500internal_errorUnexpected server error

Rate Limits

API requests are limited to 100 requests/minute per user. If you exceed this limit you'll receive a 429 response. Standard rate limit headers (RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset) are included in every response.

For error handling details, see Error Codes.