| title | REST API |
|---|---|
| description | Complete reference for the OpenReels HTTP API — job management, health checks, and artifact serving. |
The OpenReels API server is a Fastify application that manages video generation jobs via a BullMQ queue backed by Redis. All endpoints are prefixed with /api/v1.
http://localhost:3000/api/v1
The host and port are configurable via the HOST and PORT environment variables (defaults: 0.0.0.0:3000).
Returns the server health status, Redis connectivity, and which API keys are configured.
Response
{
"status": "healthy",
"redis": "connected",
"jobsDir": "exists",
"keys": {
"ANTHROPIC_API_KEY": true,
"OPENAI_API_KEY": false,
"GOOGLE_API_KEY": true,
"ELEVENLABS_API_KEY": true,
"INWORLD_TTS_API_KEY": false,
"PEXELS_API_KEY": true,
"PIXABAY_API_KEY": false
}
}The status field is "healthy" when Redis is connected, "degraded" otherwise. The keys object shows which API keys are present in the environment (values are booleans, not the actual keys).
Returns aggregate statistics across all jobs.
Response
{
"totalJobs": 42,
"completedJobs": 38,
"failedJobs": 2,
"activeJobs": 2,
"totalCost": 4.57
}totalCost is the sum of actual costs (or estimated costs as fallback) for all completed jobs, rounded to two decimal places.
Creates a new video generation job and adds it to the processing queue.
Request Body
{
"topic": "The history of the Roman Colosseum",
"archetype": "editorial_caricature",
"pacing": "standard",
"platform": "youtube",
"dryRun": false,
"noMusic": false,
"noVideo": false,
"providers": {
"llm": "anthropic",
"tts": "elevenlabs",
"image": "gemini",
"stock": "pexels",
"video": "gemini",
"videoModel": "veo-3.0-generate-preview",
"music": "bundled"
},
"keys": {
"ANTHROPIC_API_KEY": "sk-ant-...",
"ELEVENLABS_API_KEY": "..."
}
}| Field | Type | Required | Default | Description |
|---|---|---|---|---|
topic |
string | Yes | - | The video topic (max 500 characters) |
archetype |
string | No | auto-selected | Visual style archetype |
pacing |
string | No | auto-selected | Pacing tier (slow, standard, fast) |
platform |
string | No | "youtube" |
Target platform |
dryRun |
boolean | No | false |
Skip rendering, produce only the DirectorScore |
noMusic |
boolean | No | false |
Skip music generation/selection |
noVideo |
boolean | No | false |
Skip AI video generation for scenes |
direction |
string | No | — | Creative direction text (free-form markdown, max 10KB). Guides the AI's DirectorScore generation. |
score |
object | No | — | A previous DirectorScore JSON for replay. Skips research, director, and critic stages. Must be a valid DirectorScore schema. |
providers |
object | No | see defaults | Provider selection per category |
keys |
object | No | {} |
BYOK (Bring Your Own Key) API keys |
Provider defaults: llm: "anthropic", tts: "elevenlabs", image: "gemini", stock: "pexels", music: "bundled".
Response 201 Created
{
"id": "1",
"topic": "The history of the Roman Colosseum",
"archetype": "editorial_caricature",
"status": "queued"
}Errors
| Status | Condition |
|---|---|
400 |
Missing or empty topic |
400 |
topic exceeds 500 characters |
400 |
Unknown archetype |
400 |
Unknown pacing tier |
400 |
Unknown platform |
400 |
direction exceeds 10KB |
400 |
direction is not a string |
400 |
score is not a valid DirectorScore schema |
Lists all jobs, sorted by creation time (newest first).
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
limit |
number | 20 |
Max jobs to return (capped at 100) |
offset |
number | 0 |
Number of jobs to skip |
Response
{
"jobs": [
{
"id": "3",
"topic": "Black holes explained",
"status": "completed",
"createdAt": "2025-01-15T10:30:00.000Z",
"completedAt": "2025-01-15T10:35:00.000Z",
"stages": { ... }
}
],
"total": 42
}Returns full metadata for a single job including stage statuses, cost estimates, research data, the DirectorScore, and critic review.
Response
{
"id": "1",
"topic": "The history of the Roman Colosseum",
"archetype": "editorial_caricature",
"status": "completed",
"createdAt": "2025-01-15T10:30:00.000Z",
"completedAt": "2025-01-15T10:35:00.000Z",
"stages": {
"research": { "status": "done", "detail": "5 key facts", "durationSec": 4.2 },
"director": { "status": "done", "detail": "8 scenes", "durationSec": 6.1 },
"tts": { "status": "done", "detail": "42s audio", "durationSec": 8.3 },
"visuals": { "status": "done", "detail": "8 assets", "durationSec": 25.7 },
"assembly": { "status": "done", "detail": "final.mp4", "durationSec": 45.2 },
"critic": { "status": "done", "detail": "Score: 8.5/10", "durationSec": 3.1 }
},
"costEstimate": { "totalCost": 0.12 },
"actualCost": { "totalCost": 0.11 },
"videoPath": "run-20250115-103000/final.mp4",
"runDir": "run-20250115-103000",
"researchData": {
"summary": "...",
"key_facts": ["..."],
"mood": "epic_cinematic"
},
"score": { ... },
"criticReview": {
"score": 8.5,
"strengths": ["..."],
"weaknesses": ["..."]
}
}Stage statuses: "pending", "running", "done", "skipped", "error"
Job statuses: "queued", "running", "completed", "failed", "cancelled"
Errors
| Status | Condition |
|---|---|
400 |
Invalid job ID format |
404 |
Job not found |
Opens a Server-Sent Events (SSE) stream for real-time job progress. See SSE Events for the full event reference.
Headers
Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
The connection sends a job:snapshot event immediately with the current job state, then streams progress events until the job completes or fails.
Errors
| Status | Condition |
|---|---|
400 |
Invalid job ID format |
404 |
Job not found in queue or on disk |
Deletes a job and all its artifacts from disk. Active or queued jobs cannot be deleted.
Response
{ "status": "deleted" }Errors
| Status | Condition |
|---|---|
400 |
Invalid job ID format |
404 |
Job not found |
409 |
Job is active or waiting |
Requests cancellation of a running or queued job. The worker checks for the cancel flag between pipeline stages.
Response
{ "status": "cancelled" }Errors
| Status | Condition |
|---|---|
400 |
Invalid job ID format |
404 |
Job not found |
409 |
Job already completed or failed |
Serves files from a job's output directory. Path traversal is prevented by validating the resolved path stays within the job directory.
Examples
GET /api/v1/jobs/1/artifacts/run-20250115-103000/final.mp4
GET /api/v1/jobs/1/artifacts/run-20250115-103000/scene-001.png
Errors
| Status | Condition |
|---|---|
400 |
Invalid job ID format |
403 |
Path traversal attempt |
404 |
Artifact not found |
Returns the list of available visual style archetypes with their configuration.
[
{
"name": "editorial_caricature",
"captionStyle": "glitch",
"artStyle": "editorial caricature with bold outlines",
"mood": "satirical",
"colorPalette": "high contrast",
"scenePacing": "standard",
"motionIntensity": "medium"
}
]Returns available target platforms with their video specifications.
[
{
"name": "youtube",
"width": 1080,
"height": 1920,
"fps": 30,
"maxDurationSeconds": 60
}
]Returns available providers grouped by category.
{
"llm": [
{ "key": "anthropic", "label": "Anthropic (Claude)" },
{ "key": "openai", "label": "OpenAI (GPT)" },
{ "key": "gemini", "label": "Google Gemini" }
],
"tts": [
{ "key": "elevenlabs", "label": "ElevenLabs" },
{ "key": "inworld", "label": "Inworld" },
{ "key": "kokoro", "label": "Kokoro (Local)" },
{ "key": "gemini-tts", "label": "Gemini TTS" },
{ "key": "openai-tts", "label": "OpenAI TTS" }
],
"image": [
{ "key": "gemini", "label": "Google Gemini" },
{ "key": "openai", "label": "OpenAI (GPT Image)" }
],
"video": [
{ "key": "gemini", "label": "Google Veo" },
{ "key": "fal", "label": "fal.ai (Kling, Wan, etc.)" }
]
}| Variable | Default | Description |
|---|---|---|
REDIS_URL |
redis://localhost:6379 |
Redis connection URL |
PORT |
3000 |
HTTP server port |
HOST |
0.0.0.0 |
HTTP server bind address |
JOBS_DIR |
./jobs |
Directory for job artifacts |
MAX_JOBS |
0 (disabled) |
Auto-prune completed jobs when count exceeds this limit |