Endpoint
Text to video
POST
https://lannevideo.com/api/v1/text-to-videoTurn a prompt into a clip. The request stays open while the model renders, usually 1 to 3 minutes, then returns the MP4 URL.
Request
curl https://lannevideo.com/api/v1/text-to-video \
-X POST \
--max-time 300 \
-H "Authorization: Bearer $NB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "Slow push-in on a barista pouring latte art, warm morning light, shallow depth of field",
"video_model": "minimax-h3",
"duration": 8,
"resolution": "768P",
"aspect_ratio": "16:9"
}'import os
import requests
resp = requests.post(
"https://lannevideo.com/api/v1/text-to-video",
headers={"Authorization": f"Bearer {os.environ['NB_API_KEY']}"},
json={
"prompt": "Slow push-in on a barista pouring latte art, warm morning light, shallow depth of field",
"video_model": "minimax-h3",
"duration": 8,
"resolution": "768P",
"aspect_ratio": "16:9",
},
timeout=300, # renders take 1 to 3 minutes
)
resp.raise_for_status()
print(resp.json())// Node.js 18+
const res = await fetch("https://lannevideo.com/api/v1/text-to-video", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.NB_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
prompt: "Slow push-in on a barista pouring latte art, warm morning light, shallow depth of field",
video_model: "minimax-h3",
duration: 8,
resolution: "768P",
aspect_ratio: "16:9"
}),
signal: AbortSignal.timeout(300_000), // renders take 1 to 3 minutes
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status} ${data.error}`);
console.log(data);<?php
$ch = curl_init('https://lannevideo.com/api/v1/text-to-video');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode([
'prompt' => 'Slow push-in on a barista pouring latte art, warm morning light, shallow depth of field',
'video_model' => 'minimax-h3',
'duration' => 8,
'resolution' => '768P',
'aspect_ratio' => '16:9',
]),
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('NB_API_KEY'),
'Content-Type: application/json',
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 300,
]);
$data = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status !== 200) {
throw new RuntimeException($data['error'] ?? "HTTP $status");
}
print_r($data);Set your client timeout to 300 seconds or more. If it gives up earlier, the render usually still finishes and shows up in your dashboard; read it with video status.
Body parameters
JSON body, sent with Content-Type: application/json.
promptstringrequiredWhat happens in the shot: subject, action, camera move, light, style. Up to 7,000 characters.
video_modelstringdefault minimax-h3minimax-h3 MiniMax H3 Ultra Fast (default), seedance-2.5 Seedance 2.5 Fast, flux-3 FLUX 3 Max. The legacy ids veo3, seedance2 and flux3 still work. See Models.durationintegerdefault 5Length in seconds:
minimax-h3 5 to 15, seedance-2.5 4 to 15, flux-3 5 to 20. A value outside the model's range falls back to 5.resolutionstringminimax-h3: 480P or 768P (default). seedance-2.5: 480p (default) or 720p. flux-3: 720p (default) or 1080p. Asking for more than a model renders gives its best resolution.aspect_ratiostringdefault 16:921:9 16:9 4:3 1:1 3:4 9:16 on every model, plus 2:1 on flux-3.motion_intensitystringdefault mediumlow, medium or high.Response
200 OK
{
"success": true,
"video_id": 48213,
"video_url": "https://…/48213.mp4",
"thumbnail_url": "https://…/48213.jpg",
"credits_used": 5,
"rate_limit": {
"count": 3,
"limit": 15,
"remaining": 12,
"reset_in_seconds": 1412,
"reset_at": "2026-10-21 16:30:00"
}
}successbooleantrue when the clip is rendered.video_idintegerId of the generation. Pass it to video status.
video_urlstringMP4 file. Download it if you need to keep it long term.
thumbnail_urlstring | nullStill frame, when the model produced one.
credits_usedintegerCredits taken from the plan for this clip.
rate_limitobjectcount, limit, remaining, reset_in_seconds and reset_at for the current 30 minute window.Examples by model
The same call with each model's strengths. Switch the language once, every block follows.
MiniMax H3, the fast default
curl https://lannevideo.com/api/v1/text-to-video \
-X POST \
--max-time 300 \
-H "Authorization: Bearer $NB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "Cinematic drone flyover of a glacier at golden hour",
"video_model": "minimax-h3",
"duration": 6,
"resolution": "768P"
}'import os
import requests
resp = requests.post(
"https://lannevideo.com/api/v1/text-to-video",
headers={"Authorization": f"Bearer {os.environ['NB_API_KEY']}"},
json={
"prompt": "Cinematic drone flyover of a glacier at golden hour",
"video_model": "minimax-h3",
"duration": 6,
"resolution": "768P",
},
timeout=300, # renders take 1 to 3 minutes
)
resp.raise_for_status()
print(resp.json())// Node.js 18+
const res = await fetch("https://lannevideo.com/api/v1/text-to-video", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.NB_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
prompt: "Cinematic drone flyover of a glacier at golden hour",
video_model: "minimax-h3",
duration: 6,
resolution: "768P"
}),
signal: AbortSignal.timeout(300_000), // renders take 1 to 3 minutes
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status} ${data.error}`);
console.log(data);<?php
$ch = curl_init('https://lannevideo.com/api/v1/text-to-video');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode([
'prompt' => 'Cinematic drone flyover of a glacier at golden hour',
'video_model' => 'minimax-h3',
'duration' => 6,
'resolution' => '768P',
]),
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('NB_API_KEY'),
'Content-Type: application/json',
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 300,
]);
$data = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status !== 200) {
throw new RuntimeException($data['error'] ?? "HTTP $status");
}
print_r($data);Seedance 2.5, vertical social
curl https://lannevideo.com/api/v1/text-to-video \
-X POST \
--max-time 300 \
-H "Authorization: Bearer $NB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "A creator unboxes sneakers to camera, natural window light, handheld",
"video_model": "seedance-2.5",
"duration": 8,
"resolution": "720p",
"aspect_ratio": "9:16"
}'import os
import requests
resp = requests.post(
"https://lannevideo.com/api/v1/text-to-video",
headers={"Authorization": f"Bearer {os.environ['NB_API_KEY']}"},
json={
"prompt": "A creator unboxes sneakers to camera, natural window light, handheld",
"video_model": "seedance-2.5",
"duration": 8,
"resolution": "720p",
"aspect_ratio": "9:16",
},
timeout=300, # renders take 1 to 3 minutes
)
resp.raise_for_status()
print(resp.json())// Node.js 18+
const res = await fetch("https://lannevideo.com/api/v1/text-to-video", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.NB_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
prompt: "A creator unboxes sneakers to camera, natural window light, handheld",
video_model: "seedance-2.5",
duration: 8,
resolution: "720p",
aspect_ratio: "9:16"
}),
signal: AbortSignal.timeout(300_000), // renders take 1 to 3 minutes
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status} ${data.error}`);
console.log(data);<?php
$ch = curl_init('https://lannevideo.com/api/v1/text-to-video');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode([
'prompt' => 'A creator unboxes sneakers to camera, natural window light, handheld',
'video_model' => 'seedance-2.5',
'duration' => 8,
'resolution' => '720p',
'aspect_ratio' => '9:16',
]),
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('NB_API_KEY'),
'Content-Type: application/json',
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 300,
]);
$data = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status !== 200) {
throw new RuntimeException($data['error'] ?? "HTTP $status");
}
print_r($data);FLUX 3, long 1080p take
curl https://lannevideo.com/api/v1/text-to-video \
-X POST \
--max-time 300 \
-H "Authorization: Bearer $NB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "One tracking shot through a neon-lit Tokyo street at night, rain reflections",
"video_model": "flux-3",
"duration": 15,
"resolution": "1080p",
"aspect_ratio": "21:9"
}'import os
import requests
resp = requests.post(
"https://lannevideo.com/api/v1/text-to-video",
headers={"Authorization": f"Bearer {os.environ['NB_API_KEY']}"},
json={
"prompt": "One tracking shot through a neon-lit Tokyo street at night, rain reflections",
"video_model": "flux-3",
"duration": 15,
"resolution": "1080p",
"aspect_ratio": "21:9",
},
timeout=300, # renders take 1 to 3 minutes
)
resp.raise_for_status()
print(resp.json())// Node.js 18+
const res = await fetch("https://lannevideo.com/api/v1/text-to-video", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.NB_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
prompt: "One tracking shot through a neon-lit Tokyo street at night, rain reflections",
video_model: "flux-3",
duration: 15,
resolution: "1080p",
aspect_ratio: "21:9"
}),
signal: AbortSignal.timeout(300_000), // renders take 1 to 3 minutes
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status} ${data.error}`);
console.log(data);<?php
$ch = curl_init('https://lannevideo.com/api/v1/text-to-video');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode([
'prompt' => 'One tracking shot through a neon-lit Tokyo street at night, rain reflections',
'video_model' => 'flux-3',
'duration' => 15,
'resolution' => '1080p',
'aspect_ratio' => '21:9',
]),
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('NB_API_KEY'),
'Content-Type: application/json',
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 300,
]);
$data = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status !== 200) {
throw new RuntimeException($data['error'] ?? "HTTP $status");
}
print_r($data);Errors
| Status | When |
|---|---|
| 400 | prompt missing or longer than 7,000 characters. |
| 401 / 403 | Key missing, invalid, or account not on the API plan. See Authentication. |
| 410 | video_model is sora2, which was retired. The body lists the current ids. |
| 429 | More than 15 generations in 30 minutes. Wait Retry-After seconds. |
| 500 | The render failed, the plan has no credits left, or the content filter blocked the prompt. error says which. |