Skip to main content

Open API v1 · Seedance 2.0

Put video generation behind your product

AiuniVid Open API is an asynchronous generation gateway. Create returns a task ID immediately. The website and API share the same credit ledger. It exposes Seedance 2.5 and Seedance 2.0 across text, image, and reference modes; 2.0 also has Fast and Mini tiers — twelve public model IDs.

  • Text-to-Video: Generate from a text description.
  • Image-to-Video: Use 1–2 images as first or first-and-last frames.
  • Reference-to-Video: Use images, video, and audio as multimodal references.

Quickstart

Any signed-in user can create an av_live_ key in Developer Center. The secret is shown once — store it on your server.

  1. 1. Set environment variables
    export AIUNIVID_BASE_URL=https://aiunivid.com/api/open
    export AIUNIVID_API_KEY=av_live_xxx
  2. 2. Quote credits (optional, no charge)
    POST the same body to /v1/videos/generations/quote and read data.credits_to_hold.
  3. 3. Create the task
    POST /v1/videos/generations with a required Idempotency-Key. Success is 202 plus a task id. Replaying the same key and body does not charge twice.
  4. 4. Poll or receive a webhook
    GET /v1/videos/generations/{id} until status is succeeded or failed — or pass callback_url on create. On success, use result.download_url.

Integrate into your video product

Keep AiuniVid behind your backend. Users talk only to your product; your service owns the API key and task sync.

01

Product UI

Submits prompt, model, and media.

02

Your backend

Validates the user, stores a record, then calls AiuniVid.

03

AiuniVid API

Returns 202 and a task ID.

04

Result page

Reads your task status and plays the video.

Boundary: Do not call the Open API from the browser. Never expose the API key, webhook secret, or billing decisions to the client.

Authentication and scopes

Authorizationstring · headerrequired
Every endpoint requires Authorization: Bearer $AIUNIVID_API_KEY.
Idempotency-Keystring · headerrequired
Required on create. UUID recommended. Same key and body replay within 24h returns the first result; same key with a different body returns 409 idempotency_conflict.
ScopeGrants
video:createCreate and quote generation tasks.
video:readRead tasks, models, and credit balance.
files:writeRequest presigned upload URLs for reference media.

Rate limits

Every response includes X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset (Unix seconds). Exceeding the limit returns 429 rate_limit_exceeded.

ClassEndpointsLimit
Create endpointsPOST /v1/videos/generations, /quote, /{id}/final10 requests / minute / key
Read endpointsGET /v1/models, /v1/credits/balance, /v1/videos/generations, /v1/videos/generations/{id}60 requests / minute / key

Models and capabilities

GET /v1/modelsendpoint
Returns public models available to the current key, including allowed duration, quality, aspect_ratio, and capability flags. Fast and Mini do not support 1080p.
{
  "success": true,
  "request_id": "req_xxx",
  "data": {
    "models": [
      {
        "id": "seedance-2.0-text-to-video",
        "name": "Seedance 2.0 Text-to-Video",
        "mode": "text-to-video",
        "tier": "standard",
        "durations": [5, 8, 10],
        "aspect_ratios": ["16:9", "9:16", "1:1"],
        "qualities": ["480p", "720p", "1080p"],
        "capabilities": {
          "text_to_video": true,
          "generate_audio": true,
          "max_images": 0,
          "max_videos": 0,
          "max_audios": 0
        }
      }
    ]
  }
}

Quote a generation

POST /v1/videos/generations/quoteendpoint
Use the same body as create to estimate credits. This does not create a task or reserve credits; it returns data.credits_to_hold. Quote and create share one billing formula.
{
  "success": true,
  "request_id": "req_01JQ9X2B6XK9K4VQY2QZ4H6W3R",
  "data": {
    "model": "seedance-2.5-text-to-video",
    "credits_to_hold": 50,
    "currency_note": "credits"
  }
}

Create a generation

POST /v1/videos/generationsendpointrequired
Creates an asynchronous video task and returns 202 with the task object. Use the monitor on the right to switch model and language examples.
modelenum<string>required
Use these public model IDs; do not send upstream aliases.
Model IDModeTier
seedance-2.5-text-to-videotext-to-videostandard
seedance-2.5-image-to-videoimage-to-videostandard
seedance-2.5-reference-to-videoreference-to-videostandard
seedance-2.0-text-to-videotext-to-videostandard
seedance-2.0-image-to-videoimage-to-videostandard
seedance-2.0-reference-to-videoreference-to-videostandard
seedance-2.0-fast-text-to-videotext-to-videofast
seedance-2.0-fast-image-to-videoimage-to-videofast
seedance-2.0-fast-reference-to-videoreference-to-videofast
seedance-2.0-mini-text-to-videotext-to-videomini
seedance-2.0-mini-image-to-videoimage-to-videomini
seedance-2.0-mini-reference-to-videoreference-to-videomini
promptstringrequired
1–10,000 characters. In reference mode, use @image1, @video1, and @audio1 to address array items by position.
image_urlsstring<uri>[]
Public HTTPS URLs. Text mode rejects images; image mode requires 1–2 (one first frame, two first-and-last); reference mode allows up to 9 images on Seedance 2.0 and 30 on Seedance 2.5.
video_urls / audio_urlsstring<uri>[]
Reference mode only. Seedance 2.0 accepts up to 3 video and 3 audio URLs; audio cannot be the only reference input. Seedance 2.5 accepts up to 10 each and allows audio-only. Use GET /v1/models capabilities for the selected model.
durationinteger
Seedance 2.5: 4–30 seconds. Seedance 2.0 series: 4–15 seconds. Default 5. Use GET /v1/models for the selected model's allowed values.
qualityenum<string>
480p, 720p, or 1080p; default 720p. Seedance 2.5 and 2.0 support 1080p. Fast and Mini top out at 720p and reject 1080p with 422 unsupported_capability.
aspect_ratioenum<string>
16:9, 9:16, 1:1, 4:3, 3:4, 21:9, or adaptive.
generate_audioboolean
Defaults to true and is included in the quote.
draftboolean
Draft mode, Seedance 2.5 only. Renders at 480p and is billed as a normal 480p video; omit quality or pass 480p, anything else returns 422. When you like the draft, render the same shot in 1080p with /{id}/final.
callback_urlstring<uri>
Optional public HTTPS URL. A terminal task object is posted to it; verify the signature.
metadataobject
Optional string values only, 500 characters each. Echoed on the task object.

Task management

GET /v1/videos/generations/{id}endpoint
Poll until status is succeeded or failed. Submitted tasks cannot be cancelled; wait for completion or a failed refund. On success, use result.download_url — a platform URL, not an upstream temporary link. State machine: queued → processing → succeeded | failed.
GET /v1/videos/generationsendpoint
Lists tasks newest first. Query params: limit (1–100, default 20), cursor, and status. data.next_cursor is null on the last page.
{
  "success": true,
  "request_id": "req_xxx",
  "data": {
    "tasks": [{ "id": "vid_01JQ9X2B6XK9K4VQY2QZ4H6W3R", "status": "succeeded" }],
    "next_cursor": null
  }
}
POST /v1/videos/generations/{id}/cancelendpoint
Cancellation is not supported. Submitted tasks run until they succeed or fail; failed tasks refund reserved credits. This endpoint returns 403 task_cancel_not_allowed.
POST /v1/videos/generations/{id}/finalendpoint
Renders a succeeded draft (draft: true) as a 1080p final; requires Idempotency-Key. The final reuses the draft's prompt, reference media, duration, aspect ratio, seed, and audio setting, so the body accepts only optional callback_url and metadata. It is billed as a normal 1080p video and the new task carries draft_id. Returns 410 draft_expired 7 days after the draft was created, 409 draft_not_ready if the draft has not succeeded, and 409 final_exists with details.task_id if a final is already running or done. A failed final can be retried. For when drafts pay off and what they cost, see the Seedance 2.5 draft mode guide.

Upload reference media

POST /v1/uploads/presignendpoint
Send filename, content_type, and optional purpose. PUT bytes to data.upload_url with the returned headers, then pass data.public_url in image_urls, video_urls, or audio_urls. Requires files:write.
{
  "success": true,
  "request_id": "req_xxx",
  "data": {
    "upload_url": "https://aiunivid.com/api/open/v1/uploads/put?key=api-uploads/...&sig=...",
    "public_url": "https://cdn.example.com/api-uploads/user/file.png",
    "expires_at": 1761314644,
    "headers": { "Content-Type": "image/png" },
    "method": "PUT"
  }
}

Credit balance

GET /v1/credits/balanceendpoint
Returns available_credits and frozen_credits. Quote first, then decide whether the user can submit.

Billing

The website and API use the same markup for the same user. 1 credit = $0.01.

StageBehavior
quoteNo charge; returns credits_to_hold
createReserves credits_reserved
succeededSettles credits_settled
failed / cancelledReleases the hold as credits_refunded

Webhooks

Pass callback_url on create. AiuniVid POSTs the full task object when the task reaches succeeded, failed, or cancelled.

X-AiuniVid-Eventheader
video.completed · video.failed · video.cancelled
X-AiuniVid-Signatureheader
Format t=<unix seconds>,v1=<hex>. signed_payload = "{t}." + raw_body; v1 is hex(HMAC-SHA256(secret, signed_payload)). Reject timestamps older than 5 minutes. Read the raw body before JSON.parse.

Node

import { createHmac, timingSafeEqual } from "node:crypto";

export function verifyAiuniVidSignature(header, rawBody, secret) {
  const parts = Object.fromEntries(
    header.split(",").map((item) => item.split("="))
  );
  const age = Math.abs(Date.now() / 1000 - Number(parts.t));
  if (age > 300) throw new Error("Signature timestamp is stale");

  const expected = createHmac("sha256", secret)
    .update(`${parts.t}.${rawBody}`)
    .digest("hex");

  if (
    !timingSafeEqual(Buffer.from(parts.v1, "utf8"), Buffer.from(expected, "utf8"))
  ) {
    throw new Error("Invalid signature");
  }
}

Python

import hmac, hashlib, time

def verify_aiunivid_signature(header: str, raw_body: str, secret: str) -> None:
    parts = dict(item.split("=", 1) for item in header.split(","))
    if abs(time.time() - int(parts["t"])) > 300:
        raise ValueError("Signature timestamp is stale")
    expected = hmac.new(
        secret.encode(),
        f'{parts["t"]}.{raw_body}'.encode(),
        hashlib.sha256,
    ).hexdigest()
    if not hmac.compare_digest(parts["v1"], expected):
        raise ValueError("Invalid signature")

Delivery times out after 10 seconds. Non-2xx responses are retried with exponential backoff (1s, 2s, 4s, 8s, …) for up to 24 hours. Always return 2xx to acknowledge the event.

Producing a series

A short-form series is many small jobs that share the same characters and settings. Four habits keep it consistent and its cost predictable.

  1. Upload each character once. Upload the character image through /v1/uploads/presign, then pass the same public_url in image_urls on every request of the series and refer to it as @image1 in the prompt. Recognizable real faces are refused by every model, so use a generated or illustrated character.
  2. One request per shot. Keep each request to one story beat and assemble the shots in your own edit. Give every shot its own Idempotency-Key: replay the same key only when you never received a response, such as after a network drop. To retry a shot that failed, use a new key — replaying the same key within 24 hours returns the first result.
  3. Quote the batch before you submit it. Send every body to /v1/videos/generations/quote, compare the total with available_credits from /v1/credits/balance, and stop before submitting if the balance is short; quote and charge use one formula. Create endpoints allow 10 requests per minute per key, so pace a large batch instead of firing it at once.
  4. Collect results by webhook rather than tight polling. Pass callback_url on create; read endpoints allow 60 requests per minute per key, which a batch of polling loops reaches quickly. A failed shot releases its frozen credits automatically.

For keeping one character consistent from shot to shot, see the consistent character guide.

Advanced compatibility path

The primary path is /v1/videos/generations. If you already integrated BytePlus-style content[] payloads, /v1/contents/generations/tasks (and its quote endpoint) remains available. New integrations should not use this path.

POST /v1/contents/generations/tasksendpoint
model uses internal tiers seedance-2.5 / seedance-2.0 / seedance-2.0-fast / seedance-2.0-mini. content is an array of text / image_url / video_url / audio_url items. Billing matches the primary path. Idempotency-Key is still required.

Error handling

Branch on the stable error.code, not the message text. 500 is safe to retry with the same Idempotency-Key.

HTTPerror.codeMeaning
400invalid_requestMalformed request body or fields
400unsupported_modelModel ID is not one of the public IDs
401invalid_api_keyKey is invalid, expired, or revoked
402insufficient_creditsNot enough available credits
403insufficient_scopeKey lacks the required scope
403task_cancel_not_allowedTask cancellation is not supported
404task_not_foundTask does not exist or is not owned by this key
409idempotency_conflictSame Idempotency-Key reused with a different body
422unsupported_capabilityFields exceed the model's capability
422unsafe_inputMedia or callback URL is not a public HTTPS address
429rate_limit_exceededRate limit exceeded
429too_many_concurrent_jobsIn-flight generation jobs exceeded the account limit
500internal_errorRetry with the same Idempotency-Key

Machine-readable contract: openapi.yaml · api-reference.md · llms.txt

Written byJarvisFounderLast updated
Seedance 2.5 & 2.0 API Documentation | AiuniVid