Endpoint
Image to video
POST
https://lannevideo.com/api/v1/image-to-videoAnimate a still. Send a public image URL and describe the motion; the clip starts from your image. Same rendering time as text to video.
Request
curl https://lannevideo.com/api/v1/image-to-video \
-X POST \
--max-time 300 \
-H "Authorization: Bearer $NB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"image_url": "https://example.com/product-still.jpg",
"prompt": "Slow orbit around the bottle, soft studio light, drops sliding down the glass",
"video_model": "minimax-h3",
"duration": 6,
"aspect_ratio": "1:1"
}'import os
import requests
resp = requests.post(
"https://lannevideo.com/api/v1/image-to-video",
headers={"Authorization": f"Bearer {os.environ['NB_API_KEY']}"},
json={
"image_url": "https://example.com/product-still.jpg",
"prompt": "Slow orbit around the bottle, soft studio light, drops sliding down the glass",
"video_model": "minimax-h3",
"duration": 6,
"aspect_ratio": "1:1",
},
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/image-to-video", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.NB_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
image_url: "https://example.com/product-still.jpg",
prompt: "Slow orbit around the bottle, soft studio light, drops sliding down the glass",
video_model: "minimax-h3",
duration: 6,
aspect_ratio: "1:1"
}),
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/image-to-video');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode([
'image_url' => 'https://example.com/product-still.jpg',
'prompt' => 'Slow orbit around the bottle, soft studio light, drops sliding down the glass',
'video_model' => 'minimax-h3',
'duration' => 6,
'aspect_ratio' => '1:1',
]),
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);The image must be reachable without login or cookies: a public HTTPS URL to a JPG, PNG or WebP file.
Body parameters
image_urlstringrequiredPublic URL of the source image. It becomes the first frame.
promptstringHow the image should move: camera, subject, atmosphere. Without it the model animates the image on its own.
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": 48214,
"video_url": "https://…/48214.mp4",
"thumbnail_url": "https://…/48214.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
Seedance 2.5, e-commerce loop
curl https://lannevideo.com/api/v1/image-to-video \
-X POST \
--max-time 300 \
-H "Authorization: Bearer $NB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"image_url": "https://example.com/sneaker.jpg",
"prompt": "The sneaker rotates slowly on a white surface, soft shadow",
"video_model": "seedance-2.5",
"duration": 5,
"resolution": "720p",
"aspect_ratio": "1:1"
}'import os
import requests
resp = requests.post(
"https://lannevideo.com/api/v1/image-to-video",
headers={"Authorization": f"Bearer {os.environ['NB_API_KEY']}"},
json={
"image_url": "https://example.com/sneaker.jpg",
"prompt": "The sneaker rotates slowly on a white surface, soft shadow",
"video_model": "seedance-2.5",
"duration": 5,
"resolution": "720p",
"aspect_ratio": "1:1",
},
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/image-to-video", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.NB_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
image_url: "https://example.com/sneaker.jpg",
prompt: "The sneaker rotates slowly on a white surface, soft shadow",
video_model: "seedance-2.5",
duration: 5,
resolution: "720p",
aspect_ratio: "1:1"
}),
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/image-to-video');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode([
'image_url' => 'https://example.com/sneaker.jpg',
'prompt' => 'The sneaker rotates slowly on a white surface, soft shadow',
'video_model' => 'seedance-2.5',
'duration' => 5,
'resolution' => '720p',
'aspect_ratio' => '1:1',
]),
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, 1080p hero shot
curl https://lannevideo.com/api/v1/image-to-video \
-X POST \
--max-time 300 \
-H "Authorization: Bearer $NB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"image_url": "https://example.com/hero-still.jpg",
"prompt": "Slow dolly-in, fabric moving in the wind, golden hour",
"video_model": "flux-3",
"duration": 10,
"resolution": "1080p"
}'import os
import requests
resp = requests.post(
"https://lannevideo.com/api/v1/image-to-video",
headers={"Authorization": f"Bearer {os.environ['NB_API_KEY']}"},
json={
"image_url": "https://example.com/hero-still.jpg",
"prompt": "Slow dolly-in, fabric moving in the wind, golden hour",
"video_model": "flux-3",
"duration": 10,
"resolution": "1080p",
},
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/image-to-video", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.NB_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
image_url: "https://example.com/hero-still.jpg",
prompt: "Slow dolly-in, fabric moving in the wind, golden hour",
video_model: "flux-3",
duration: 10,
resolution: "1080p"
}),
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/image-to-video');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode([
'image_url' => 'https://example.com/hero-still.jpg',
'prompt' => 'Slow dolly-in, fabric moving in the wind, golden hour',
'video_model' => 'flux-3',
'duration' => 10,
'resolution' => '1080p',
]),
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 | image_url missing or not a valid URL. |
| 401 / 403 | Key missing, invalid, or account not on the API plan. |
| 410 | video_model is the retired sora2. |
| 429 | More than 15 generations in 30 minutes. |
| 500 | The image could not be fetched or rendered, the plan has no credits left, or the content filter blocked it. error says which. |