cURL
curl https://api.apipod.ai/v1/videos/generations \
-H "Authorization: Bearer $APIPOD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "muse-video-i2v",
"prompt": "A corgi surfing at sunset, cinematic, slow motion",
"first_frame_image": "https://cdn.example.com/first-frame.jpg",
"duration": 10,
"aspect_ratio": "16:9",
"style_preset": "cinematic_realistic",
"generate_audio": true
}'import os
import requests
payload = {
"model": "muse-video-i2v",
"prompt": "A corgi surfing at sunset, cinematic, slow motion",
"first_frame_image": "https://cdn.example.com/first-frame.jpg",
"duration": 10,
"aspect_ratio": "16:9",
"style_preset": "cinematic_realistic",
"generate_audio": True
}
response = requests.post(
"https://api.apipod.ai/v1/videos/generations",
headers={
"Authorization": f"Bearer {os.environ['APIPOD_API_KEY']}",
"Content-Type": "application/json",
},
json=payload,
timeout=60,
)
response.raise_for_status()
print(response.json())package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
)
func main() {
payload := map[string]any{}
if err := json.Unmarshal([]byte(`{
"model": "muse-video-i2v",
"prompt": "A corgi surfing at sunset, cinematic, slow motion",
"first_frame_image": "https://cdn.example.com/first-frame.jpg",
"duration": 10,
"aspect_ratio": "16:9",
"style_preset": "cinematic_realistic",
"generate_audio": true
}`), &payload); err != nil {
panic(err)
}
body, err := json.Marshal(payload)
if err != nil {
panic(err)
}
req, err := http.NewRequest(http.MethodPost, "https://api.apipod.ai/v1/videos/generations", bytes.NewReader(body))
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("APIPOD_API_KEY"))
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println(resp.Status)
}use reqwest::Client;
use serde_json::json;
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let payload = json!({
"model": "muse-video-i2v",
"prompt": "A corgi surfing at sunset, cinematic, slow motion",
"first_frame_image": "https://cdn.example.com/first-frame.jpg",
"duration": 10,
"aspect_ratio": "16:9",
"style_preset": "cinematic_realistic",
"generate_audio": true
});
let response = Client::new()
.post("https://api.apipod.ai/v1/videos/generations")
.bearer_auth(env::var("APIPOD_API_KEY")?)
.json(&payload)
.send()
.await?
.error_for_status()?;
println!("{}", response.text().await?);
Ok(())
}const response = await fetch("https://api.apipod.ai/v1/videos/generations", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.APIPOD_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify(
{
"model": "muse-video-i2v",
"prompt": "A corgi surfing at sunset, cinematic, slow motion",
"first_frame_image": "https://cdn.example.com/first-frame.jpg",
"first_frame_image": "https://cdn.example.com/first-frame.jpg",
"duration": 10,
"aspect_ratio": "16:9",
"style_preset": "cinematic_realistic",
"generate_audio": true
}
),
});
if (!response.ok) {
throw new Error(`APIPod request failed: ${response.status} ${await response.text()}`);
}
console.log(await response.json());{
"code": 200,
"message": "success",
"data": {
"task_id": "vid_task_01JEXAMPLE"
}
}MU Video
Muse Video Image to Video
Muse Video Image to Video animates a required first frame, with an optional last frame for first-to-last keyframe control, producing 5-60 second 720p clips with native audio.
POST
https://api.apipod.ai
/
v1
/
videos
/
generations
cURL
curl https://api.apipod.ai/v1/videos/generations \
-H "Authorization: Bearer $APIPOD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "muse-video-i2v",
"prompt": "A corgi surfing at sunset, cinematic, slow motion",
"first_frame_image": "https://cdn.example.com/first-frame.jpg",
"duration": 10,
"aspect_ratio": "16:9",
"style_preset": "cinematic_realistic",
"generate_audio": true
}'import os
import requests
payload = {
"model": "muse-video-i2v",
"prompt": "A corgi surfing at sunset, cinematic, slow motion",
"first_frame_image": "https://cdn.example.com/first-frame.jpg",
"duration": 10,
"aspect_ratio": "16:9",
"style_preset": "cinematic_realistic",
"generate_audio": True
}
response = requests.post(
"https://api.apipod.ai/v1/videos/generations",
headers={
"Authorization": f"Bearer {os.environ['APIPOD_API_KEY']}",
"Content-Type": "application/json",
},
json=payload,
timeout=60,
)
response.raise_for_status()
print(response.json())package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
)
func main() {
payload := map[string]any{}
if err := json.Unmarshal([]byte(`{
"model": "muse-video-i2v",
"prompt": "A corgi surfing at sunset, cinematic, slow motion",
"first_frame_image": "https://cdn.example.com/first-frame.jpg",
"duration": 10,
"aspect_ratio": "16:9",
"style_preset": "cinematic_realistic",
"generate_audio": true
}`), &payload); err != nil {
panic(err)
}
body, err := json.Marshal(payload)
if err != nil {
panic(err)
}
req, err := http.NewRequest(http.MethodPost, "https://api.apipod.ai/v1/videos/generations", bytes.NewReader(body))
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("APIPOD_API_KEY"))
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println(resp.Status)
}use reqwest::Client;
use serde_json::json;
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let payload = json!({
"model": "muse-video-i2v",
"prompt": "A corgi surfing at sunset, cinematic, slow motion",
"first_frame_image": "https://cdn.example.com/first-frame.jpg",
"duration": 10,
"aspect_ratio": "16:9",
"style_preset": "cinematic_realistic",
"generate_audio": true
});
let response = Client::new()
.post("https://api.apipod.ai/v1/videos/generations")
.bearer_auth(env::var("APIPOD_API_KEY")?)
.json(&payload)
.send()
.await?
.error_for_status()?;
println!("{}", response.text().await?);
Ok(())
}const response = await fetch("https://api.apipod.ai/v1/videos/generations", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.APIPOD_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify(
{
"model": "muse-video-i2v",
"prompt": "A corgi surfing at sunset, cinematic, slow motion",
"first_frame_image": "https://cdn.example.com/first-frame.jpg",
"first_frame_image": "https://cdn.example.com/first-frame.jpg",
"duration": 10,
"aspect_ratio": "16:9",
"style_preset": "cinematic_realistic",
"generate_audio": true
}
),
});
if (!response.ok) {
throw new Error(`APIPod request failed: ${response.status} ${await response.text()}`);
}
console.log(await response.json());{
"code": 200,
"message": "success",
"data": {
"task_id": "vid_task_01JEXAMPLE"
}
}muse-video-i2v animates a still image. Pass one image and it becomes the first frame; pass a second image and Muse Video interpolates a shot from the first frame to that last frame, giving you exact control over where the motion begins and ends.
Model at a glance
| Public model ID | muse-video-i2v |
| Input | text + image (1-2) |
| Output | video with audio |
| Duration | 5, 10, 20, 30, 40, 50 or 60 seconds (default 5) |
| Resolution | 720p |
| Aspect ratio | 16:9, 9:16, 1:1, 4:3, 3:4 (default 16:9) |
| Billing | per second of output |
Parameters
| Parameter | Type | Default | Notes |
|---|---|---|---|
prompt | string | — | Required, up to 4000 characters. Describe the motion, not the still. |
first_frame_image | string | — | Required. Public URL of the first frame. |
image_urls | string[] | — | Optional. Pass a second URL to use it as the last frame. |
duration | integer | 5 | Must be one of 5, 10, 20, 30, 40, 50, 60. |
aspect_ratio | string | 16:9 | Output framing. It does not have to match the source image. |
resolution | string | 720p | 720p is the only supported tier. |
style_preset | string | none | Same seven presets as text-to-video. |
generate_audio | boolean | true | Set false to mute voices. |
reference_images are rejected here — that alias belongs to muse-video-r2v, which treats every image as a subject reference rather than a frame.
First frame only vs. first and last
| You send | Upstream mode | What you get |
|---|---|---|
| 1 image | first-frame | Motion continues naturally from the still. |
| 2 images | first-last | A controlled transition from the first image to the second. |
Camera pushes slowly through drifting fog toward the lighthouse,
the beam sweeping across frame, cool blue hour light
Workflow
POST /v1/videos/generationswithfirst_frame_image(and optionally a second entry inimage_urls).- Read
data.task_id. - Poll
GET /v1/videos/status/{task_id}untilcompleted. - Download from
data.result.
curl https://api.apipod.ai/v1/videos/generations \
-H "Authorization: Bearer $APIPOD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "muse-video-i2v",
"prompt": "Camera pushes slowly through drifting fog toward the lighthouse",
"first_frame_image": "https://cdn.example.com/lighthouse.jpg",
"duration": 5,
"aspect_ratio": "16:9"
}'
Image requirements
- Use plain, public HTTPS URLs. Signed links that expire, hotlink-protected hosts, and URLs that require a login all fail at submission.
- Portrait, product and landscape photos all work; keep the subject unobstructed in the first frame.
- For real-person portraits, prefer wide, well-lit shots — extreme close-ups give the model very little to animate.
Cost
Billing is per output second and, unlike reference-to-video, the frames you supply do not add to the bill:duration × per-second price.Authorizations
Use your APIPod API key as a Bearer token in the Authorization header.
Body
application/json
Public APIPod model ID.
Allowed value:
"muse-video-i2v"Describe the video to generate. Required, up to 4000 characters.
Required string length:
1 - 4000Required. Public URL of the first frame image. Pass a second URL in image_urls (up to two) to use it as the last frame.
Video duration in seconds.
Available options:
5, 10, 20, 30, 40, 50, 60 Aspect ratio of the generated video.
Available options:
16:9, 9:16, 1:1, 4:3, 3:4 Output resolution. MU Video currently supports 720p only.
Available options:
720p Visual style preset applied to the video.
Available options:
none, cinematic_realistic, 2d_anime, 3d_xianxia, american_comic, cyberpunk_neon, ecommerce_ugc Whether to generate voice and sound. Set to false to mute voices.
Was this page helpful?