AI video generation
Create videos from text and images, track progress and download MP4 through the Videos API.
Back to documentationConnection and authentication
Base URL: https://apivn.dev/v1
Authorization: Bearer $STALI_API_KEY
Set STALI_API_KEY in your environment. GET /v1/models checks authentication without creating a video.
read -r -s -p "STALI_API_KEY: " STALI_API_KEY
export STALI_API_KEY
printf '\n'
curl -fsS https://apivn.dev/v1/models -H "Authorization: Bearer ${STALI_API_KEY:?STALI_API_KEY}"cURL commands use Bash; on Windows, use the PowerShell setup. Replace sample media URLs with your own provider-accessible files.
Creating a video is billable. Save the id from a successful response to track the same job.
If a job fails after an id is returned, refunds depend on provider results and reconciliation. A failed status does not confirm an immediate wallet refund.
Polling, downloading and cancellation do not create another generation. Successful cancellation does not automatically reverse a recorded charge.
Models and capabilities
| Model | Duration (seconds) | Price / video | Reference images, max. | Aspect ratios | Resolution |
|---|---|---|---|---|---|
apivn/seedance-2.5 | 5 / 8 / 10 / 12 / 15 / 30 | $0.3182 / $0.4205 / $0.4886 / $0.5795 / $0.7159 / $1.06 | 0–9 | 16:9, 9:16, 1:1, 4:3, 3:4, 21:9, auto | 720p / 1080p |
seedance-2.5-30s | Fixed 30 | $2.27 | 1–9 | 16:9, 9:16, 1:1, 4:3, 3:4 | 720p |
seedance-2.5-10s | Fixed 10 | $1.36 | 1–9 | 16:9, 9:16, 1:1, 4:3, 3:4 | 720p |
seedance-2.5 | 5 / 10 / 15 / 20–30 | $0.1909 / $0.2932 / $0.4295 / $0.6341 | 1–10 | 16:9, 9:16, 1:1, 4:3, 3:4 | 720p |
seedance-2.0-fast | 5 / 10 / 15 | $0.15 / $0.2523 / $0.3886 | 1–10 | 16:9, 9:16, 1:1, 4:3, 3:4 | 720p |
veo-3.1 | 4 / 6 / 8 | $0.1136 / $0.1136 / $0.1136 | 1–3 | 16:9, 9:16 | — |
google-omni-flash | 5 / 10 | $0.15 / $0.15 | 1–3 | 16:9, 9:16 | 720p |
seedance-2.5-10s and seedance-2.5-30s use the fixed duration in their names; another seconds value does not change it.
Image, size and resolution support also depends on the provider route. Not every parameter applies to every model.
seedance-2.5 accepts 5, 10, 15 or seconds in the 20–30 range; values outside these groups are rejected. Within 20–30, values may be rounded to the nearest 20, 25 or 30 second step. apivn/seedance-2.5 accepts only 5, 8, 10, 12, 15 or 30. Check seconds in the response rather than inferring duration from the prompt.
Endpoints and parameters
POST /v1/videos — create a job
Send application/json. This endpoint reads JSON, not multipart/form-data; use URLs or image JSON supported by the model.
| Parameter | Requirement | Usage |
|---|---|---|
model | Required | An available video model ID; set it explicitly rather than relying on a default. |
prompt | Required | Describe the subject, setting, action and camera movement. |
seconds | Optional | See the model table. seedance-2.5 defaults to 5 seconds; apivn/seedance-2.5 defaults to 10; fixed-duration models ignore other seconds. |
aspect_ratio | Optional | An aspect ratio such as 16:9 or 9:16, depending on the model. Keep it consistent with size. apivn/seedance-2.5 also accepts 1:1, 4:3, 3:4, 21:9, and auto. |
size | Optional | Dimensions such as 1280x720 or 720x1280. Accepted sizes depend on the model. |
images / input_reference | Optional | Starting/reference images via URL/JSON. The entire body is limited to 20 MB; provider image limits also apply. |
last_frame | Optional | End frame for veo-3.1 or apivn/seedance-2.5 (batch-frame), used with input_reference. |
input_video | Optional | Source MP4 URL for google-omni-flash video-to-video. |
resolution | Optional | apivn/seedance-2.5 accepts 720p or 1080p (default 720p). 1080p bills at 2× the per-second 720p price. Other models may ignore this field or derive it from size. |
generate_audio | Optional | apivn/seedance-2.5: generate_audio (default true). Optional reference_audios (up to 2 URLs). |
GET /v1/videos/{id} — track progress
Include ?model= with the original model. Start with a 10-second polling interval and back off on 429. The JSON below is illustrative, not a live result.
- queued: the job was accepted and is waiting.
- in_progress: the provider is processing the job.
- completed: the result can be downloaded.
- failed: inspect error and keep the id for support.
{
"id": "video_abc123",
"object": "video",
"model": "apivn/seedance-2.5",
"status": "completed",
"progress": 100,
"seconds": "10",
"size": "1280x720",
"error": null
}GET /v1/videos/{id}/content — download MP4
Download only after completed. Send the same API key and ?model=; save the binary response as .mp4.
DELETE /v1/videos/{id} — request cancellation
Cancellation depends on the route and job state; some routes currently do not support DELETE. Cancellation does not guarantee a refund.
Pricing by duration
Prices follow this website’s current configuration, including applicable adjustments. Check them before creating a video.
| Model | Duration (seconds) | Price / video |
|---|---|---|
apivn/seedance-2.5 | 5 | $0.3182 |
apivn/seedance-2.5 | 8 | $0.4205 |
apivn/seedance-2.5 | 10 | $0.4886 |
apivn/seedance-2.5 | 12 | $0.5795 |
apivn/seedance-2.5 | 15 | $0.7159 |
apivn/seedance-2.5 | 30 | $1.06 |
seedance-2.5-30s | 30 | $2.27 |
seedance-2.5-10s | 10 | $1.36 |
seedance-2.5 | 5 | $0.1909 |
seedance-2.5 | 10 | $0.2932 |
seedance-2.5 | 15 | $0.4295 |
seedance-2.5 | 30 | $0.6341 |
seedance-2.0-fast | 5 | $0.15 |
seedance-2.0-fast | 10 | $0.2523 |
seedance-2.0-fast | 15 | $0.3886 |
veo-3.1 | 4 | $0.1136 |
veo-3.1 | 6 | $0.1136 |
veo-3.1 | 8 | $0.1136 |
google-omni-flash | 5 | $0.15 |
google-omni-flash | 10 | $0.15 |
Seedance 2.5: the 20–30 second group shares one price; the table shows the 30 second step. apivn/seedance-2.5 prices each of 5/8/10/12/15/30 separately (table = 720p; 1080p = 2×). Fixed-duration models and duration-priced models use separate pricing paths.
View all pricingIntegration examples
Each POST creates a billable video. Choose one example; example.com media URLs are placeholders and must be replaced.
import os
import time
from getpass import getpass
from urllib.parse import quote
import requests
from requests.adapters import HTTPAdapter
api_key = os.getenv("STALI_API_KEY") or getpass("STALI_API_KEY: ")
headers = {"Authorization": f"Bearer {api_key}"}
model = "apivn/seedance-2.5"
http = requests.Session()
http.mount("https://", HTTPAdapter(max_retries=0))
created = http.post("https://apivn.dev/v1/videos", headers=headers, json={
"model": model, "prompt": "Cinematic sunset over ocean waves",
"seconds": 10, "aspect_ratio": "16:9", "resolution": "720p",
"generate_audio": True,
}, timeout=(10, 120))
created.raise_for_status()
video = created.json()
video_id = video["id"]
print(video_id, video.get("status"), flush=True)
job_url = "https://apivn.dev/v1/videos/" + quote(video_id, safe="")
for _ in range(120):
if video.get("status") in ("completed", "failed"):
break
time.sleep(10)
progress = http.get(job_url, headers=headers, params={"model": model}, timeout=(10, 60))
progress.raise_for_status()
video = progress.json()
print(video_id, video.get("status"), flush=True)
if video.get("status") != "completed":
raise RuntimeError(str(video))
content = http.get(job_url + "/content", headers=headers, params={"model": model}, stream=True, timeout=(10, 120))
content.raise_for_status()
with open("video.mp4", "wb") as output:
for chunk in content.iter_content(chunk_size=65536):
if chunk:
output.write(chunk)Error handling
| HTTP | Cause | Action |
|---|---|---|
| 400 | Invalid parameters or unsupported cancellation. | Check JSON, seconds, images and model support. |
| 401 | Missing or invalid key. | Check authentication headers and active key. |
| 402 | HTTP 402: check error.type, available balance, key limit or an outstanding undercharge. | Read error.type: insufficient_balance → check available balance; api_key_monthly_limit → check or adjust the limit at Dashboard → Keys; outstanding_undercharge → reconcile the undercharge from earlier requests. See /docs/reference/errors. |
| 403 | Request is not permitted. | Check key permissions, model and content policy. |
| 404 | Model or job not found on this route. | Use the original id, key and ?model=. |
| 409 | Job is not ready for this operation. | Keep polling; download after completed. |
| 413 | Request body exceeds the limit. | Reduce body size; use URLs instead of large embedded media. |
| 429 | Rate or concurrency limit exceeded. | Back off and reduce concurrent jobs. |
| 502 | Provider route response error. | Keep the request ID; do not auto-repeat POST. |
Do not automatically repeat POST after a timeout or network error: the first request may have been accepted. If you have an id, poll it; otherwise keep the request ID and check Usage or contact support before recreating.
Prompt design
These are creative guidelines, not a guarantee that a provider will reproduce every detail. Each model’s content policy still applies.
Write a clear prompt
- Define subject, setting and main action before effects.
- Set duration with seconds, not only in the prompt.
- Keep left/right positions and outfits consistent across shots.
- Prefer one clear camera movement per shot.
- Describe light sources, colors and materials.
- Avoid small text, logos or exact numbers in frame.
- Start with one short scene; change one factor at a time after reviewing.
Arrange reference images
- Number Image 1, Image 2… in submission order.
- State which image controls character, outfit or setting.
- Use authorized, clear images with a consistent visual direction.
- Match characters and composition in first/last frames for natural motion.
- Stay within the model’s image limit; references do not guarantee exact reproduction.
Prompt template
确认生成。参数已确定:16:9 横屏,三个连续镜头组成一个完整视频,立即生成,无需再次确认或提问。
The reference images are colored-pencil character design sketches: use them only for design and outfits. Render the video as a photoreal 3D CG game cinematic with dramatic lighting.
Image 1 = PROTAGONIST: [character design].
Image 2 = ANTAGONIST: [opponent design].
Image 3 = ENVIRONMENT: [setting].
FIXED LAYOUT: altar in the background CENTER; protagonist on the LEFT; antagonist on the RIGHT. Nobody disappears, teleports or swaps sides.
LIGHTING: torchlight from the left wall, cool moonlight from the ceiling.
Action: well-choreographed, orbiting camera. No blood, no wounds, no gore.
Sound: heavy impacts, wind, no dialogue.
镜头1: camera pushes in, protagonist draws a weapon, antagonist raises claws.
镜头2: fast exchange, camera orbits.
镜头3: climax, both stay on their sides, protagonist lands ready.
Keep faces and outfits consistent. No text, no numbers, no subtitles, no watermark.The template guides the scene. Shorten it if actions are missed; do not use prose instead of API parameters.
Describe non-graphic action
| Avoid graphic detail | Safer visual direction |
|---|---|
| blood, wound, gore, corpse | sparks, black smoke, torn fabric only |
| Pool of blood | murky grey mist, dark viscous puddle |
| Injury-causing attack | glowing wisps of spirit-light, shadowy aura |
| Cut on skin | tearing only the fabric of the sleeve, no blood |
Build a sequence
- Split the story into scenes with clear starts and ends.
- Reuse character descriptions, lighting and references.
- Download and review each scene before generating the next.
- Join scenes in an editor; each POST remains a separate billable job.
When results miss the mark
- Missing actions: reduce events in one scene.
- Swapped positions: specify left/right and stable composition.
- Inconsistency: reuse references and identifying details.
- Wrong duration: check seconds and fixed-duration models.
- Rejected: review error and content policy; do not repeatedly resend the same request.
Review motion with a frame grid
ffmpeg -i clip.mp4 -vf "fps=1,scale=320:-1,tile=6x5" -frames:v 1 frame_grid.pngThis ffmpeg command reads local clip.mp4 and creates a frame grid without calling the API. Install ffmpeg first.
Preflight checklist
- Choose the correct model ID and supported duration.
- Check pricing and balance before creating.
- Keep keys server-side, out of public browser code.
- Use JSON and provider-accessible media URLs.
- Save id, model and request ID for tracking.
- Poll the same id with ?model= and back off when limited.
- Download after completed and verify the MP4 file.
- Do not recreate automatically when acceptance is uncertain.
- Review errors and costs in Usage; send the id to support if needed.

