Lumavo API: Complete REST Integration Guide for Developers
A comprehensive developer guide to integrating Lumavo's AI video and image generation models into your applications. REST API reference, authentication, webhooks, and production best practices.
Overview
The Lumavo REST API gives you programmatic access to 12+ AI models for text-to-video, image-to-video, text-to-image, and text-to-audio generation. This guide covers everything from authentication to handling production workloads.
All endpoints live under https://api.lumavo.com/v1/ and accept JSON request bodies. Responses are JSON unless streaming is explicitly requested.
Authentication
Getting Your API Key
- Sign up at [lumavo.com](https://lumavo.com)
- Navigate to [API Keys](/app/api-keys)
- Click "Create API Key" and copy the key immediately (it is only shown once)
Passing Your Key
Every request must include your API key in the Authorization header:
Authorization: Bearer lumavo_sk_live_xxxxxxxxxxxxxxxxxxxxxxxx
Keys come in two flavors:
- Live keys (prefix
lumavo_sk_live_): Used in production. Charges credits. - Test keys (prefix
lumavo_sk_test_): Used in development. Free, but capped at 720p and no priority queue.
# Example: curl with live key
curl -X POST https://api.lumavo.com/v1/txt2video \
-H "Authorization: Bearer lumavo_sk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"model":"seedance-20","prompt":"A forest at dawn","duration":5}'
Security best practice: Never expose your API key in client-side code. Always route API requests through your backend server. Use environment variables for key storage.
// ❌ Don't do this — key is exposed in the browser
const API_KEY = "lumavo_sk_live_abc123";
// ✅ Do this — key stays on the server
const API_KEY = process.env.LUMAVO_API_KEY;
Core Endpoints
POST /v1/txt2video — Text to Video
Generate a video from a text prompt.
Request body:{
"model": "seedance-20",
"prompt": "A cinematic drone shot flying over a tropical coastline at sunset. Turquoise water crashes against white sand. Palm trees sway in the breeze. 4K quality.",
"duration": 5,
"resolution": "720p",
"aspectRatio": "16:9",
"quality": "pro",
"negativePrompt": "blurry, static, watermark, text overlay, low quality",
"seed": 42,
"webhookUrl": "https://your-server.com/lumavo-webhook"
}
Parameters:
| Field | Type | Required | Description |
| model | string | Yes | Model ID: seedance-20, kling-30, happyhorse-10 |
| prompt | string | Yes | Text description (max 10,000 chars) |
| duration | integer | Yes | Video length in seconds (1-15) |
| resolution | string | No | 480p or 720p (default: 720p) |
| aspectRatio | string | No | 16:9, 9:16, or 1:1 (default: 16:9) |
| quality | string | No | pro or fast (Seedance only, default: pro) |
| negativePrompt | string | No | What to avoid (max 500 chars) |
| seed | integer | No | Deterministic seed for reproducibility |
| webhookUrl | string | No | Callback URL for async completion |
{
"taskId": "task_x9K3mP7qR2vL",
"status": "queued",
"estimatedTime": 45,
"creditsConsumed": 200,
"createdAt": "2026-06-14T10:30:00Z"
}
POST /v1/img2video — Image to Video
Animate a reference image into video. Excellent for bringing still illustrations to life or creating motion from product photos.
{
"model": "seedance-20",
"referenceImage": "https://your-cdn.com/reference.jpg",
"prompt": "Gentle camera push-in. The character in frame blinks and looks to the right. Wind blows through their hair.",
"duration": 5,
"resolution": "720p",
"motionIntensity": 0.6
}
The referenceImage field accepts a publicly accessible URL. For local files, upload first using:
POST /v1/upload — File Upload
curl -X POST https://api.lumavo.com/v1/upload \
-H "Authorization: Bearer $LUMAVO_API_KEY" \
-F "file=@reference.jpg"
Returns a URL you can use in referenceImage.
POST /v1/txt2img — Text to Image
Generate still images using Flux Pro, Flux Dev, or Stable Diffusion XL.
{
"model": "flux-pro",
"prompt": "A cyberpunk street market at night. Neon signs in Japanese and English. Steam rising from food stalls. Wet pavement reflecting colored light. Photorealistic.",
"width": 1024,
"height": 1024,
"numImages": 1,
"negativePrompt": "blurry, low quality, deformed",
"seed": 42
}
Response:
{
"taskId": "task_img_b8N2v",
"status": "completed",
"images": [
{
"url": "https://cdn.lumavo.com/generated/img_b8N2v_0.png",
"width": 1024,
"height": 1024,
"creditsConsumed": 10
}
]
}
POST /v1/txt2audio — Text to Audio/Music
Generate music or sound effects using Suno v4 or Udio.
{
"model": "suno-v4",
"prompt": "Lo-fi hip hop instrumental. Warm jazz chords, vinyl crackle, relaxed boom-bap drums. 85 BPM. Rain sounds in the background.",
"duration": 30,
"genre": "lo-fi"
}
GET /v1/task/{taskId} — Check Task Status
Generation is asynchronous. Poll this endpoint to check progress.
curl https://api.lumavo.com/v1/task/task_x9K3mP7qR2vL \
-H "Authorization: Bearer $LUMAVO_API_KEY"
Responses by status:
// Status: processing
{ "taskId": "task_x9K3mP7qR2vL", "status": "processing", "progress": 45 }
// Status: completed
{
"taskId": "task_x9K3mP7qR2vL",
"status": "completed",
"output": {
"url": "https://cdn.lumavo.com/output/task_x9K3mP7qR2vL.mp4",
"duration": 5,
"resolution": "720p",
"fileSize": 4820000
},
"processingTime": 38.2
}
// Status: failed
{ "taskId": "task_x9K3mP7qR2vL", "status": "failed", "error": "Content policy violation" }
GET /v1/credits — Check Credit Balance
curl https://api.lumavo.com/v1/credits \
-H "Authorization: Bearer $LUMAVO_API_KEY"
{ "balance": 850, "plan": "Starter" }
Webhooks (Recommended for Production)
Polling is simple but wastes requests. Webhooks push task status updates to your server in real time.
1. Configure your webhook URL per request:{
"webhookUrl": "https://your-app.com/api/lumavo-webhook"
}
2. Lumavo POSTs to your endpoint when the task status changes:
{
"event": "task.completed",
"taskId": "task_x9K3mP7qR2vL",
"status": "completed",
"output": {
"url": "https://cdn.lumavo.com/output/task_x9K3mP7qR2vL.mp4",
"duration": 5,
"resolution": "720p"
},
"creditsConsumed": 200,
"timestamp": "2026-06-14T10:30:45Z"
}
3. Verify webhook signatures to prevent spoofing:
Lumavo signs every webhook payload with your webhook secret (configured in [API Keys](/app/api-keys)). Verify using HMAC-SHA256:
import crypto from "crypto";
function verifySignature(payload: string, signature: string, secret: string): boolean {
const expected = crypto
.createHmac("sha256", secret)
.update(payload, "utf-8")
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
// In your webhook handler:
const rawBody = await request.text();
const sig = request.headers.get("x-lumavo-signature");
if (!sig || !verifySignature(rawBody, sig, process.env.LUMAVO_WEBHOOK_SECRET)) {
return new Response("Invalid signature", { status: 401 });
}
Rate Limits and Concurrency
| Plan | Concurrent Requests | Requests/min | Queue Priority |
| Free | 1 | 5 | Standard |
| Starter | 2 | 20 | Standard |
| XL Pack | 10 | 60 | High |
| Studio | 25 | 120 | High |
| Enterprise | 50+ | Custom | Highest |
When you exceed your limit, the API returns 429 Too Many Requests with a Retry-After header.
Error Handling
The API uses standard HTTP status codes:
| Code | Meaning | Action |
| 200 | Success | — |
| 202 | Accepted (processing) | Poll task endpoint |
| 400 | Bad request | Check your JSON and parameters |
| 401 | Unauthorized | Verify your API key |
| 402 | Insufficient credits | Top up at [Settings](/app/settings) |
| 429 | Rate limited | Wait for Retry-After seconds |
| 500 | Server error | Retry with exponential backoff |
async function generateWithRetry(
endpoint: string,
body: Record<string, unknown>,
maxRetries = 3
): Promise<{ taskId: string }> {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
const response = await fetch(https://api.lumavo.com/v1/${endpoint}, {
method: "POST",
headers: {
"Authorization": Bearer ${process.env.LUMAVO_API_KEY},
"Content-Type": "application/json",
},
body: JSON.stringify(body),
});
if (response.ok) return response.json();
if (response.status === 429) {
const retryAfter = parseInt(response.headers.get("Retry-After") || "5");
await new Promise((r) => setTimeout(r, retryAfter * 1000));
continue;
}
if (response.status >= 500) {
const delay = Math.pow(2, attempt) * 1000;
await new Promise((r) => setTimeout(r, delay));
continue;
}
throw new Error(API error ${response.status}: ${await response.text()});
}
throw new Error("Max retries exceeded");
}
Production Checklist
- [ ] Store API keys in environment variables or a secrets manager (never in source control)
- [ ] Route all Lumavo API calls through your backend — never expose keys to the client
- [ ] Implement webhook signature verification
- [ ] Add idempotency keys (
x-idempotency-keyheader) for payment-sensitive operations - [ ] Set up monitoring for credit balance — Lumavo will stop generating when credits hit zero
- [ ] Implement exponential backoff for 429 and 5xx responses
- [ ] Cache completed outputs to avoid re-generating identical content
- [ ] Use the
seedparameter to make outputs reproducible for A/B testing - [ ] Configure webhook retries in your infrastructure (Lumavo retries up to 3 times with 30s intervals)
Next Steps
- [API Reference](/docs/api) — Full OpenAPI specification
- [Model Comparison](/blog/model-comparison-seedance-vs-kling) — Choose the right model
- [Building a Video Pipeline](/blog/building-video-pipeline-lumavo) — Production workflow guide
- [API Keys](/app/api-keys) — Manage your keys