Video models usually run as asynchronous tasks and may bill by seconds, resolution, or clip. Start with the shortest duration supported by that model, n=1, and a base resolution. Standard Hailuo models only accept 6 or 10 seconds, so do not use 5 or 7 seconds. Store x-sealink-request-id in production.
POST /v1/video/generationsAsync 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 editing are most reliable with data:image/...;base64,... image inputs. Plain image or video URLs must be publicly accessible without sign-in; avoid restricted, very small, expiring, or private resources. For video editing, do not request a duration longer than the usable source video unless the model detail says extension is supported.
The Seedance 2.0 series runs as asynchronous tasks. Standard supports 480p, 720p, 1080p, and 4K; Fast and Mini support 480p and 720p. Available parameters include seed, camera_fixed, and generate_audio, with duration from 4 to 15 seconds. Check the model details in /v1/models for current capabilities.
Use the model details in /v1/models as the source of truth; supported input modes, resolutions, and durations can differ by video model. Standard Hailuo models only accept 6 or 10 seconds; Hailuo 2.3 Fast currently uses 6-second image-to-video. A 503 model_temporarily_unavailable response means the selected model is temporarily unavailable; retry later or choose another available model.
Seedance 1.0 Pro and Pro Fast support 480p, 720p, and 1080p with a default of 1080p; duration is 2-12 seconds. You may send frames instead: valid values are 29-289 matching 25 + 4n at 24 fps, and frames takes precedence over duration. Seedance 1.5 Pro supports 480p, 720p, and 1080p with a default of 720p; duration is 4-12 seconds, or -1 for intelligent duration. Seedance 1.0 Pro supports last_image_url; Pro Fast rejects last-frame input.
| Parameter | Type | Required | Description |
|---|---|---|---|
| model | string | Yes | Choose a video generation model from /v1/models |
| prompt | string | Yes* | Video description; can be generated from an existing prompt template via template_id |
| template_id | string | No | Existing prompt template ID, use with variables; unknown templates return 404 |
| variables | object | No | Prompt template variables; values must be strings |
| image / image_url | string | No | Starting frame as base64 or URL |
| last_image_url | string | No | Last-frame image. Seedance 1.0 Pro supports last_image_url; Pro Fast rejects last-frame input |
| n | integer | No | 1 - 4 |
| size | string | No | 832x480, 480x832, 624x624, 1280x720, 720x1280, 960x960, 1088x832, 832x1088, 1920x1080, 1080x1920, 1440x1440, 1632x1248, 1248x1632, 864x480, 1248x704, 1920x1088 |
| resolution | string | No | Resolution alias; Seedance 1.0 Pro and Pro Fast support 480p, 720p, and 1080p, defaulting to 1080p; Seedance 1.5 Pro supports 480p, 720p, and 1080p, defaulting to 720p |
| duration | integer | No | Model-specific seconds; Seedance 1.0 Pro and Pro Fast accept 2-12 seconds and default to 5 seconds; Seedance 1.5 Pro accepts 4-12 seconds or -1 for intelligent duration |
| frames | integer | No | For models that support frame control; Seedance 1.0 Pro and Pro Fast require 29-289 matching 25 + 4n at 24 fps and frames takes precedence over duration |
| fps | integer | No | 1 - 60 |
| negative_prompt | string | No | Negative prompt, max 1024 chars |
| seed | integer | No | Random seed for reproducible generation |
| camera_fixed / watermark | boolean | No | Optional camera_fixed and watermark controls; support varies by model. Unsupported fields may be rejected or ignored. Check the model details in /v1/models. |
| webhook_url | string | No | Callback URL on completion (https only) |
| tags | array | No | Array of tag strings |
curl https://api.sealink.io/v1/video/generations \-H "Authorization: Bearer $SEALINK_API_KEY" \-H "Content-Type: application/json" \-d '{"model": "seedance-1-0-pro-fast","prompt": "A serene lake at sunset, camera slowly panning across the water","size": "1280x720","duration": 5,"n": 1}'
import osfrom openai import OpenAIimport requests# For async video generation, use the raw HTTP clientres = requests.post("https://api.sealink.io/v1/video/generations",headers={"Authorization": f"Bearer {os.environ['SEALINK_API_KEY']}"},json={"model": "seedance-1-0-pro-fast","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']}")
IMG_B64="$(base64 -w0 first-frame.png)"curl https://api.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": "<supported-size-from-/v1/models>","duration": 5,"n": 1}'
import osimport requestsres = requests.post("https://api.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": "<supported-size-from-/v1/models>","duration": 3,"n": 1,},)task = res.json()print(f"Task ID: {task['id']}")
FIRST_B64="$(base64 -w0 first-frame.png)"LAST_B64="$(base64 -w0 last-frame.png)"curl https://api.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": "<supported-size-from-/v1/models>","duration": 5,"n": 1}'
POST /v1/video/editsVideo 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 editing are most reliable with data:image/...;base64,... image inputs. Plain image or video URLs must be publicly accessible without sign-in; avoid restricted, very small, expiring, or private resources. For video editing, do not request a duration longer than the usable source video unless the model detail says extension is supported.
| Parameter | Type | Required | Description |
|---|---|---|---|
| model | string | Yes | Choose a video editing model from /v1/models |
| video | string | Yes | Source video as base64 or URL |
| prompt | string | Yes | Edit instruction description |
| negative_prompt | string | No | Negative prompt |
| image / image_url | string | No | Reference image base64 or URL |
| reference_image_url / reference_url | string | No | Reference image URL aliases |
| resolution | string | No | Same as video size enum |
| duration | integer | No | 1 - 60 seconds |
| seed | integer | No | Random seed |
| prompt_extend | boolean | No | Enable prompt expansion |
| watermark / check_image | boolean | No | Optional watermark and image-validation controls; support varies by model |
curl https://api.sealink.io/v1/video/edits \-H "Authorization: Bearer $SEALINK_API_KEY" \-H "Content-Type: application/json" \-d '{"model": "seedance-1-0-pro-fast","video": "<publicly-downloadable-video-url>","prompt": "Change the background to a beach sunset","resolution": "1280x720","duration": 5}'
import osimport requestsres = requests.post("https://api.sealink.io/v1/video/edits",headers={"Authorization": f"Bearer {os.environ['SEALINK_API_KEY']}"},json={"model": "seedance-1-0-pro-fast","video": "<publicly-downloadable-video-url>","prompt": "Change the background to a beach sunset","resolution": "1280x720","duration": 5,},)task = res.json()print(f"Task ID: {task['id']}")
IMG_B64="$(base64 -w0 character.png)"curl https://api.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": "<publicly-downloadable-single-person-video-url>","size": "<supported-size-from-/v1/models>","duration": 5,"n": 1}'
GET /v1/tasks/{task_id}Poll asynchronous task status. Completed video tasks return normalized data; failed tasks return a normalized error.
Status values: pending | running | completed | failed. If the selected model supports cancellation, use DELETE /v1/tasks/{task_id} to cancel the task; otherwise the endpoint returns 501. After submission, poll with the task ID instead of keeping the submit request open while the video renders.
# Poll task statuscurl https://api.sealink.io/v1/tasks/task_abc123 \-H "Authorization: Bearer $SEALINK_API_KEY"
# Cancel a running async task when the selected model supports cancellationcurl -X DELETE https://api.sealink.io/v1/tasks/task_abc123 \-H "Authorization: Bearer $SEALINK_API_KEY"
# Poll until completeimport osimport requestsimport timetask_id = "task_abc123"while True:res = requests.get("https://api.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("error"))breaktime.sleep(5)
const taskId = "task_abc123";async function poll() {while (true) {const res = await fetch(`https://api.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.error);break;}await new Promise(r => setTimeout(r, 5000));}}poll();