Video integration guide

For teams that call the API directly and produce video in volume: how to submit, poll and download reliably, plus a worked AI short-drama pipeline.

Back to the API reference · Released: 2026-11-03 (build 279d2e2db879) · https://tokentable.asia/v1

This page is advice and a worked example, not a contract. Fields, limits, error codes, retention and points are defined by the API reference and the member catalog (GET /v1/me/model-catalog); where they differ, the reference wins.

Model lists and points on this page are read from the same documentation data when the page loads, so they follow catalog changes automatically.

Prerequisites: before the first media request, sign in on the web and activate media (the API cannot activate it for you); video generation needs a paid plan or purchased points; advanced models marked spicy need a matching entitlement.

Part 1 — Running video at volume

Video is asynchronous: you submit, receive a taskId, poll to a terminal state and then download. At volume the costly mistakes are resubmitting a task that is in fact running, and losing a finished file before downloading it; every section below guards against those two.

A1 Request lifecycle

  1. 1. Submit
  2. 2. Store taskId
  3. 3. Poll status
  4. 4. Download
  5. 5. Store file
  1. Submit POST /v1/media/video. An accepted request returns HTTP 200 with status "pending", a taskId and the quotaCost held for it.
  2. Write the taskId and quotaCost to your own database immediately. There is no webhook, cancellation, idempotency key or task-list endpoint, so the taskId is your only handle on the task.
  3. Poll POST /v1/media/task/status with the taskId until status is succeeded, failed or delivery_failed.
  4. On success, follow the delivery descriptor in the status response (method and path) with the same Authorization header.
  5. Read the downloaded file for the real width, height, fps and audio. The size in the submit response only echoes the request.

The image endpoint POST /v1/media/image answers in one of two ways: asynchronous models return 202 with a taskId (same flow as above); synchronous models such as Seedream 5.0 return 200 with an image URL that lasts one hour, so download it at once.

From the API reference: Keep it: there is no webhook, cancellation, idempotency key or task-list endpoint, and video has no seed. If the submission itself times out without a taskId, the API cannot confirm whether a task was created; contact support before resubmitting.

A2 Polling interval and rate limits

  • Poll each task every 5 seconds or slower; generation time depends on model, resolution and duration.
  • Status, Seedance artifact and batch-status calls share a limit of 200 requests per minute per client IP (header x-ratelimit-limit); submissions are not counted.
  • Arithmetic: one poll every 5 seconds is 12 calls per task per minute, so one IP can poll about 16 tasks at once. With more tasks, lengthen the interval or poll from a queue in rotation instead of in parallel.
  • Starter plans also have daily caps.
From the API reference: Poll every 5 seconds or slower. Status, Seedance artifact and batch-status calls share a global limit of 200 requests per minute per client IP (x-ratelimit-limit); media submissions are not counted by it, and Starter plans have daily caps.

A3 What to do with each error

Rule of thumb: once you hold a taskId, every transient error means poll the same taskId again, never resubmit the generation. Failure and points handling differs by model; the "failure" part of each model note in the reference is authoritative.

SituationMeaningWhat to do
Submit returns 400/413/415The request itself is invalid: parameters, file size, format, or a file extension that does not match the real formatFix and resubmit (the reference states that 400 invalid_request and 415 image_type_mismatch are not charged)
Submit returns 402 insufficient_pointsNot enough pointsTop up, then resubmit
Submit returns 403Model or entitlement rejected (media not activated, plan without video, advanced model without entitlement)Check activation and plan; resubmitting unchanged will not help
Submit returns 429Daily or batch limit reachedDo not retry immediately; wait for the limit to reset or reduce the batch
Submit times out or disconnects with no taskIdThe API cannot confirm whether a task was createdDo not resubmit blindly; contact support first
Submit returns 502/503 with an error messageDispatch failed or its outcome is uncertain; points may have been refunded or may be held for reviewDo not resubmit immediately; read the failure part of the model note and contact support if needed
Submit returns 503 provider_payment_requiredThe upstream provider is temporarily unavailableThe system attempts to refund the held points; retry later and rely on your account records for the outcome
Status returns 5xx (for example 502 Failed to reach provider)This poll could not learn the result; the task has not failedPoll the same taskId again later; never resubmit the generation
status is failedGeneration failed (including moderation)Adjust the prompt or inputs and resubmit; points handling is in the model note
status is delivery_failed (generationStatus succeeded)Generation succeeded and was charged; only delivery failedDo not resubmit; poll again for a fresh descriptor and contact support if it keeps failing
Download returns 410The download grant or the upstream file expiredPoll status for a fresh grant; an expired upstream file cannot be recovered, so download as soon as a task succeeds

A4 Points: hold and settlement

  • Points are held on acceptance; the quotaCost in the video submit response is the held amount. Settlement happens only at a terminal state: captured on success, handled per the model note on failure. Pending polls never settle.
  • In some cases (an uncertain dispatch outcome, or a refund that itself fails) points stay held for review, so an error code alone does not prove a refund. At volume, record each taskId with its quotaCost and final status for reconciliation.
  • Asynchronous image 202 responses and their status responses carry no quotaCost; use the catalog price.
  • Seedance source-video requests accept quoteOnly=true for an exact quote with no charge and no task.

A5 Downloading and retention

  • Retention is promised only where stated: Seedance artifacts 30 days, private image artifacts 7 days, synchronous image URLs one hour (also lost on a server restart). Every other file has no promised retention, so download and store it as soon as it succeeds.
  • Treat "downloaded" as the last step of a task: download as soon as status is succeeded, store it in your own storage, and only then mark the task done.
  • Use the Content-Type of the download rather than assuming a format; Seedance was measured as MP4 with H.264 video and AAC audio.
  • Seedance artifacts and /v1/media/delivery/rmw accept a single Range header, which lets you resume large downloads.
From the API reference: Follow the returned delivery descriptor. Provider relays use POST /v1/media/delivery/video or /rmw; durable Seedance artifacts use authenticated GET /v1/media/artifact/:taskId. Seedance status responses carry that GET path as their delivery descriptor too, so every model can simply follow the descriptor. Video downloads carry a video/* Content-Type (Seedance measured as video/mp4 with H.264 video and AAC audio); read the Content-Type rather than assuming a format. Retention is promised only where stated: Seedance artifacts 30 days, private image artifacts P7D, synchronous image blobs one hour. Every other finished file has no promised retention and the upstream copy may expire (410), so download and store results as soon as they succeed.

A6 Not provided today

Not providedInstead
Webhook or completion callbackPoll POST /v1/media/task/status
Cancelling a taskNone; check parameters and points before submitting
Idempotency keyRecord the request on your side before submitting; never resubmit blindly after a timeout
Listing my tasksStore every taskId yourself
Video seedNone, results cannot be pinned; download good shots immediately
Muting or choosing video audioNone; strip the audio in post-production
Real width, height, fps or audio in the status responseRead the downloaded file

A7 The batch endpoint

  • POST /v1/media/video/batch submits several video requests (items) at once, with optional shared size, duration and model; it returns 202 with batchId, totalItems and quotaCost.
  • Track progress with GET /v1/media/batch/:batchId: completedItems, failedItems and per-item status.
  • The reference does not yet list which fields each item accepts. Shots that need a start image, first and last frames, reference images or a source video should go through single POST /v1/media/video calls with your own concurrency control.
  • A 429 from the batch endpoint can also mean the batch limit was reached.

Part 2 — AI short-drama pipeline (worked example)

The example is a vertical short drama of 20 shots, 5 seconds each, built as a pipeline you can batch. The models named in each step come from the documentation data.

B0 Overview

  1. 1. Script and shot list
  2. 2. Keyframes
  3. 3. Shot videos
  4. 4. Trial and final
  5. 5. Audio
  6. 6. Edit

B1 Script and shot list

  • Write the script with POST /v1/chat/completions and send "modalities": ["text"] (or the header X-TokenTable-Modalities: text) so the request is not treated as media generation.
  • To pin a model, check the id against GET /v1/models first: an unknown id is not rejected but routed as auto.
  • Ask for fixed-format JSON (below). Give every character one fixed appearance description and paste it verbatim into every image prompt; that is the basis of character consistency.
{
  "characters": [
    {
      "id": "A",
      "look": "woman in her twenties, short black hair, red trench coat, silver earring on the left ear"
    }
  ],
  "shots": [
    {
      "shot": 1,
      "seconds": 5,
      "characters": [
        "A"
      ],
      "camera": "slow push-in",
      "line": "(dialogue)",
      "startFrame": "(start frame description)",
      "endFrame": "(end frame = next shot start frame)"
    }
  ]
}

B2 Keyframes

  • Generate each shot's start frame with POST /v1/media/image. With first/last-frame chaining, 20 shots need 21 keyframes (the next shot's start frame is this shot's end frame).
  • Image models on the image endpoint are text-only today and take no reference image, so character consistency relies on the fixed appearance description.
  • For vertical 9:16, send size=1080*1920 with: qwen-image-3.0, wan2.7-image, kling/kling-v3-omni-image-generation (Kling snaps to the nearest ratio and the provider decides the pixels).
  • volcengine/doubao-seedream-5.0-flash, volcengine/doubao-seedream-5.0-pro have no aspect parameter and the model picks the ratio, so use them for character sheets (R2V references) rather than keyframes that must share one ratio.
  • Save files with an extension that matches the real format (a JPEG as .jpg); a mismatch returns 415 on the video endpoint.

B3 Shot videos

  • First/last-frame chaining (I2V_LAST): shot N uses keyframe N as image and keyframe N+1 as lastImage, so each shot lands on the next one's opening. Supported: volcengine/doubao-seedance-2.5, volcengine/doubao-seedance-2.0, volcengine/doubao-seedance-2.0-fast, volcengine/doubao-seedance-2.0-mini, bytedance/seedance-2.5-spicy, bytedance/seedance-2.0-spicy, bytedance/seedance-2.0-fast-spicy, bytedance/seedance-2.0-mini-spicy, w3.0-video (advanced), w3.0-video-pro (advanced).
  • Use the same aspect ratio for both keyframes: Seedance follows the start frame and centre-crops the end frame. On Seedance, I2V_LAST costs the same as T2V at the same resolution and duration.
  • Lock a character's look (R2V): repeat the referenceImage field with character references and refer to them in the prompt, for example "the first reference image" (results not guaranteed). Supported: volcengine/doubao-seedance-2.5, volcengine/doubao-seedance-2.0, volcengine/doubao-seedance-2.0-fast, volcengine/doubao-seedance-2.0-mini, bytedance/seedance-2.5-spicy, bytedance/seedance-2.0-spicy, bytedance/seedance-2.0-fast-spicy, bytedance/seedance-2.0-mini-spicy, w3.0-video (advanced), w3.0-video-pro (advanced).
  • Vertical dramas: Seedance T2V and R2V output is fixed at 16:9. For vertical output use a 9:16 start image (I2V or I2V_LAST); Seedance follows the start image ratio.
  • Upload images as multipart/form-data (image, lastImage, referenceImage); image URLs are not accepted.

B4 Trial and final

  • Check framing and motion at low resolution first, then resubmit the same inputs at a higher resolution; for example volcengine/doubao-seedance-2.0-mini at 480p for 5 seconds costs 13 points.
  • For text-to-video, volcengine/doubao-seedance-2.5 offers draft then final: draft=true produces a 480p draft at the 480p price, then draftTaskId produces the 1080p final (reusing the draft prompt and duration; one final per draft, within seven days; drafts take no image or video input).
  • Video has no seed, so the same prompt gives a different result each time; download good shots immediately.

B5 Audio

  • Output from volcengine/doubao-seedance-2.5, volcengine/doubao-seedance-2.0, volcengine/doubao-seedance-2.0-fast, volcengine/doubao-seedance-2.0-mini, wan2.6-t2v, happyhorse-1.1-t2v, w3.0-video (advanced), w3.0-video-pro (advanced) includes an audio track that cannot be muted or chosen; see each model note for the others. Strip the audio in post-production when you need clean footage (see B6).
  • Use POST /v1/media/audio for narration and voice-over; it returns an audio URL synchronously. Audio retention is not promised, so download it at once.
  • text: Up to 2000 characters per call; longer text returns 400 text_too_long, so split it.
  • voice: longxiaochun_v2 (default), longcheng_v2, longhua_v2 or longshu_v2; any other or missing value uses the default without an error.

B6 Editing

TokenTable does not edit or composite. After downloading, join, mix and subtitle with an editor or ffmpeg. Common ffmpeg commands:

# 1) Remove the original audio
ffmpeg -i shot01.mp4 -an -c:v copy shot01_silent.mp4
# 2) Join shots (same codec, resolution and fps)
printf "file 'shot01.mp4'\nfile 'shot02.mp4'\n" > list.txt
ffmpeg -f concat -safe 0 -i list.txt -c copy episode.mp4
# 3) Replace the audio with narration
ffmpeg -i episode.mp4 -i narration.mp3 -map 0:v -map 1:a -c:v copy -c:a aac -shortest episode_vo.mp4

When shots come from different models or resolutions, re-encode them to one resolution and fps before joining; -c copy will fail otherwise.

B7 Cost estimate

Estimates for 20 shots × 5 seconds plus 21 keyframes, computed live from catalog points; trials, retries, voice-over and text are extra.

RecipeVideo model · resolutionPer shot (5s)Keyframe modelPer imageTotal
Entryvolcengine/doubao-seedance-2.0-mini · 720p28 pointsqwen-image-3.02 points28 × 20 + 2 × 21 = 602 points
Standardvolcengine/doubao-seedance-2.0 · 720p56 pointswan2.7-image3 points56 × 20 + 3 × 21 = 1183 points
High qualityvolcengine/doubao-seedance-2.5 · 1080p211 pointswan2.7-image3 points211 × 20 + 3 × 21 = 4283 points

Points per 5-second shot for every video model (use it to price other combinations):

ModelResolutionPer 5s shot20 shots
wan2.6-t2v—541080
kling/kling-v3-omni-video-generation—651300
happyhorse-1.1-t2v—651300
volcengine/doubao-seedance-2.5480p38760
volcengine/doubao-seedance-2.5720p861720
volcengine/doubao-seedance-2.51080p2114220
volcengine/doubao-seedance-2.0480p26520
volcengine/doubao-seedance-2.0720p561120
volcengine/doubao-seedance-2.01080p1402800
volcengine/doubao-seedance-2.04k2855700
volcengine/doubao-seedance-2.0-fast480p21420
volcengine/doubao-seedance-2.0-fast720p45900
volcengine/doubao-seedance-2.0-mini480p13260
volcengine/doubao-seedance-2.0-mini720p28560
bytedance/seedance-2.5-spicy480p591180
bytedance/seedance-2.5-spicy720p1322640
bytedance/seedance-2.5-spicy1080p3236460
bytedance/seedance-2.0-spicy480p40800
bytedance/seedance-2.0-spicy720p861720
bytedance/seedance-2.0-fast-spicy480p32640
bytedance/seedance-2.0-fast-spicy720p691380
bytedance/seedance-2.0-mini-spicy480p20400
bytedance/seedance-2.0-mini-spicy720p43860
vega-video-1.0-pro720p46920
vega-video-1.0-pro1080p1002000
vega-video-1.0-pro-fast720p38760
vega-video-1.0-pro-fast1080p811620
vega-video-1.0-pro-mini720p24480
vega-video-1.0-pro-mini1080p521040
vega-video-1.5-pro720p691380
vega-video-1.5-pro1080p1503000
vega-video-1.0-lite1080p29580
wan2.7-i2v-spicy (advanced)720p741480
w3.0-video (advanced)720p34680
w3.0-video (advanced)1080p681360
w3.0-video-pro (advanced)1080p611220
w3.0-video-pro (advanced)2k681360
seedance-2.5-i2v-spicy (advanced)480p1022040
seedance-2.5-i2v-spicy (advanced)720p2034060
seedance-2.5-i2v-spicy (advanced)1080p50710140
seedance-2.5-i2v-spicy (advanced)4k101320260

Back to the API reference