API docs

Lumen5 Video Creation API

Turn content into video over HTTP, from automation platforms like Make, Zapier and n8n, or from AI agents over MCP.

Create Lumen5 videos from your content. Send a script or some source text, and Lumen5's agent turns it into a finished video in one of your workspaces. You can leave the style to the agent or pin down the template, voice, brand kit, aspect ratio and length yourself.

There are three ways to connect:

Quick start

  1. Create an API key at https://lumen5.com/dashboard/api/. It is shown once, so store it somewhere safe.

  2. Find the workspace to create the video in:

    curl https://lumen5.com/api/v1/video-creation/workspaces/ \
      -H "Authorization: Bearer $LUMEN5_API_KEY"
    
  3. Ask for a video:

    curl -X POST https://lumen5.com/api/v1/video-creation/requests/ \
      -H "Authorization: Bearer $LUMEN5_API_KEY" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: $(uuidgen)" \
      -d '{
        "workspace": "ws_123",
        "input_content": {"text": "Paste an article, notes or a brief here."},
        "output_settings": {"aspect_ratio": "landscape", "target_duration_seconds": 60}
      }'
    
  4. Poll GET /api/v1/video-creation/requests/{request_id}/ until status is completed or failed, or register a webhook endpoint to be told. A completed request has a video_url that opens the video in Lumen5.

Automation platforms

Lumen5 publishes apps on automation platforms, so you can create videos from your workflows without writing code: for example, turning each new blog post into a video.

Platform Status
Make Coming soon
Zapier Coming soon
n8n Coming soon

Each app connects to Lumen5 with OAuth: you sign in to Lumen5 and approve access when you add the connection, so there's no API key to create or paste. The apps are built on this API, so the options and behavior on this page apply to them too.

Until the app for your platform is available, you can use the platform's own HTTP step to call the API directly with an API key, as in the quick start above.

MCP

Lumen5 runs a Model Context Protocol (MCP) server, so AI assistants and agents can create videos as a tool. Its URL is:

https://lumen5.com/mcp

It speaks MCP's Streamable HTTP transport. Its tools work like the HTTP endpoints below, so the options, limits and errors on this page apply to it too.

Connect with OAuth

Most assistants (Claude, ChatGPT, Cursor, VS Code and others) only need the URL. Add https://lumen5.com/mcp as a custom connector or remote MCP server, and the assistant opens Lumen5 for you to sign in and approve access. Approve both permissions if you want it to create videos, not just look things up.

Lumen5 doesn't review the assistants that connect this way, so the approval screen marks them as unverified and shows where approving sends you. Only approve a connection you just started yourself.

Under the hood, the server follows the MCP authorization spec. A call without a credential gets a 401 whose WWW-Authenticate header points to https://lumen5.com/.well-known/oauth-protected-resource/mcp, which names Lumen5's authorization server (metadata at https://lumen5.com/.well-known/oauth-authorization-server). Clients register themselves, either with a client ID metadata document or through dynamic client registration at /oauth/register/, then sign the user in with the authorization-code flow and PKCE.

MCP tools

Tool What it does
list_workspaces Lists the workspaces you can create videos in.
list_recipes, list_templates, list_voices, list_blueprints, list_brand_kits List the style options, as the matching endpoints do.
preview_video_request Checks a request without creating anything, like POST /resolve/.
create_video Starts a video, like POST /requests/. Needs video:write.
get_video_request Gets a request's status and, once it's done, its video_url.
list_video_requests Lists a workspace's requests, newest first.

preview_video_request and create_video take the same body as POST /requests/, and create_video also takes an optional idempotency_key in place of the header. Lists return up to 50 results per page. When a call fails, the tool's result says why, so the assistant can correct itself.

Authentication

Send a credential on every call as Authorization: Bearer <token>. Either works:

What a credential may do depends on its scopes:

Scope Allows
basic:read Every GET, and POST /resolve/ (a dry run that changes nothing)
video:write Creating video requests and managing webhook endpoints

Workspace viewers and reviewers can read but not create videos, just as in the Lumen5 app.

Workspaces

Every call that reads or creates videos names the workspace it acts in: in the workspace query parameter for GET, and in the workspace body field for POST. There is no default workspace. Get workspace ids from GET /workspaces/.

IDs

Every id the API returns has a prefix that says what it is. Pass ids back exactly as you received them.

Prefix Names Listed by
ws_ Workspace GET /workspaces/
tpl_ Template GET /templates/
voice_ AI voice GET /voices/
bp_ Blueprint (a workspace's saved video style) GET /blueprints/
bk_ Brand kit GET /brand-kits/
req_ Video creation request GET /requests/
whep_ Webhook endpoint GET /webhook-endpoints/

Recipe ids have no prefix (for example create-promo-ad); get them from GET /recipes/.

Pagination

List endpoints return 50 items per page:

{
  "count": 120,
  "next": "https://lumen5.com/api/v1/video-creation/templates/?page=2&workspace=ws_123",
  "previous": null,
  "results": []
}

Follow next until it is null.

Choosing a style

Everything in output_settings is optional. Anything you leave out (or send as null) is chosen by the agent.

There are two ways to set a style:

Every listing endpoint accepts search to narrow the list by keywords, and only returns options the named workspace can use.

Use POST /resolve/ to check a body before sending it: it validates exactly as POST /requests/ does and returns what would be stored, without creating anything.

Endpoints

All paths are relative to https://lumen5.com.

List workspaces

GET /api/v1/video-creation/workspaces/

The workspaces the caller can create videos in. Each result: id (ws_…), label.

List recipes

GET /api/v1/video-creation/recipes/?workspace=ws_123&search=promo

The kinds of video a request can ask for. Each result: id, label, description.

List voices

GET /api/v1/video-creation/voices/?workspace=ws_123

AI voices for narration. Each result: id (voice_…), label, attributes (for example accent and gender, each a list of strings), preview_url, is_paid.

List templates

GET /api/v1/video-creation/templates/?workspace=ws_123

Each result: id (tpl_…), label, description, aspect_ratios, preview_url.

List blueprints

GET /api/v1/video-creation/blueprints/?workspace=ws_123

Each result: id (bp_…), label, description, aspect_ratio.

List brand kits

GET /api/v1/video-creation/brand-kits/?workspace=ws_123

Each result: id (bk_…), label.

Validate a request (dry run)

POST /api/v1/video-creation/resolve/

Takes the same body as creating a request. Returns 200 with the request as it would be stored (workspace, input_content, output_settings, instructions, with null for anything left to the agent), or 400 explaining what's wrong. Needs only basic:read.

Create a video

POST /api/v1/video-creation/requests/

Body:

{
  "workspace": "ws_123",
  "input_content": {
    "script": null,
    "text": "Source material for the agent to write a script from."
  },
  "output_settings": {
    "blueprint": null,
    "template": "tpl_abc",
    "voice": "voice_emma",
    "recipe": "create-promo-ad",
    "brand_kit": "bk_42",
    "aspect_ratio": "vertical",
    "target_duration_seconds": 45,
    "video_name": "Q3 product update"
  },
  "instructions": "Upbeat tone. End on a call to action to book a demo."
}
Field Required Description
workspace Yes A ws_ id.
input_content.script See below Narration, used word for word.
input_content.text See below Source material (an article, notes, a brief) for the agent to write a script from.
output_settings.blueprint No A bp_ id. Can't be combined with the settings below, apart from video_name.
output_settings.template No A tpl_ id.
output_settings.voice No A voice_ id.
output_settings.recipe No A recipe id.
output_settings.brand_kit No A bk_ id.
output_settings.aspect_ratio No landscape, square, vertical or fourfive (4:5).
output_settings.target_duration_seconds No 5 to 600.
output_settings.video_name No Up to 200 characters.
instructions See below Free-text direction for the agent.

Send at least one of script, text and instructions, and never both script and text. With instructions alone, the agent writes the script from them.

Responses:

Idempotency. Send an Idempotency-Key header (any unique string up to 255 characters, such as a UUID) so you can safely retry after a timeout or network error. Retrying with the same key and body returns the original request; the same key with a different body is refused with 409. Keys are scoped to the caller and workspace.

List video requests

GET /api/v1/video-creation/requests/?workspace=ws_123&status=running

The workspace's requests, newest first. status is optional: running, completed or failed.

Get a video request

GET /api/v1/video-creation/requests/{request_id}/

List webhook endpoints

GET /api/v1/video-creation/webhook-endpoints/

Add a webhook endpoint

POST /api/v1/video-creation/webhook-endpoints/

{
  "url": "https://example.com/lumen5-webhook",
  "events": ["request.completed", "request.failed"]
}

url must be a public https URL. Returns 201 with id (whep_…), url, events, created_at and secret (whsec_…). The secret is shown only this once; store it to verify deliveries.

An endpoint receives events for all of the caller's requests, in every workspace.

Delete a webhook endpoint

DELETE /api/v1/video-creation/webhook-endpoints/{endpoint_id}/

Returns 204.

Rotate a webhook secret

POST /api/v1/video-creation/webhook-endpoints/{endpoint_id}/rotate-secret/

Returns the endpoint with its new secret. The old secret keeps working for 24 hours, so you can update your receiver without dropping deliveries.

Get the OpenAPI schema

GET /api/v1/video-creation/schema/

No authentication needed. Use it to generate a client or to give an agent the full set of operations.

The video request object

{
  "id": "req_9f1c2d3e-…",
  "status": "completed",
  "workspace": "ws_123",
  "input_content": {"script": null, "text": "Source material…"},
  "output_settings": {
    "blueprint": null,
    "template": "tpl_abc",
    "voice": null,
    "recipe": null,
    "brand_kit": null,
    "aspect_ratio": "vertical",
    "target_duration_seconds": null,
    "video_name": null
  },
  "instructions": null,
  "video_url": "https://lumen5.com/app/?id=456",
  "error": null,
  "created_at": "2026-10-06T18:30:00Z",
  "finished_at": "2026-10-06T18:34:10Z"
}
Field Description
status running, then completed or failed.
output_settings What you asked for. null means you left it to the agent.
video_url Opens the video in Lumen5. null until there is a video.
error Why the request failed, when status is failed.
finished_at When the request completed or failed.

Webhooks

Lumen5 sends a POST with a JSON body to each endpoint subscribed to the event:

Event Sent when
request.completed A video request finished and its video is ready.
request.failed A video request failed.
{
  "event": "request.completed",
  "request_id": "req_9f1c2d3e-…",
  "workspace": "ws_123",
  "status": "completed",
  "occurred_at": "2026-10-06T18:34:10+00:00",
  "video_url": "https://lumen5.com/app/?id=456"
}

Payloads say what happened and, once there is a video, link to it in video_url (null otherwise, as for a failed request). Verify the signature before you act on a delivery or pass its video_url on. Fetch GET /requests/{request_id}/ with your own credentials for the rest of the details.

Respond with a 2xx status within 10 seconds. Redirects aren't followed. Respond with 410 Gone to unsubscribe: the endpoint is deleted and gets no further deliveries. Any other response, or no response, is retried up to 5 times over about half an hour, so the same event can arrive more than once: use request_id and event to ignore repeats.

Each delivery carries these headers:

Header Value
X-Lumen5-Event The event name.
X-Lumen5-Timestamp When the delivery was signed.
X-Lumen5-Signature One or more comma-separated signatures, each v0= followed by a hex HMAC-SHA256 signature.

To verify a delivery, compute HMAC-SHA256 over v0:{timestamp}:{raw request body} with the endpoint's secret, and accept the delivery if it matches any of the signatures in the header, comparing in constant time. Use the raw body bytes, before any JSON parsing.

The header usually holds one signature. For 24 hours after you rotate the secret, it holds one for the new secret and one for the old, so a receiver with either secret keeps verifying deliveries.

import hashlib
import hmac


def is_from_lumen5(secret: str, timestamp: str, raw_body: str, signature_header: str) -> bool:
    expected = "v0=" + hmac.new(secret.encode(), f"v0:{timestamp}:{raw_body}".encode(), hashlib.sha256).hexdigest()
    return any(hmac.compare_digest(expected, signature) for signature in signature_header.split(","))

Errors

Errors use standard HTTP status codes with a JSON body:

Status Meaning
400 The body or parameters are invalid. The body maps each bad field to a list of messages, and detail sums them up in one readable string.
401 The credential is missing, invalid, revoked or expired.
403 The credential lacks the scope, or the user's role can't make that change.
404 The workspace, request or endpoint doesn't exist or isn't visible to the caller.
409 The Idempotency-Key was already used with a different body.
429 Rate limited. Wait for the number of seconds in the Retry-After header.

Limits

Each user can create up to 300 video requests an hour, on top of Lumen5's general API rate limits.

Notes for AI agents