Videos API

AI video generation

Create videos from text and images, track progress and download MP4 through the Videos API.

Back to documentation

Connection 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

ModelDuration (seconds)Price / videoReference images, max.Aspect ratiosResolution
apivn/seedance-2.55 / 8 / 10 / 12 / 15 / 30$0.3182 / $0.4205 / $0.4886 / $0.5795 / $0.7159 / $1.060–916:9, 9:16, 1:1, 4:3, 3:4, 21:9, auto720p / 1080p
seedance-2.5-30sFixed 30$2.271–916:9, 9:16, 1:1, 4:3, 3:4720p
seedance-2.5-10sFixed 10$1.361–916:9, 9:16, 1:1, 4:3, 3:4720p
seedance-2.55 / 10 / 15 / 20–30$0.1909 / $0.2932 / $0.4295 / $0.63411–1016:9, 9:16, 1:1, 4:3, 3:4720p
seedance-2.0-fast5 / 10 / 15$0.15 / $0.2523 / $0.38861–1016:9, 9:16, 1:1, 4:3, 3:4720p
veo-3.14 / 6 / 8$0.1136 / $0.1136 / $0.11361–316:9, 9:16—
google-omni-flash5 / 10$0.15 / $0.151–316:9, 9:16720p

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.

ParameterRequirementUsage
modelRequiredAn available video model ID; set it explicitly rather than relying on a default.
promptRequiredDescribe the subject, setting, action and camera movement.
secondsOptionalSee the model table. seedance-2.5 defaults to 5 seconds; apivn/seedance-2.5 defaults to 10; fixed-duration models ignore other seconds.
aspect_ratioOptionalAn 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.
sizeOptionalDimensions such as 1280x720 or 720x1280. Accepted sizes depend on the model.
images / input_referenceOptionalStarting/reference images via URL/JSON. The entire body is limited to 20 MB; provider image limits also apply.
last_frameOptionalEnd frame for veo-3.1 or apivn/seedance-2.5 (batch-frame), used with input_reference.
input_videoOptionalSource MP4 URL for google-omni-flash video-to-video.
resolutionOptionalapivn/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_audioOptionalapivn/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.

ModelDuration (seconds)Price / video
apivn/seedance-2.55$0.3182
apivn/seedance-2.58$0.4205
apivn/seedance-2.510$0.4886
apivn/seedance-2.512$0.5795
apivn/seedance-2.515$0.7159
apivn/seedance-2.530$1.06
seedance-2.5-30s30$2.27
seedance-2.5-10s10$1.36
seedance-2.55$0.1909
seedance-2.510$0.2932
seedance-2.515$0.4295
seedance-2.530$0.6341
seedance-2.0-fast5$0.15
seedance-2.0-fast10$0.2523
seedance-2.0-fast15$0.3886
veo-3.14$0.1136
veo-3.16$0.1136
veo-3.18$0.1136
google-omni-flash5$0.15
google-omni-flash10$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 pricing

Integration 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

HTTPCauseAction
400Invalid parameters or unsupported cancellation.Check JSON, seconds, images and model support.
401Missing or invalid key.Check authentication headers and active key.
402HTTP 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.
403Request is not permitted.Check key permissions, model and content policy.
404Model or job not found on this route.Use the original id, key and ?model=.
409Job is not ready for this operation.Keep polling; download after completed.
413Request body exceeds the limit.Reduce body size; use URLs instead of large embedded media.
429Rate or concurrency limit exceeded.Back off and reduce concurrent jobs.
502Provider 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

  1. Define subject, setting and main action before effects.
  2. Set duration with seconds, not only in the prompt.
  3. Keep left/right positions and outfits consistent across shots.
  4. Prefer one clear camera movement per shot.
  5. Describe light sources, colors and materials.
  6. Avoid small text, logos or exact numbers in frame.
  7. 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 detailSafer visual direction
blood, wound, gore, corpsesparks, black smoke, torn fabric only
Pool of bloodmurky grey mist, dark viscous puddle
Injury-causing attackglowing wisps of spirit-light, shadowy aura
Cut on skintearing only the fabric of the sleeve, no blood

Build a sequence

  1. Split the story into scenes with clear starts and ends.
  2. Reuse character descriptions, lighting and references.
  3. Download and review each scene before generating the next.
  4. 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.png

This 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.
Support