DocsVideo generation

Video generation

How to use the video API (submit, check progress, download the file), the fields and values each model accepts, how tasks are charged, how long files can be downloaded, and errors.

Generating a video takes time, so a single call does not return the video. You use it as a task (a job you submit and whose result you collect after generation finishes), in three steps.

StepMethod and pathWhat it does
1. SubmitPOST /v1/videosSend the model, the prompt (a description of the video you want), the length and the resolution. The task ID is returned
2. Check progressGET /v1/videos/{task ID}Repeat at intervals until status becomes completed or failed
3. Download the fileGET /v1/videos/{task ID}/contentReturns the finished video as an MP4 file

The base URL and the way you send the key are the same as for the other OpenAI-format endpoints (https://token.echohub.io/v1, Authorization: Bearer key).

The models currently offered are listed in the model list.

Models

Model IDProviderLengthResolutionInputs you can use
MiniMax-H3MiniMax[ ]768P, 2K[ ]
doubao-seedance-2-0-260128 (Seedance 2.0)ByteDance (Volcano Engine)[ ]480p, 720p, 1080p, 4k[ ]
  • Prices (per second or per 1 million tokens) are listed on each model's page in the model list
  • The processing region is shown on each model's page in the model list. The prompt and the images, videos and audio used as references are passed to the provider's API that processes them in that region (Data handling)
  • The fields and values you can use differ by model. See "Parameters by model" below

Example

This example makes a 6-second 768P video with MiniMax-H3 and saves it as video.mp4. Put your key in the environment variable ECHO_API_KEY first (Quickstart).

bash
# 1. Submit. Note the id that is returned
curl "https://token.echohub.io/v1/videos" \
  -H "Authorization: Bearer $ECHO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "MiniMax-H3",
    "prompt": "夕方の海辺を、柴犬がゆっくり歩いている",
    "seconds": 6,
    "resolution": "768P"
  }'

# 2. Check progress. Set VIDEO_ID to the id returned in step 1
VIDEO_ID="task_..."
curl "https://token.echohub.io/v1/videos/$VIDEO_ID" \
  -H "Authorization: Bearer $ECHO_API_KEY"

# 3. When status is completed, download the file
curl -o video.mp4 "https://token.echohub.io/v1/videos/$VIDEO_ID/content" \
  -H "Authorization: Bearer $ECHO_API_KEY"

1. Submit

Send the following fields as JSON to POST /v1/videos.

ParameterRequiredDescription
modelRequiredThe model ID
promptRequired for MiniMax-H3A description of the video you want
secondsLength of the video in seconds. An integer
resolutionResolution (MiniMax-H3). For Seedance 2.0, write it in metadata.resolution
imagesAn array of image URLs, used for the first and last frame (the first and last picture of the video) (MiniMax-H3)
input_referenceThe URL of an image to use as the first frame (MiniMax-H3)
metadataExtra settings for each model (Seedance 2.0's resolution, aspect ratio, sound on or off, reference material and so on). A JSON object
  • Pass images, videos and audio as public URLs that the provider's servers can fetch
  • Each model decides where each value goes. Values written anywhere other than the place given in "Parameters by model" may not be used. Echo refuses requests that would produce a video different from what you asked for or a price that does not match, such as a length, resolution or image written where Seedance 2.0 does not read it (HTTP 400, "Requests that are rejected")
  • Do not use the OpenAI-format size (such as 1280x720). It does not set the aspect ratio; some models read it as the resolution and others return an error
  • For MiniMax-H3 you can also attach an image file to the request: use the form format (multipart/form-data) and attach one file as input_reference (up to 20 MB). In the form format, write metadata as a JSON string. Seedance 2.0 does not accept files (HTTP 400); pass images as URLs

When the submission is accepted, JSON like the following is returned with HTTP 200.

JSON
{"id":"task_3H0YkK1PMgAiKglDcHbxqtL8WC7C247u","object":"video","model":"MiniMax-H3","status":"queued","progress":0,"created_at":1790796502}

An estimated price is deducted from your balance at submission ("Pricing" below).

2. Check progress

GET /v1/videos/{task ID} returns the state of the task.

FieldDescription
idThe task ID (a string starting with task_)
objectAlways video
modelThe model ID
statusThe state (table below)
progressA number from 0 to 100, fixed for each state (0 right after submission, 10 (Seedance 2.0) or 30 (MiniMax-H3) while waiting, 50 while generating, 100 when finished). It does not measure actual progress
created_atWhen the task was submitted (seconds since 1970-01-01)
completed_atWhen the task completed. Present only when it has completed
errorWhy the task failed (code and message). Present only when the provider returned a reason (Seedance 2.0). Not present for MiniMax-H3
statusMeaning
queuedWaiting in the provider's queue
in_progressBeing generated
completedCompleted. You can download the file
failedFailed. The price is refunded in full
  • Echo's servers ask the provider for progress every 15–30 seconds, so it can take about 30 seconds after the provider finishes before the status becomes completed. The interval is sometimes longer than 30 seconds
  • Check progress every 10–15 seconds or so. Echo does not send a notice when a task completes
  • A task that has not completed 24 hours after submission is set to failed and refunded in full. For Seedance 2.0, the provider cancels a task that has not completed 23 hours after submission; it then becomes failed and is refunded in full

3. Download the file

GET /v1/videos/{task ID}/content returns the finished video as an MP4 file (Content-Type: video/mp4). You can also use HEAD to check only the file size, or the Range header to download part of the file.

  • Echo does not store generated videos. Each time you call this path, Echo fetches the file from the provider and passes it to you as is
  • You can download the file only while the provider keeps it. After that, HTTP 410 is returned. Download and save the file soon after the task completes
ModelHow long the provider keeps the file
Seedance 2.0[ ]
MiniMax-H3[ ]

Parameters by model

MiniMax-H3

ItemFieldValues
LengthsecondsAn integer ([ ]). Default 5
Resolutionresolution768P or 2K. Default 768P
Aspect ratiometadata.ratio16:9, 9:16, 1:1, 4:3, 3:4, 21:9, adaptive (follow the input image or video). Default: adaptive when you pass an image or video, 16:9 otherwise. adaptive cannot be used without an image or video
First and last frameimages1 or 2 image URLs. The first is the first frame and the second is the last frame. An image in input_reference becomes the first frame
Reference imagesmetadata.contentUp to 9, in the form shown in the example below
Reference videosmetadata.reference_videoAn array of URLs. Up to 3
  • Frames (images, input_reference) and references (images, videos) cannot be used together
  • Reference audio cannot be used (HTTP 400)
  • Without prompt, HTTP 400 is returned

An example with a reference image:

JSON
{
  "model": "MiniMax-H3",
  "prompt": "画像のマグカップが、木のテーブルの上でゆっくり回っている",
  "seconds": 5,
  "resolution": "768P",
  "metadata": {
    "content": [
      {"type": "image_url", "image_url": {"url": "https://example.com/mug.png"}, "role": "reference_image"}
    ]
  }
}
TypeAccepted files (provider's specification)
ImageJPG, PNG, WEBP, HEIC, HEIF. Up to 30 MB each. Width and height 256–5760 pixels, width ÷ height 0.4–2.5
VideoMP4, MOV. Up to 50 MB each. 2–15 seconds each, 15 seconds in total
Whole requestUp to 64 MB. Pass large files as URLs

Seedance 2.0 (doubao-seedance-2-0-260128)

ItemFieldValues
LengthsecondsAn integer ([ ])
Resolutionmetadata.resolution480p, 720p, 1080p, 4k. Default 720p
Aspect ratiometadata.ratio16:9, 4:3, 1:1, 3:4, 9:16, 21:9, adaptive. Default adaptive (the model chooses from the prompt or images)
Soundmetadata.generate_audiotrue (with sound) or false (no sound). Default true
First frame, first and last frame, referencesmetadata.contentIn the form shown in the example below. role decides how each item is used
Maximum wait at the providermetadata.execution_expires_afterA whole number of seconds from 3600 to 82800. When omitted, Echo sets 82800 (23 hours). The provider cancels a task that has not completed within this time, and the price is refunded in full
  • Write the length in seconds and the resolution in metadata.resolution. The top-level resolution, duration and input_reference, and parameters such as --dur 5 after the prompt, cannot be used with Seedance 2.0 (HTTP 400, "Requests that are rejected")
  • Do not omit seconds and metadata.resolution. When they are omitted, the estimated price is calculated as 15 seconds at 1080p, so you may not be able to submit because of your balance (the price is recalculated from actual usage after generation)
  • First frame, first and last frame, and references (images, videos, audio) cannot be combined (provider's specification)
  • Pass images, videos and audio as URLs. Attaching a file in the form format returns HTTP 400
  • Images and videos showing real people's faces cannot be used as references (provider's specification)

An example with a first and last frame:

JSON
{
  "model": "doubao-seedance-2-0-260128",
  "prompt": "つぼみがゆっくり開いて花が咲く",
  "seconds": 5,
  "metadata": {
    "resolution": "720p",
    "content": [
      {"type": "image_url", "image_url": {"url": "https://example.com/first.png"}, "role": "first_frame"},
      {"type": "image_url", "image_url": {"url": "https://example.com/last.png"}, "role": "last_frame"}
    ]
  }
}
roleUseCount
first_frameFirst frame (type is image_url). On its own, the video starts from this image1
last_frameLast frame (type is image_url). Use it together with first_frame1
reference_imageReference image (type is image_url)1–9
reference_videoReference video (type is video_url, URL in video_url.url)Up to 3
reference_audioReference audio (type is audio_url, URL in audio_url.url). Use it together with an image or videoUp to 3
TypeAccepted files (provider's specification)
ImageJPEG, PNG, WEBP, BMP, TIFF, GIF, HEIC, HEIF. Under 30 MB each. Width and height 300–6000 pixels, width ÷ height 0.4–2.5
VideoMP4, MOV. Up to 200 MB each. 2–15 seconds each, 15 seconds in total
AudioWAV, MP3. Up to 15 MB each. 2–15 seconds each, 15 seconds in total
Whole requestUp to 64 MB

Requests that are rejected

Echo refuses the following at submission, because the video would not match what you asked for, or the price would be calculated from different values than the ones used to generate the video. They return HTTP 400 with error.code invalid_request, and message says how to write the request instead. They are free.

What was writtenModelWrite insteadmessage
The length in duration or metadata.duration (without seconds, or with a different value from seconds)Seedance 2.0secondsWrite the video length in seconds, for example "seconds": 5. This model does not read duration. With a value different from seconds: duration does not match seconds. Write the video length only in seconds
A seconds value that is not a whole number (such as 5.5)Seedance 2.0A whole number (5 or "5")seconds must be a whole number of seconds, for example "seconds": 5
The length as frames or metadata.frames (a number of frames)Seedance 2.0secondsThis model does not read frames. Write the video length in seconds, for example "seconds": 5
The resolution in the top-level resolutionSeedance 2.0metadata.resolutionWrite the resolution in metadata.resolution, for example "metadata": {"resolution": "720p"}. This model does not read the top-level resolution
Only size, without metadata.resolutionSeedance 2.0metadata.resolutionWrite the resolution in metadata.resolution, for example "metadata": {"resolution": "720p"}. This model does not read size
A metadata.resolution other than 480p, 720p, 1080p and 4k (such as 720P)Seedance 2.0One of these fourmetadata.resolution must be one of 480p, 720p, 1080p, 4k
Length or resolution parameters after the prompt (--dur 5, --rs 720p and so on)Seedance 2.0seconds and metadata.resolutionWrite the video length in seconds and the resolution in metadata.resolution. This model does not accept --dur in the prompt
Images in input_reference, image or imagesSeedance 2.0metadata.content (for the first frame, set role to first_frame)This model does not read input_reference. Put images in metadata.content; for the first frame use {"type": "image_url", "image_url": {"url": "<image URL>"}, "role": "first_frame"}
A file attached in the form formatSeedance 2.0Image URLs in metadata.contentThis model does not accept uploaded files. Pass images as URLs in metadata.content; for the first frame use {"type": "image_url", "image_url": {"url": "<image URL>"}, "role": "first_frame"}
A metadata.execution_expires_after outside 3600–82800Seedance 2.0A whole number from 3600 to 82800 (when omitted, Echo sets 82800)metadata.execution_expires_after must be a whole number of seconds from 3600 to 82800 (1 to 23 hours)
Reference audio (metadata.reference_audio, audio_url in metadata.content)MiniMax-H3Not availableReference audio is not supported for this model. Remove audio_url and reference_audio from the request
A video model called through POST /v1/responses or POST /v1/tasks/…BothPOST /v1/videosVideo generation requests must be sent to POST /v1/videos
  • In message, duration, frames, input_reference and --dur are replaced with the name you actually wrote (metadata.duration, image, --rs and so on)
  • For a correctly written request, the only thing Echo adds is metadata.execution_expires_after for Seedance 2.0 (the maximum time to wait at the provider). Everything else reaches the provider as written

Pricing

Video is charged at a unit price per second (MiniMax-H3) or per 1 million tokens (Seedance 2.0). Tokens are the unit the provider uses to count the amount of video. Unit prices are listed on each model's page in the model list.

The price of a task is settled in this order.

  1. When you submit, an estimated price is deducted from your balance. The estimate is calculated from the requested length and resolution (for MiniMax-H3, also the number of reference images and any reference video). If your balance or the key's spending limit is not enough, the submission is refused (HTTP 403)
  2. When generation finishes, the price is recalculated from the actual usage the provider reports, and the difference is refunded or additionally deducted
  3. Tasks that fail, and tasks that have not completed 24 hours after submission (23 hours for Seedance 2.0), are refunded in full
ModelWhat the recalculation uses
Seedance 2.0The actual number of tokens. The unit price per 1 million tokens depends on whether you attached a reference video
MiniMax-H3The actual length, number of reference images and seconds of reference video. A reference video is counted as 15 seconds at submission
  • Requests refused at submission (wrong values, requests the provider did not accept and so on) are free
  • An additional deduction is made even if your balance is not enough. The part that makes your balance negative is deducted from your next top-up (Pricing and top-ups)
  • The state and price of each task are shown in 「呼び出し履歴」 (Call history) in the console (API keys and usage)

Errors

Error bodies use the same format as the other OpenAI-format endpoints (Errors). Errors specific to video generation are listed below.

CaseHTTP status and error.codemessageWhat to do
A value such as the length or resolution cannot be used with the model400, invalid_request or an empty stringAn English sentence giving the reason (for example MiniMax-H3 duration must be an integer between 4 and 15 seconds)Fix it using "Parameters by model"
The request is written in a way Echo refuses (for Seedance 2.0, the length in duration or a file attached in the form format; a video model called through POST /v1/responses, and so on)400, invalid_requestAn English sentence saying how to write it (for example Write the video length in seconds, for example "seconds": 5. This model does not read duration)Fix it using "Requests that are rejected"
The provider did not accept the request400, upstream_errorThe model service rejected the request, check the parameters and try againCheck the values and the URLs of images and other files
Wrong task ID, or a task of another account400 (404 when downloading the file), task_not_foundTask not foundCheck the ID
The file was requested before the task completed400, task_not_readyThe video is not ready yetDownload after the status becomes completed
The file of a failed task was requested400, task_failedThe video generation failedSubmit again
The provider no longer keeps the file410, artifact_goneArtifact content is no longer availableThe file cannot be downloaded. Submit again
Insufficient balance403, insufficient_quotaInsufficient balanceTop up
Not enough of the key's spending limit left403, insufficient_quotaThis API key has reached its spending limitRaise the spending limit (Limits and rate limits)
Wrong model ID503, model_not_foundThe model {model ID} does not exist or is not availableCheck the model ID

Errors returned at submission are free.

Using the OpenAI SDK

  • The OpenAI SDKs (Python, Node.js) also have video functions (videos.create and so on), but in the SDKs they are marked as deprecated with the note "The Sora API is scheduled to permanently shut down on September 24, 2026". The examples on this page call the API over HTTP without the SDK
  • The SDK's videos.create sends the request in the form format (multipart/form-data). In this format, metadata does not reach the provider unless it is a JSON string (Python example: extra_body={"metadata": json.dumps({"resolution": "720p"})})

Sources

WhatSourceChecked
The three steps and responses, states and progress, downloading the file (including HEAD and Range), error bodies, deduction, recalculation and refunds, Seedance 2.0's metadata.resolution and metadata.content (role) reaching the provider, Seedance 2.0 refusing form-format files, metadata in the form format and in the SDK's videos.createMeasured in Echo's test environment, with the same relay settings as production and a server that returns test responses in place of the provider's API2026-10-02
How often progress is checked (19–36 seconds from submission to the first check, then every 30 seconds)Measured in Echo's test environment (as above)2026-10-01
Tasks not completed within 24 hours are failed and refundedEcho relay server settings (as of 2026-10-01)2026-10-01
Requests that are rejected and their errors; Echo setting Seedance 2.0's metadata.execution_expires_after to 82800Measured in Echo's test environment (as above)2026-10-02
The range of Seedance 2.0's metadata.execution_expires_after (3600–259200 seconds, 172800 when omitted); parameters such as --dur after the prompthttps://www.volcengine.com/docs/82379/15207572026-10-02
MiniMax-H3 length, resolution, aspect ratio, input combinations and file conditions; the file URL has a time limithttps://platform.minimax.io/docs/api-reference/video-generation-v2-create , https://platform.minimax.io/docs/api-reference/video-generation-v2-query2026-10-01
Seedance 2.0 length, resolution, aspect ratio, sound, role and file conditions; files kept for 24 hours; real people's faces cannot be used as referenceshttps://www.volcengine.com/docs/82379/1520757 , https://www.volcengine.com/docs/82379/15213092026-10-01
The OpenAI SDKs' video functions are deprecatedhttps://github.com/openai/openai-python (3.23.0), https://github.com/openai/openai-node (7.27.0)2026-10-02