- 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
Request example
curl --request POST \
--url https://api.openveer.com/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.openveer.com/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.openveer.com/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.openveer.com/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.openveer.com/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.openveer.com/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.openveer.com/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.bodyimport Foundation
let url = URL(string: "https://api.openveer.com/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.openveer.com/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);
}
}Response example
{
"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
Authorization stringAll API endpoints require Bearer Token authentication
Get your API Key:
Visit the API Key Management Page to get your API Key
Add to the request header:
Authorization: Bearer YOUR_API_KEYGeneration Modes
SkyReels V4 auto-routes to the correct mode based on request fields — no mode 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
model stringTwo 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.
nsfw_check booleanWhether to run content moderation before submitting the video task.
true: useomni-moderation-latestto review prompts and input imagesfalseor omitted: do not send a moderation request, adding no moderation cost or latency (default)
prompt stringText prompt, max 1280 tokens
Describe 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."
duration integerOutput 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).
resolution stringVideo resolution
Options:
480p720p1080p(default)
aspect_ratio stringAspect ratio
Options:
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.
prompt_optimizer booleanWhether to auto-optimize the prompt
When enabled, the system automatically optimizes your prompt for better generation results.
I2V-Specific Fields
first_frame_image stringFirst frame image URL (jpg / jpeg / png / gif / bmp)
When provided, this image is used as the starting frame of the video.
end_frame_image stringEnd 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_frame_images object[]tag stringMust start with @ and appear in the prompt, e.g., @image1
image_url stringImage URL (jpg / jpeg / png / gif / bmp)
time_stamp integerTimestamp of appearance (seconds). Default -1 (unspecified); when specified, must satisfy 0 < time_stamp < duration.
Omni-Specific Fields
ref_images object[]type). Each element has the following structure:
tag stringMust start with @ and appear in the prompt, e.g., @Actor-1
type stringReference type:
* image - Regular reference image (list length 1~~3; each image_urls length 1~~5)
* grid - Grid collage, i.e., a single image composed of multiple tiles (e.g., 2×2, 3×3); list length must = 1, image_urls must be 1 image
image_urls string[]Array of image URLs
audio_url stringVoice audio URL (only supported when type=image, audio duration ≤ 15 seconds)
ref_videos object[]tag stringMust start with @ and appear in the prompt, e.g., @video1
type stringReference type:
* reference - Motion / subject reference, **overrides duration** (follows the reference video length, max 10 seconds), carries input video audio by default; **can be combined with ref_images.type=image**
* extend - Video extension, billed by the requested duration; **cannot be combined with ref_images**
video_url stringVideo URL (MP4 / MOV, duration ≤ 15 seconds)
Supported Scenarios
The following scenarios are supported by both skyreels-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
code integerResponse status code, 200 on success
data arraystatus stringTask status, submitted when initially submitted
task_id stringUnique task identifier for querying task status and results
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 Results
Video generation is an async task that returns a task_id upon submission. Use the Get Task Status endpoint to query generation progress and results.
This documentation is built and hosted on Mintlify, a developer documentation platform.