DEVELOPER DOCS

API Reference

Render captioned and AI-edited videos programmatically. All endpoints require authentication via API key or Bearer token.

Quickstart

Go from video URL to captioned MP4 in 4 steps:

  1. Get an API key — create one below or on your account page
  2. Add captions — call POST /api/v1/captions with any public video_url and optional style_id. Returns immediately with a run ID.
  3. Poll for completion — call GET /api/v1/render/:id until status is "completed".
  4. Export & download — call POST /api/v1/render/:id/export, then poll until export_status is "completed" and grab the download_url.

Full example

# 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"}'

CLI

The Clipcode CLI lets you render videos directly from your terminal using local files or URLs.

Install

npm install -g @clipcode/cli

Authenticate

clipcode auth --key ck_your_key

Render a local file

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

clipcode styles          # list available styles
clipcode renders         # list past renders
clipcode status <run-id> # check render status

MCP — AI Agent Integration

Clipcode ships an MCP server so AI agents (Claude, Cursor, or any MCP-compatible client) can render videos autonomously — no API calls required from your code.

Install

npm install -g @clipcode/mcp-server

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

{
  "mcpServers": {
    "clipcode": {
      "command": "clipcode-mcp",
      "env": {
        "CLIPCODE_API_KEY": "ck_your_key"
      }
    }
  }
}

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

{
  "mcpServers": {
    "clipcode": {
      "command": "clipcode-mcp",
      "env": {
        "CLIPCODE_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

Pass your API key in the X-API-Key header with every request:

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

Bearer token authentication (Authorization: Bearer <token>) is also supported for web frontend integration.

Your API Keys

Loading keys...

How Renders Work

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 templates: builds a composition with styled captions overlaid on your video
  4. For AI edit templates: 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

Compositions & Re-editing

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. The composition 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 templates)

Every video you render is effectively a reusable template. You can take any public video URL, process it with different templates, and get different styled outputs from the same source.

Async Flow & Status

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

Render status progression

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 (POST /render/:id/rerun) skip transcription entirely. Caption re-runs complete instantly. AI edit re-runs only need a brief LLM step. Re-runs are free — no credits charged.

Captions

POST/api/v1/captions

Add captions to a video. Transcribes the audio and overlays styled captions. Returns immediately — poll GET /render/:id for completion.

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.

AI Edits

POST/api/v1/ai-edits

Apply an AI-powered overlay template to a video. Transcribes audio, then uses AI to extract structured data (quotes, features, stats) and renders a styled overlay. Returns immediately — poll GET /render/:id for completion.

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.

Renders

GET/api/v1/render/:id

Get the status, composition, and export details of a render job.

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 (captions and AI edits).

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"
    }
  ]
}
POST/api/v1/render/:id/export

Trigger a server-side MP4 export. The render must have status 'completed' with a composition.

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.

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

Re-run a completed render with a different style. Reuses the stored transcription — no re-transcription, no credits charged. Caption re-runs complete instantly. AI edit re-runs need a brief LLM processing step.

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).

Styles

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"
    }
  ]
}

Caption Styles

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 current list.

Example 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)

AI Edit Styles

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 current list.

Example 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)

Webhooks

Register a URL to receive HTTP POST notifications when render events occur. Useful for agents and automations that want push delivery instead of polling.

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 shape

{
  "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.

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. Maximum 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.

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.

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

List the last 20 delivery attempts for a webhook — useful for debugging.

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

GET/api/v1/account

Get your current credit balance.

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.

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 — 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. The key will immediately stop working.

Parameters

:id — The API key ID

Response

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

List your credit purchase history.

Response

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

Billing

GET/api/v1/billing/packages

List available credit packages and prices.

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.

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).

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 will receive a 429 response. Standard rate limit headers (RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset) are included in every response.