curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"model": "skyreels-v4-fast",
"prompt": "A serene forest at sunset with golden light filtering through the trees.",
"duration": 5,
"resolution": "1080p",
"aspect_ratio": "16:9",
"prompt_optimizer": true
}'
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "skyreels-v4-fast",
"prompt": "A serene forest at sunset with golden light filtering through the trees.",
"duration": 5,
"resolution": "1080p",
"aspect_ratio": "16:9",
"prompt_optimizer": True
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "skyreels-v4-fast",
prompt: "A serene forest at sunset with golden light filtering through the trees.",
duration: 5,
resolution: "1080p",
aspect_ratio: "16:9",
prompt_optimizer: true
};
const headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "skyreels-v4-fast",
"prompt": "A serene forest at sunset with golden light filtering through the trees.",
"duration": 5,
"resolution": "1080p",
"aspect_ratio": "16:9",
"prompt_optimizer": true,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer <token>")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/videos/generations";
String payload = """
{
"model": "skyreels-v4-fast",
"prompt": "A serene forest at sunset with golden light filtering through the trees.",
"duration": 5,
"resolution": "1080p",
"aspect_ratio": "16:9",
"prompt_optimizer": true
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
<?php
$url = "https://api.apimart.ai/v1/videos/generations";
$payload = [
"model" => "skyreels-v4-fast",
"prompt" => "A serene forest at sunset with golden light filtering through the trees.",
"duration" => 5,
"resolution" => "1080p",
"aspect_ratio" => "16:9",
"prompt_optimizer" => true
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer <token>",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/videos/generations")
payload = {
model: "skyreels-v4-fast",
prompt: "A serene forest at sunset with golden light filtering through the trees.",
duration: 5,
resolution: "1080p",
aspect_ratio: "16:9",
prompt_optimizer: true
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer <token>"
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/videos/generations")!
let payload: [String: Any] = [
"model": "skyreels-v4-fast",
"prompt": "A serene forest at sunset with golden light filtering through the trees.",
"duration": 5,
"resolution": "1080p",
"aspect_ratio": "16:9",
"prompt_optimizer": true
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer <token>", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/videos/generations";
var payload = @"{
""model"": ""skyreels-v4-fast"",
""prompt"": ""A serene forest at sunset with golden light filtering through the trees."",
""duration"": 5,
""resolution"": ""1080p"",
""aspect_ratio"": ""16:9"",
""prompt_optimizer"": true
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer <token>");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KPEY5H3NQ2W8D7T6VB3F9GR4"
}
]
}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
{
"error": {
"code": 422,
"message": "Parameter conflict or invalid value (e.g. I2V and Omni fields passed simultaneously)",
"type": "invalid_request_error"
}
}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
{
"error": {
"code": 500,
"message": "Internal server error, please retry later",
"type": "server_error"
}
}
SkyReels V4
SkyReels V4 Video Generation
- Two model tiers: Fast (speed-optimized) and Std (quality-optimized)
- Three modes auto-routed by request fields: Text-to-Video (T2V), Image-to-Video (I2V), Multimodal Reference (Omni)
- 480p / 720p / 1080p resolution, 3 ~ 15 seconds duration
- Advanced features: first/end/key frame, reference images, reference videos, grid collage, video extension, audio sync
- Async processing mode, returns a task ID for later query
POST
/
v1
/
videos
/
generations
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"model": "skyreels-v4-fast",
"prompt": "A serene forest at sunset with golden light filtering through the trees.",
"duration": 5,
"resolution": "1080p",
"aspect_ratio": "16:9",
"prompt_optimizer": true
}'
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "skyreels-v4-fast",
"prompt": "A serene forest at sunset with golden light filtering through the trees.",
"duration": 5,
"resolution": "1080p",
"aspect_ratio": "16:9",
"prompt_optimizer": True
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "skyreels-v4-fast",
prompt: "A serene forest at sunset with golden light filtering through the trees.",
duration: 5,
resolution: "1080p",
aspect_ratio: "16:9",
prompt_optimizer: true
};
const headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "skyreels-v4-fast",
"prompt": "A serene forest at sunset with golden light filtering through the trees.",
"duration": 5,
"resolution": "1080p",
"aspect_ratio": "16:9",
"prompt_optimizer": true,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer <token>")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/videos/generations";
String payload = """
{
"model": "skyreels-v4-fast",
"prompt": "A serene forest at sunset with golden light filtering through the trees.",
"duration": 5,
"resolution": "1080p",
"aspect_ratio": "16:9",
"prompt_optimizer": true
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
<?php
$url = "https://api.apimart.ai/v1/videos/generations";
$payload = [
"model" => "skyreels-v4-fast",
"prompt" => "A serene forest at sunset with golden light filtering through the trees.",
"duration" => 5,
"resolution" => "1080p",
"aspect_ratio" => "16:9",
"prompt_optimizer" => true
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer <token>",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/videos/generations")
payload = {
model: "skyreels-v4-fast",
prompt: "A serene forest at sunset with golden light filtering through the trees.",
duration: 5,
resolution: "1080p",
aspect_ratio: "16:9",
prompt_optimizer: true
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer <token>"
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/videos/generations")!
let payload: [String: Any] = [
"model": "skyreels-v4-fast",
"prompt": "A serene forest at sunset with golden light filtering through the trees.",
"duration": 5,
"resolution": "1080p",
"aspect_ratio": "16:9",
"prompt_optimizer": true
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer <token>", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/videos/generations";
var payload = @"{
""model"": ""skyreels-v4-fast"",
""prompt"": ""A serene forest at sunset with golden light filtering through the trees."",
""duration"": 5,
""resolution"": ""1080p"",
""aspect_ratio"": ""16:9"",
""prompt_optimizer"": true
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer <token>");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KPEY5H3NQ2W8D7T6VB3F9GR4"
}
]
}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
{
"error": {
"code": 422,
"message": "Parameter conflict or invalid value (e.g. I2V and Omni fields passed simultaneously)",
"type": "invalid_request_error"
}
}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
{
"error": {
"code": 500,
"message": "Internal server error, please retry later",
"type": "server_error"
}
}
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"model": "skyreels-v4-fast",
"prompt": "A serene forest at sunset with golden light filtering through the trees.",
"duration": 5,
"resolution": "1080p",
"aspect_ratio": "16:9",
"prompt_optimizer": true
}'
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "skyreels-v4-fast",
"prompt": "A serene forest at sunset with golden light filtering through the trees.",
"duration": 5,
"resolution": "1080p",
"aspect_ratio": "16:9",
"prompt_optimizer": True
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "skyreels-v4-fast",
prompt: "A serene forest at sunset with golden light filtering through the trees.",
duration: 5,
resolution: "1080p",
aspect_ratio: "16:9",
prompt_optimizer: true
};
const headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "skyreels-v4-fast",
"prompt": "A serene forest at sunset with golden light filtering through the trees.",
"duration": 5,
"resolution": "1080p",
"aspect_ratio": "16:9",
"prompt_optimizer": true,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer <token>")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/videos/generations";
String payload = """
{
"model": "skyreels-v4-fast",
"prompt": "A serene forest at sunset with golden light filtering through the trees.",
"duration": 5,
"resolution": "1080p",
"aspect_ratio": "16:9",
"prompt_optimizer": true
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
<?php
$url = "https://api.apimart.ai/v1/videos/generations";
$payload = [
"model" => "skyreels-v4-fast",
"prompt" => "A serene forest at sunset with golden light filtering through the trees.",
"duration" => 5,
"resolution" => "1080p",
"aspect_ratio" => "16:9",
"prompt_optimizer" => true
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer <token>",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/videos/generations")
payload = {
model: "skyreels-v4-fast",
prompt: "A serene forest at sunset with golden light filtering through the trees.",
duration: 5,
resolution: "1080p",
aspect_ratio: "16:9",
prompt_optimizer: true
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = "Bearer <token>"
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/videos/generations")!
let payload: [String: Any] = [
"model": "skyreels-v4-fast",
"prompt": "A serene forest at sunset with golden light filtering through the trees.",
"duration": 5,
"resolution": "1080p",
"aspect_ratio": "16:9",
"prompt_optimizer": true
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer <token>", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/videos/generations";
var payload = @"{
""model"": ""skyreels-v4-fast"",
""prompt"": ""A serene forest at sunset with golden light filtering through the trees."",
""duration"": 5,
""resolution"": ""1080p"",
""aspect_ratio"": ""16:9"",
""prompt_optimizer"": true
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer <token>");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01KPEY5H3NQ2W8D7T6VB3F9GR4"
}
]
}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
{
"error": {
"code": 422,
"message": "Parameter conflict or invalid value (e.g. I2V and Omni fields passed simultaneously)",
"type": "invalid_request_error"
}
}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
{
"error": {
"code": 500,
"message": "Internal server error, please retry later",
"type": "server_error"
}
}
Authorization
All API endpoints require Bearer Token authenticationGet your API Key:Visit the API Key Management Page to get your API KeyAdd to the request header:
Authorization: Bearer YOUR_API_KEY
Generation Modes
SkyReels V4 auto-routes to the correct mode based on request fields — nomode field needed:
| Mode | Trigger | Capability |
|---|---|---|
| T2V (Text-to-Video) | Only prompt + general fields | Pure text-driven generation |
| I2V (Image-to-Video) | Any of first_frame_image / end_frame_image / mid_frame_images | First/end/key frame control |
| Omni (Multimodal Reference) | Any of ref_images / ref_videos | Subject reference, grid collage, motion reference, video extension, audio sync |
Strict mutual exclusion: I2V fields (
first_frame_image / end_frame_image / mid_frame_images) and Omni fields (ref_images / ref_videos) cannot be used together, otherwise returns 422.@tag mechanism: When using mid_frame_images / ref_images / ref_videos, each element must declare a tag starting with @ (e.g., @image1, @Actor-1, @video1), and the tag must appear in the prompt.Think of prompt as the “script” and tag as a “character pointer” to specific assets (images / videos). For example, a prompt like "@Actor-1 walks into the scene of @video1" instructs the system to inject the reference image subject tied to @Actor-1 and the motion reference tied to @video1 into the generation process.Request Parameters
General Fields
Two model tiers are available:
| Model | Positioning | Use Cases |
|---|---|---|
skyreels-v4-fast | Speed-first | Quick previews, batch generation, daily content |
skyreels-v4-std | Quality-first (25~30% higher price than Fast) | Key shots, high-detail requirements, formal delivery |
The
model field must be explicitly provided — no default value.Pricing is strongly tied to resolution and whether
ref_videos is used: 1080p is significantly more expensive than 480p / 720p; tiers with ref_videos (video input) cost ~1.5 ~ 2× compared to those without. Simultaneous audio and video output is not yet supported.Text prompt, max 1280 tokensDescribe scenes, subjects, actions, styles in detail for better generation results.When using
ref_images / ref_videos / mid_frame_images, the prompt must contain the corresponding @tag (e.g., @Actor-1, @video1, @image1).Example: "@Actor-1 walks through a neon-lit street at night."Output video duration (seconds)
- Range:
[3, 15] - Default:
5
When
ref_videos.type=reference is provided, duration is overridden by the reference video length (max 10 seconds).Video resolutionOptions:
480p720p1080p(default)
Aspect ratioOptions:
16:9(default)4:31:19:163:4
aspect_ratio is ignored in I2V mode (output ratio is determined by the input image); also ignored when Omni is combined with ref_videos.Whether to auto-optimize the promptWhen enabled, the system automatically optimizes your prompt for better generation results.
I2V-Specific Fields
First frame image URL (jpg / jpeg / png / gif / bmp)When provided, this image is used as the starting frame of the video.
End frame image URL (jpg / jpeg / png / gif / bmp)When provided, this image is used as the ending frame of the video. Can be combined with
first_frame_image for first-and-last-frame control.Mid keyframe list, up to 6. Each element has the following structure:
Show mid_frame_images element
Show mid_frame_images element
Omni-Specific Fields
Reference image list (all elements must share the same
type). Each element has the following structure:Show ref_images element
Show ref_images element
Must start with
@ and appear in the prompt, e.g., @Actor-1Reference type:
image- Regular reference image (list length 13; each5)image_urlslength 1grid- Grid collage, i.e., a single image composed of multiple tiles (e.g., 2×2, 3×3); list length must = 1,image_urlsmust be 1 image
Array of image URLs
Voice audio URL (only supported when
type=image, audio duration ≤ 15 seconds)Reference video list, up to 1. Each element has the following structure:
Show ref_videos element
Show ref_videos element
Must start with
@ and appear in the prompt, e.g., @video1Reference type:
reference- Motion / subject reference, overridesduration(follows the reference video length, max 10 seconds), carries input video audio by default; can be combined withref_images.type=imageextend- Video extension, billed by the requestedduration; cannot be combined withref_images
Video URL (MP4 / MOV, duration ≤ 15 seconds)
Supported Scenarios
The following scenarios are supported by bothskyreels-v4-fast and skyreels-v4-std:
| Scenario | Mode | Required Fields | Typical Use Case |
|---|---|---|---|
| Text-to-Video | T2V | prompt | Pure text-driven, rapid concept shots |
| Image-to-Video - First Frame | I2V | first_frame_image | Still-to-video with a specified starting frame |
| Image-to-Video - End Frame | I2V | end_frame_image | Specifies the closing frame |
| Image-to-Video - Keyframes | I2V | mid_frame_images (1 ~ 6) | First + end + mid keyframes for precise pacing |
| Omni Single/Multi-Subject | Omni | ref_images (type=image) | Character consistency, multi-subject framing |
| Omni Grid Collage | Omni | ref_images (type=grid, 1 image) | Step-by-step process videos (tutorials, recipes, demos) |
| Omni Motion Reference | Omni | ref_videos (type=reference) | Replicate the motion, subject, or style of a reference video |
| Omni Video Extension | Omni | ref_videos (type=extend) | Continue an existing video with new content |
| Omni Audio Sync | Omni | ref_images (type=image) + audio_url | Digital human narration, audio-driven lip-sync |
Parameter Constraints
Violating any of the following will cause the request to be rejected with a 422 response, no billing occurs:| Parameter | Constraint |
|---|---|
prompt | Max 1280 tokens |
duration | [3, 15] seconds; overridden by reference video length (max 10s) when ref_videos.type=reference |
resolution | Only 480p / 720p / 1080p |
aspect_ratio | 16:9 / 4:3 / 1:1 / 9:16 / 3:4; ignored in I2V; ignored when Omni carries ref_videos |
mid_frame_images | Up to 6; time_stamp must be -1 or within (0, duration) |
ref_images overall | All elements must share the same type; cannot coexist with I2V fields |
ref_images.type=grid | List length must = 1; image_urls must be 1 image |
ref_images.type=image | List length 1 ~ 3; each image_urls length 1 ~ 5 |
ref_images.audio_url | Only supported when type=image, audio ≤ 15 seconds |
ref_videos | Up to 1; video_url MP4 / MOV, ≤ 15 seconds |
ref_videos.type=reference | Overrides requested duration (max 10s), can combine with ref_images.type=image, carries input video audio by default |
ref_videos.type=extend | Billed by requested duration; cannot combine with ref_images |
tag field | Must start with @ and appear in the prompt |
| I2V / Omni exclusion | I2V fields and Omni fields cannot be used together |
Response
Response status code, 200 on success
Request Examples
Case 1: Text-to-Video (Minimal)
{
"model": "skyreels-v4-fast",
"prompt": "A serene forest at sunset with golden light filtering through the trees."
}
Case 2: Text-to-Video (Full Parameters)
{
"model": "skyreels-v4-std",
"prompt": "A serene forest at sunset.",
"duration": 5,
"resolution": "720p",
"aspect_ratio": "16:9",
"prompt_optimizer": true
}
Case 3: Image-to-Video - First Frame
{
"model": "skyreels-v4-fast",
"prompt": "Slowly pull the camera back to reveal the entire scene.",
"first_frame_image": "https://example.com/start.png",
"duration": 5
}
Case 4: Image-to-Video - First/End Frame + Mid Keyframes
{
"model": "skyreels-v4-std",
"prompt": "The King summons a flying dragon. @image1 The dragon lowers. The King mounts and flies away.",
"duration": 8,
"resolution": "1080p",
"first_frame_image": "https://example.com/k2v_0.png",
"end_frame_image": "https://example.com/k2v_2.png",
"mid_frame_images": [
{ "tag": "@image1", "image_url": "https://example.com/k2v_1.png", "time_stamp": 3 }
]
}
Case 5: Omni - Single Subject Reference
{
"model": "skyreels-v4-fast",
"prompt": "@Actor-1 walks through a neon-lit street at night.",
"ref_images": [
{ "tag": "@Actor-1", "type": "image", "image_urls": ["https://example.com/actor.jpg"] }
]
}
Case 6: Omni - Multi-Subject + Video Motion Reference
{
"model": "skyreels-v4-fast",
"prompt": "The man from @image_1 imitates the move on the left in @video_1. The woman from @image_2 imitates the right side.",
"duration": 5,
"ref_images": [
{ "tag": "@image_1", "type": "image", "image_urls": ["https://example.com/a.png"] },
{ "tag": "@image_2", "type": "image", "image_urls": ["https://example.com/b.png"] }
],
"ref_videos": [
{ "tag": "@video_1", "type": "reference", "video_url": "https://example.com/motion.mp4" }
]
}
This case uses
ref_videos.type=reference, so the requested duration will be overridden by the actual reference video length (max 10 seconds). Even though "duration": 5 is passed here, the final video length follows the reference video.Case 7: Omni - Grid Collage
{
"model": "skyreels-v4-fast",
"prompt": "Create a video showing how to make tomato and egg noodles based on @image1.",
"ref_images": [
{ "tag": "@image1", "type": "grid", "image_urls": ["https://example.com/recipe_grid.png"] }
]
}
Case 8: Omni - Video Extension (extend)
{
"model": "skyreels-v4-fast",
"prompt": "Video extended @video1, someone walks over and sits on the sofa.",
"duration": 8,
"ref_videos": [
{ "tag": "@video1", "type": "extend", "video_url": "https://example.com/source.mp4" }
]
}
Case 9: Omni - Audio Sync (Voice-Driven)
{
"model": "skyreels-v4-std",
"prompt": "@Actor-1 speaks with a calm tone.",
"ref_images": [
{
"tag": "@Actor-1",
"type": "image",
"image_urls": ["https://example.com/actor.jpg"],
"audio_url": "https://example.com/voice.mp3"
}
]
}
Query Task ResultsVideo generation is an async task that returns a
task_id upon submission. Use the Get Task Status endpoint to query generation progress and results.⌘I