SeaLinkSeaLink
/
← Docs

Video

Video models usually run as asynchronous tasks and may bill by seconds, resolution, or clip. Start with duration=5 or shorter, n=1, and a base resolution to verify model choice, parameters, and callback handling.

POST /v1/video/generations

Async video generation. Submit a prompt to receive a task ID, then poll task status for the final video. Use /v1/models and the model detail page for text-to-video, image-to-video, reference-image, or editing parameters.

Image-to-video, keyframe, and video-edit routes are most reliable with data:image/...;base64,... image inputs. Plain image or video URLs must be directly downloadable by the execution provider; avoid signed-in, blocked, very small, or private resources.

Use /v1/models model details as the source of truth; supported input modes, resolutions, and durations can differ by video model.

Parameters

ParameterTypeRequiredDescription
modelstringYesChoose a video generation model from /v1/models
promptstringYes*Video description; can be generated from an existing prompt template via template_id
template_idstringNoExisting prompt template ID, use with variables; unknown templates return 404
variablesobjectNoPrompt template variables; values must be strings
image / image_urlstringNoStarting frame as base64 or URL
nintegerNo1 - 4
sizestringNo832x480, 480x832, 624x624, 1280x720, 720x1280, 960x960, 1088x832, 832x1088, 1920x1080, 1080x1920, 1440x1440, 1632x1248, 1248x1632
durationintegerNo1 - 60 seconds; use 5 seconds or shorter for first probes
fpsintegerNo1 - 60
negative_promptstringNoNegative prompt, max 1024 chars
seedintegerNoRandom seed for reproducible generation
webhook_urlstringNoCallback URL on completion (https only)
tagsarrayNoArray of tag strings
cURL
curl https://test.sealink.io/v1/video/generations \
-H "Authorization: Bearer $SEALINK_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "kling-v3-omni",
"prompt": "A serene lake at sunset, camera slowly panning across the water",
"size": "1280x720",
"duration": 5,
"n": 1
}'
Python
import os
from openai import OpenAI
import requests
# For async video generation, use the raw HTTP client
res = requests.post(
"https://test.sealink.io/v1/video/generations",
headers={"Authorization": f"Bearer {os.environ['SEALINK_API_KEY']}"},
json={
"model": "kling-v3-omni",
"prompt": "A serene lake at sunset, camera slowly panning across the water",
"size": "1280x720",
"duration": 5,
"n": 1,
},
)
task = res.json()
print(f"Task ID: {task['id']}")
cURL - Image-to-video
IMG_B64="$(base64 -w0 first-frame.png)"
curl https://test.sealink.io/v1/video/generations \
-H "Authorization: Bearer $SEALINK_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "<image-to-video-model-from-/v1/models>",
"prompt": "A tiny product photo turning slowly on a clean table",
"image_url": "data:image/png;base64,'"$IMG_B64"'",
"size": "832x480",
"duration": 5,
"n": 1
}'
Python - Image-to-video
import os
import requests
res = requests.post(
"https://test.sealink.io/v1/video/generations",
headers={"Authorization": f"Bearer {os.environ['SEALINK_API_KEY']}"},
json={
"model": "<image-to-video-model-from-/v1/models>",
"prompt": "A tiny product photo turning slowly on a clean table",
"image_url": "https://raw.githubusercontent.com/mathiasbynens/small/master/jpeg.jpg",
"size": "832x480",
"duration": 3,
"n": 1,
},
)
task = res.json()
print(f"Task ID: {task['id']}")
cURL - Keyframe video
FIRST_B64="$(base64 -w0 first-frame.png)"
LAST_B64="$(base64 -w0 last-frame.png)"
curl https://test.sealink.io/v1/video/generations \
-H "Authorization: Bearer $SEALINK_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "<keyframe-video-model-from-/v1/models>",
"prompt": "Smoothly move from the first frame to the last frame",
"image_url": "data:image/png;base64,'"$FIRST_B64"'",
"last_image_url": "data:image/png;base64,'"$LAST_B64"'",
"size": "832x480",
"duration": 5,
"n": 1
}'

POST /v1/video/edits

Video editing. Edit existing videos using prompts, including background replacement and style transfer. Animate-style edits usually require both a video input and a reference image, use /v1/video/edits, and human-body animation inputs should contain exactly one clearly visible human body.

Image-to-video, keyframe, and video-edit routes are most reliable with data:image/...;base64,... image inputs. Plain image or video URLs must be directly downloadable by the execution provider; avoid signed-in, blocked, very small, or private resources.

Parameters

ParameterTypeRequiredDescription
modelstringYesChoose a video editing model from /v1/models
videostringYesSource video as base64 or URL
promptstringYesEdit instruction description
negative_promptstringNoNegative prompt
image / image_urlstringNoReference image base64 or URL
reference_image_url / reference_urlstringNoReference image URL aliases
resolutionstringNoSame as video size enum
durationintegerNo1 - 60 seconds
seedintegerNoRandom seed
prompt_extendbooleanNoEnable prompt expansion
watermark / check_imagebooleanNoProvider watermark and image validation toggles
cURL
curl https://test.sealink.io/v1/video/edits \
-H "Authorization: Bearer $SEALINK_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "kling-v3-omni",
"video": "https://example.com/input-video.mp4",
"prompt": "Change the background to a beach sunset",
"resolution": "1280x720",
"duration": 5
}'
Python
import os
import requests
res = requests.post(
"https://test.sealink.io/v1/video/edits",
headers={"Authorization": f"Bearer {os.environ['SEALINK_API_KEY']}"},
json={
"model": "kling-v3-omni",
"video": "https://example.com/input-video.mp4",
"prompt": "Change the background to a beach sunset",
"resolution": "1280x720",
"duration": 5,
},
)
task = res.json()
print(f"Task ID: {task['id']}")
cURL - Animate
IMG_B64="$(base64 -w0 character.png)"
curl https://test.sealink.io/v1/video/edits \
-H "Authorization: Bearer $SEALINK_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "<video-animate-model-from-/v1/models>",
"prompt": "Make the subject wave gently",
"image_url": "data:image/png;base64,'"$IMG_B64"'",
"video_url": "https://example.com/single-person.mp4",
"size": "832x480",
"duration": 5,
"n": 1
}'

GET /v1/tasks/{task_id}

Poll async task status. Completed video tasks return data or upstream_response and settle usage at terminal state.

Status values: pending | running | completed | failed. Async routes with cancellation support can use DELETE /v1/tasks/{task_id} to release the pre-authorization; tasks without upstream cancellation return 501. Do not keep the submit request open while the video renders.

cURL
# Poll task status
curl https://test.sealink.io/v1/tasks/task_abc123 \
-H "Authorization: Bearer $SEALINK_API_KEY"
cURL - Cancel
# Cancel a running async task when the route supports cancellation
curl -X DELETE https://test.sealink.io/v1/tasks/task_abc123 \
-H "Authorization: Bearer $SEALINK_API_KEY"
Python — Poll Loop
# Poll until complete
import os
import requests
import time
task_id = "task_abc123"
while True:
res = requests.get(
"https://test.sealink.io/v1/tasks/" + task_id,
headers={"Authorization": f"Bearer {os.environ['SEALINK_API_KEY']}"},
)
task = res.json()
if task["status"] in ("completed", "failed"):
print(task["status"], task.get("data") or task.get("upstream_response"))
break
time.sleep(5)
Node.js — Poll Loop
const taskId = "task_abc123";
async function poll() {
while (true) {
const res = await fetch(
`https://test.sealink.io/v1/tasks/${taskId}`,
{ headers: { Authorization: `Bearer ${process.env.SEALINK_API_KEY}` } }
);
const task = await res.json();
if (task.status === "completed" || task.status === "failed") {
console.log(task.status, task.data ?? task.upstream_response);
break;
}
await new Promise(r => setTimeout(r, 5000));
}
}
poll();