SilkDock
APIVideo Generation

Video Generation

Generate videos from text, images, and supported reference assets.

Video generation is asynchronous. Create a task, poll its status, and download content only after the task is completed.

  • Create: POST /v1/videos/generations
  • Status: GET /v1/videos/{video_id}
  • Content: GET /v1/videos/{video_id}/content (video/mp4)
  • Edit: POST /v1/videos/edits; the legacy Remix endpoint is deprecated

Supported model families

Model familyPublic model IDsInput modesAudioMultimodal referenceStart/end frames
Seedanceseedance-2.0, seedance-2.0-fastt2v, i2v, r2vAudio input and generated audioYesYes
Wanwan-2.5, wan-2.6, wan-2.6-flash, wan-2.7, wan-3.0t2v, i2v, r2vAudio input and generated audioModel-dependentModel-dependent
Klingkling-3.0, kling-2.6, kling-2.5-turbot2v, i2v, motionGenerated audio on supported modelsModel-dependentModel-dependent
Hailuohailuo-2.3, hailuo-2.3-fastt2v, i2vNoNoNo
Veoveo-3.1, veo-3.1-fastt2vGenerated audioNoNo
Sorasora-2, sora-2-prot2v, i2v, editSynchronized generated audioNoNo
Runwaygen4_turboi2vNoNoNo

Create a video task

Endpoint: POST /v1/videos/generations

curl -X POST 'https://silkdock.ai/v1/videos/generations' \
  -H 'Authorization: Bearer $SILKDOCK_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "model": "seedance-2.0",
    "prompt": "Ocean waves strike a lighthouse as the camera slowly pushes in",
    "seconds": 10,
    "extra_body": {
      "resolution": "1080p",
      "aspect_ratio": "16:9"
    }
  }'

Request parameters

ParameterTypeRequiredDescription
modelstringYesPublic model ID.
promptstringYesVideo description or transformation instruction.
input_referencestring | string[] | fileNoOne input image. Arrays are accepted for backward compatibility, but only the first non-empty item is used.
secondsintegerNoVideo duration in seconds. Use a value supported by the selected model.
sizestringNoLegacy pixel dimensions. Prefer extra_body.resolution and extra_body.aspect_ratio.
userstringNoEnd-user identifier supplied by the caller.
extra_bodyobjectNoModel-specific extension fields listed below.

extra_body fields

FieldTypeDescription
resolutionstring480p, 720p, 1080p, or 4k, as supported by the model.
aspect_ratiostring16:9, 9:16, 1:1, 4:3, 3:4, or 21:9, as supported by the model.
audio_urlstringExternal reference audio URL.
generate_audiobooleanGenerate audio on the server.
video_urlstringSeedance reference video for r2v mode.
first_frame_url / first_imagestringExplicit first-frame URL.
last_frame_url / last_imagestringExplicit last-frame URL.
reference_image_urlsstring[]Multimodal reference-image URLs.
reference_video_urlsstring[]Multimodal reference-video URLs.
reference_audio_urlsstring[]Multimodal reference-audio URLs.
motion_ref_url / motion_ref_urlsstring | string[]Motion-reference video URL or URLs.
motion_modestringKling supports std and pro; Seedance ignores this field.
motion_strengthnumberMotion-transfer strength. Use only when the model-specific contract declares allowed values.
character_orientationstringKling character orientation: image or video.
keep_original_soundbooleanWhether Kling motion keeps the reference video's original sound.
camera_controlobjectKling motion camera control.
element_listarrayKling subject-reference or element list.
background_tolerancenumberKling motion background tolerance.
framesintegerSeedance output frame count. When present, duration is not sent as well.
return_last_framebooleanReturn the generated last frame for Seedance.
camera_fixedbooleanFix the camera for Seedance.
seedintegerSeedance random seed.
callback_urlstringSeedance task callback URL.
safety_identifierstringSeedance safety identifier.
service_tierstringSeedance service tier.
execution_expires_afterintegerSeedance task execution expiry.
enhance_promptbooleanVeo prompt enhancement; defaults to true.
prompt_extendbooleanWan 2.5/2.6/2.6 Flash/2.7/3.0 prompt rewriting; defaults to true.
prompt_optimizerbooleanHailuo 2.3/Fast prompt optimization; defaults to true.
fast_pretreatmentbooleanHailuo 2.3/Fast fast preprocessing; defaults to false.
aigc_watermarkbooleanHailuo 2.3/Fast AIGC watermark; defaults to false.
watermarkbooleanSeedance watermark; defaults to false.

Each extension field is converted only when it is a native field declared by the selected model's official API.

think_level, thinking_level, and reasoning_effort are not part of the public image or video contract. Wan 3.0 also does not expose enable_thinking.

Do not send extension fields that are absent from the selected model's model-specific input list.

Reference input selection

GoalInput
Single-image videoinput_reference as a URL or file
Multiple reference images or explicit multimodal image guidanceextra_body.reference_image_urls
General video referenceextra_body.reference_video_urls
Motion transferinput_reference plus extra_body.motion_ref_url
One external audio inputextra_body.audio_url
Multimodal audio guidanceextra_body.reference_audio_urls
First or start/end framesextra_body.first_frame_url and optionally extra_body.last_frame_url

input_reference always represents one input image. An array is accepted only for backward compatibility: the gateway uses the first non-empty item and does not interpret later items as an end frame or multimodal references. A normal input_reference is not automatically converted to first_frame_url.

Discover model capabilities

Query GET /model_group/info?model_group=<MODEL_ID> before presenting model-specific controls.

These fields describe the public model contract, not a union of every underlying provider's capabilities. Only expose controls returned for the selected public model.

Response fieldTypeDescription
supported_resolutionsstring[]Supported resolution tiers.
supported_aspect_ratiosstring[]Supported display ratios; prefer this list when rendering size controls.
max_video_duration_secondsnumberMaximum output duration.
supports_video_audio_inputbooleanWhether reference audio is supported.
supports_video_audio_outputbooleanWhether generated output audio can be controlled.
supports_video_multimodal_referencebooleanWhether multimodal reference assets or native structures such as element_list are supported.
supports_video_start_end_framebooleanWhether explicit start/end-frame generation is supported.
supports_video_motionbooleanWhether motion transfer is supported.
curl 'https://silkdock.ai/model_group/info?model_group=seedance-2.0' \
  -H 'Authorization: Bearer $SILKDOCK_API_KEY'

Task responses

Creating a task returns an opaque ID. Do not parse or construct video IDs; status and content requests do not need the model ID again.

{
  "id": "video_xxxxxx",
  "object": "video",
  "status": "processing",
  "usage": {
    "duration_seconds": 10.0,
    "video_resolution": "1080p",
    "has_audio": false
  }
}

A completed status response may include the download URL:

{
  "id": "video_xxxxxx",
  "status": "completed",
  "url": "https://cdn.example.com/video.mp4"
}

status is processing, completed, or failed. Failed tasks include an error object.

FieldTypeDescription
idstringOpaque video task ID. Do not parse or construct it.
object"video"Object type.
statusstringprocessing, completed, or failed.
created_atinteger | nullCreation timestamp, when available.
errorobject | nullFailure details.
usageobject | nullBilling inputs such as duration, resolution, and audio.
urlstring | nullDownload URL after completion, when returned.

Output specifications

ModelResolutionsAspect ratiosseconds
seedance-2.0480p, 720p, 1080p, 4kadaptive, 1:1, 4:3, 3:4, 16:9, 9:16, 21:9Any integer 4-15, or -1 for automatic
seedance-2.0-fast480p, 720padaptive, 1:1, 4:3, 3:4, 16:9, 9:16, 21:9Any integer 4-15, or -1 for automatic
kling-3.0720p, 1080p, 4k1:1, 16:9, 9:16Any integer 1-15
wan-3.0480p, 720p, 1080padaptive, 16:9, 4:3, 1:1, 3:4, 9:16Any integer 2-30, or -1 for automatic
hailuo-2.3, hailuo-2.3-fast720p (officially 768P), 1080pModel default for text; follows the reference image for image mode6 or 10
veo-3.1, veo-3.1-fast720p, 1080p, 4k16:9, 9:164, 6, or 8
sora-2, sora-2-pro720p, 1024p, 1080p on Pro16:9, 9:164, 8, 12, 16, or 20
gen4_turbo720p16:9, 9:16, 4:3, 3:4, 1:1, 21:9Any integer 2-10

A range such as 4-15 accepts every integer within the range. A comma-separated list accepts only those exact values.

Legacy size mapping

sizeresolutionaspect_ratio
1920x10801080p16:9
1080x19201080p9:16
1280x720720p16:9
720x1280720p9:16
1080x10801080p1:1
720x720720p1:1
1440x10801080p4:3
960x720720p4:3
1080x14401080p3:4
720x960720p3:4
2520x10801080p21:9
1680x720720p21:9
3840x21604k16:9
2160x38404k9:16

Seedance metering

Seedance reserves an estimated amount when the task is created using (input video seconds + output seconds) x width x height x 24 / 1024 x USD/token. A normal image-to-video request has no video input. Requests containing a reference video, motion video, or video edit use the video-input tier. Because input-video duration is not known at creation time, the estimate uses a four-second minimum; when the provider returns total_tokens, the gateway settles the difference against actual usage.

ModelOutput resolutionNo video input (USD/M tokens)With video input (USD/M tokens)
seedance-2.0480p, 720p$7.00$4.30
seedance-2.01080p$7.70$4.70
seedance-2.04K$4.00$2.40
seedance-2.0-fast480p, 720p$5.60$3.30

Metering uses the official international list price and does not follow temporary promotional discounts.

Image-to-video example

{
  "model": "wan-2.7",
  "prompt": "The subject turns and runs forward as the camera pulls back smoothly",
  "input_reference": "https://example.com/first-frame.png",
  "seconds": 10,
  "extra_body": {
    "resolution": "1080p",
    "aspect_ratio": "16:9"
  }
}

Start/end-frame example

{
  "model": "seedance-2.0",
  "prompt": "Push slowly toward the subject and end on a night skyline",
  "seconds": 6,
  "extra_body": {
    "resolution": "1080p",
    "aspect_ratio": "16:9",
    "first_frame_url": "https://example.com/first.png",
    "last_frame_url": "https://example.com/last.png"
  }
}

Normal input_reference values remain reference images and do not automatically become first_frame_url. Check supports_video_start_end_frame before exposing this mode.

Motion-reference examples

Kling uses input_reference for the character or source image and motion_ref_url for the motion video:

{
  "model": "kling-3.0",
  "prompt": "Keep the character's appearance and transfer the dance motion",
  "input_reference": "https://example.com/character.png",
  "seconds": 5,
  "extra_body": {
    "motion_ref_url": "https://example.com/motion.mp4",
    "motion_mode": "std",
    "character_orientation": "image",
    "keep_original_sound": false
  }
}

Seedance accepts the same public motion inputs. motion_mode is ignored for Seedance:

{
  "model": "seedance-2.0",
  "prompt": "Keep the subject and follow the walking rhythm and camera movement",
  "input_reference": "https://example.com/character.png",
  "seconds": 8,
  "extra_body": {
    "motion_ref_url": "https://example.com/motion.mp4",
    "resolution": "720p",
    "aspect_ratio": "16:9"
  }
}

Audio example

{
  "model": "seedance-2.0",
  "prompt": "A dancer spins in time with the beat",
  "seconds": 10,
  "extra_body": {
    "resolution": "720p",
    "aspect_ratio": "1:1",
    "audio_url": "https://example.com/music.mp3"
  }
}

Code examples

curl -X POST 'https://silkdock.ai/v1/videos/generations' \
  -H 'Authorization: Bearer sk-xxx' \
  -H 'Content-Type: application/json' \
  -d '{"model":"seedance-2.0","prompt":"Ocean waves strike a lighthouse","seconds":10,"extra_body":{"resolution":"1080p","aspect_ratio":"16:9"}}'

curl 'https://silkdock.ai/v1/videos/video_xxx' \
  -H 'Authorization: Bearer sk-xxx'

curl -L 'https://silkdock.ai/v1/videos/video_xxx/content' \
  -H 'Authorization: Bearer sk-xxx' --output out.mp4
const headers = { Authorization: "Bearer sk-xxx", "Content-Type": "application/json" };
const response = await fetch("https://silkdock.ai/v1/videos/generations", {
  method: "POST",
  headers,
  body: JSON.stringify({
    model: "seedance-2.0",
    prompt: "Ocean waves strike a lighthouse",
    seconds: 10,
    extra_body: { resolution: "1080p", aspect_ratio: "16:9" },
  }),
});
console.log(await response.json());
import OpenAI from "openai";

const client = new OpenAI({ apiKey: "sk-xxx", baseURL: "https://silkdock.ai/v1" });
const video = await client.videos.create({
  model: "seedance-2.0",
  prompt: "Ocean waves strike a lighthouse",
  seconds: 10,
  extra_body: { resolution: "1080p", aspect_ratio: "16:9" },
});
let status = video;
while (status.status === "processing") {
  await new Promise((resolve) => setTimeout(resolve, 5000));
  status = await client.videos.retrieve(video.id);
}
from openai import OpenAI
import time

client = OpenAI(api_key="sk-xxx", base_url="https://silkdock.ai/v1")
video = client.videos.create(
    model="seedance-2.0",
    prompt="Ocean waves strike a lighthouse",
    seconds=10,
    extra_body={"resolution": "1080p", "aspect_ratio": "16:9"},
)
while True:
    status = client.videos.retrieve(video.id)
    if status.status == "completed": break
    if status.status == "failed": raise RuntimeError(status.error)
    time.sleep(5)
content = client.videos.retrieve_content(video.id)
with open("out.mp4", "wb") as output:
    output.write(content.read())
#include <curl/curl.h>

int main(void) {
  CURL *curl = curl_easy_init();
  struct curl_slist *headers = NULL;
  headers = curl_slist_append(headers, "Authorization: Bearer sk-xxx");
  headers = curl_slist_append(headers, "Content-Type: application/json");
  curl_easy_setopt(curl, CURLOPT_URL, "https://silkdock.ai/v1/videos/generations");
  curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
  curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "{\"model\":\"seedance-2.0\",\"prompt\":\"Ocean waves strike a lighthouse\",\"seconds\":10,\"extra_body\":{\"resolution\":\"1080p\",\"aspect_ratio\":\"16:9\"}}");
  curl_easy_perform(curl);
  curl_easy_cleanup(curl);
}
NSURL *url = [NSURL URLWithString:@"https://silkdock.ai/v1/videos/generations"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST";
[request setValue:@"Bearer sk-xxx" forHTTPHeaderField:@"Authorization"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
NSDictionary *payload = @{ @"model": @"seedance-2.0", @"prompt": @"Ocean waves strike a lighthouse", @"seconds": @10, @"extra_body": @{ @"resolution": @"1080p", @"aspect_ratio": @"16:9" } };
request.HTTPBody = [NSJSONSerialization dataWithJSONObject:payload options:0 error:nil];
[[[NSURLSession sharedSession] dataTaskWithRequest:request] resume];
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://silkdock.ai/v1/videos/generations"))
    .header("Authorization", "Bearer sk-xxx")
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString("{\"model\":\"seedance-2.0\",\"prompt\":\"Ocean waves strike a lighthouse\",\"seconds\":10,\"extra_body\":{\"resolution\":\"1080p\",\"aspect_ratio\":\"16:9\"}}"))
    .build();
System.out.println(HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString()).body());
payload := strings.NewReader(`{"model":"seedance-2.0","prompt":"Ocean waves strike a lighthouse","seconds":10,"extra_body":{"resolution":"1080p","aspect_ratio":"16:9"}}`)
req, _ := http.NewRequest("POST", "https://silkdock.ai/v1/videos/generations", payload)
req.Header.Set("Authorization", "Bearer sk-xxx")
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
<?php
$ch = curl_init('https://silkdock.ai/v1/videos/generations');
curl_setopt_array($ch, [CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ['Authorization: Bearer sk-xxx', 'Content-Type: application/json'],
  CURLOPT_POSTFIELDS => json_encode(['model' => 'seedance-2.0', 'prompt' => 'Ocean waves strike a lighthouse', 'seconds' => 10, 'extra_body' => ['resolution' => '1080p', 'aspect_ratio' => '16:9']])]);
echo curl_exec($ch);
curl_close($ch);
var request = URLRequest(url: URL(string: "https://silkdock.ai/v1/videos/generations")!)
request.httpMethod = "POST"
request.setValue("Bearer sk-xxx", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let payload: [String: Any] = ["model": "seedance-2.0", "prompt": "Ocean waves strike a lighthouse", "seconds": 10, "extra_body": ["resolution": "1080p", "aspect_ratio": "16:9"]]
request.httpBody = try! JSONSerialization.data(withJSONObject: payload)
URLSession.shared.dataTask(with: request) { data, _, _ in print(String(data: data!, encoding: .utf8)!) }.resume()
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer sk-xxx");
var json = JsonSerializer.Serialize(new { model = "seedance-2.0", prompt = "Ocean waves strike a lighthouse", seconds = 10, extra_body = new { resolution = "1080p", aspect_ratio = "16:9" } });
var response = await client.PostAsync("https://silkdock.ai/v1/videos/generations", new StringContent(json, Encoding.UTF8, "application/json"));
Console.WriteLine(await response.Content.ReadAsStringAsync());
uri = URI("https://silkdock.ai/v1/videos/generations")
request = Net::HTTP::Post.new(uri, { "Authorization" => "Bearer sk-xxx", "Content-Type" => "application/json" })
request.body = { model: "seedance-2.0", prompt: "Ocean waves strike a lighthouse", seconds: 10, extra_body: { resolution: "1080p", aspect_ratio: "16:9" } }.to_json
puts Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(request) }.body
val json = """{"model":"seedance-2.0","prompt":"Ocean waves strike a lighthouse","seconds":10,"extra_body":{"resolution":"1080p","aspect_ratio":"16:9"}}"""
val request = Request.Builder().url("https://silkdock.ai/v1/videos/generations")
    .header("Authorization", "Bearer sk-xxx")
    .post(json.toRequestBody("application/json".toMediaType())).build()
OkHttpClient().newCall(request).execute().use { println(it.body?.string()) }
let response = reqwest::Client::new()
    .post("https://silkdock.ai/v1/videos/generations")
    .bearer_auth("sk-xxx")
    .json(&serde_json::json!({"model":"seedance-2.0","prompt":"Ocean waves strike a lighthouse","seconds":10,"extra_body":{"resolution":"1080p","aspect_ratio":"16:9"}}))
    .send().await?;
println!("{}", response.text().await?);
POST /v1/videos/generations HTTP/1.1
Host: silkdock.ai
Authorization: Bearer sk-xxx
Content-Type: application/json

{"model":"seedance-2.0","prompt":"Ocean waves strike a lighthouse","seconds":10,"extra_body":{"resolution":"1080p","aspect_ratio":"16:9"}}
final response = await http.post(
  Uri.parse('https://silkdock.ai/v1/videos/generations'),
  headers: {'Authorization': 'Bearer sk-xxx', 'Content-Type': 'application/json'},
  body: jsonEncode({'model': 'seedance-2.0', 'prompt': 'Ocean waves strike a lighthouse', 'seconds': 10, 'extra_body': {'resolution': '1080p', 'aspect_ratio': '16:9'}}),
);
print(response.body);
response <- request("https://silkdock.ai/v1/videos/generations") |>
  req_headers(Authorization = "Bearer sk-xxx") |>
  req_body_json(list(model = "seedance-2.0", prompt = "Ocean waves strike a lighthouse", seconds = 10, extra_body = list(resolution = "1080p", aspect_ratio = "16:9"))) |>
  req_perform()
resp_body_json(response)
let body = {|{"model":"seedance-2.0","prompt":"Ocean waves strike a lighthouse","seconds":10,"extra_body":{"resolution":"1080p","aspect_ratio":"16:9"}}|} in
let headers = Cohttp.Header.of_list [
  ("Authorization", "Bearer sk-xxx"); ("Content-Type", "application/json")
] in
Lwt_main.run (Cohttp_lwt_unix.Client.post ~headers ~body:(Cohttp_lwt.Body.of_string body)
  (Uri.of_string "https://silkdock.ai/v1/videos/generations"))

Check and download a task

  • Status: GET /v1/videos/{video_id}
  • Content: GET /v1/videos/{video_id}/content

The task status is processing, completed, or failed. Download the result only after the status is completed. Poll every 3-5 seconds in production and set an application-level timeout.

Errors and billing

ScenarioBehavior
Unsupported input mode400 BadRequestError
Unsupported resolution/aspect-ratio combinationFalls back to the model default and records a warning
Generation failurestatus: "failed" with details in error
Download before completionVideo-not-ready error

Billing depends on the model, duration, resolution, and generated audio. The usage object contains the metering inputs used by the gateway.

Last updated on

On this page