Seedance video generation uses an asynchronous task model. A create-task request returns only a task ID, and the video does not appear in the response. The integrator has to query the status, handle failures, and copy the result to storage before the link expires.
If you write code with the synchronous mindset of Chat Completions, you will usually time out at the first step. This article follows the order of a real deployment and explains the base URL, authentication, submission, polling, download, callbacks, and idempotency.
Note: Seedance, ByteDance, Doubao, Volcano Engine, and Volcano Ark are names and trademarks of their respective owners. This article is for technical explanation only and does not imply any partnership, agency, or endorsement relationship. Endpoint paths, model names, and prices are subject to the official or on-site documentation.
1. Integration parameters: base URL, model, and authentication
The official Volcano Ark data-plane base URL is https://ark.cn-beijing.volces.com/api/v3, and the path for creating a video task is /contents/generations/tasks. Authentication uses Authorization: Bearer $ARK_API_KEY, and the request body is JSON.
The model field accepts either a model ID or an endpoint ID. The difference lies in authentication: with an API key, both are usually accepted; with AK/SK signing, you generally must supply an endpoint ID and cannot pass a model ID directly. This is one of the most common traps during migration and debugging.
Before integrating, confirm three things: whether the model is enabled, whether the account quota is sufficient, and whether the current channel supports the duration and resolution you intend to use. Gateway users should first read the on-site documentation to confirm that the video channel and task fields match the official interface.
| Operation | Method and path | Notes |
|---|---|---|
| Create task | POST /contents/generations/tasks |
Returns a task ID, not a video |
| Query task | GET /contents/generations/tasks/{id} |
Returns status and result |
| List tasks | GET /contents/generations/tasks |
Batch reconciliation and compensation |
| Cancel task | Cancellation or deletion endpoint per documentation | Usually only effective for queued tasks |
Support for cancellation, deletion, and list queries varies by platform, so check the documentation before integrating. Do not append /api/v3 twice to the base URL, or you will get a path error.
2. Submitting a task: what one POST must carry
Below is a common task creation request. The fields are examples only:
export ARK_API_KEY="your-api-key"
export BASE_URL="https://ark.cn-beijing.volces.com/api/v3"
curl -sS -X POST "$BASE_URL/contents/generations/tasks" \
-H "Authorization: Bearer $ARK_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "doubao-seedance-1-0-pro-250528",
"content": [
{"type": "text", "text": "A harbor at dawn, container cranes, slow aerial orbit, realistic style"},
{"type": "image_url", "image_url": {"url": "https://example.com/first-frame.jpg"}, "role": "first_frame"}
],
"duration": 5,
"ratio": "16:9",
"resolution": "720p",
"watermark": false,
"callback_url": "https://api.example.com/callbacks/seedance"
}'
Several fields deserve attention:
contentis an array. Text, first-frame images, reference images, and reference videos each use differenttypeandrolevalues.- The allowed ranges for
duration,ratio, andresolutionchange with the model version. Do not copy them directly from another provider's documentation. watermarkcontrols whether the output carries a watermark. Confirm platform rules before commercial use.callback_urlreceives task completion notifications, and whether it is supported depends on the actual platform.- Fields such as
seed,camera_fixed, andreturn_last_frameare not supported by every model.
After a successful submission, write the task ID from the response to your database immediately and bind it to the business order number. Polling, retries, reconciliation, and cost allocation all depend on this ID.
3. Polling: state machine and backoff strategy
Querying a task requires only the task ID:
curl -sS "$BASE_URL/contents/generations/tasks/$TASK_ID" \
-H "Authorization: Bearer $ARK_API_KEY"
Common states and how to handle them:
| status | Meaning | Recommended action |
|---|---|---|
queued |
Waiting in queue | Keep waiting; cancel if necessary |
running |
Generating | Keep polling; do not resubmit |
succeeded |
Succeeded | Read the result and copy it to storage immediately |
failed |
Failed | Record the error code and decide whether a retry is appropriate |
expired |
Terminated by timeout | Adjust the timeout or parameters, then resubmit |
cancelled |
Cancelled | Confirm whether the business cancelled it intentionally |
Do not poll once per second at a fixed interval. Start at 5 seconds and back off to 10, then 20 seconds, capping around 30 seconds, and add a small amount of random jitter so multiple instances do not hit the upstream at the same moment. Set an overall timeout appropriate to the business, for example 10 minutes. When it expires, mark the task for manual review rather than waiting indefinitely.
Task records are usually queryable only for a limited period; official documentation gives a figure of about 7 days. Beyond that window, historical status can only come from your own task table, so persist every state change promptly.
4. Downloading and storing results
After a task succeeds, the response includes a video URL. That URL usually expires; official documentation puts the validity at about 24 hours, and some models limit the number of downloads. Do not hand it to a frontend or a customer as if it were a permanent CDN address.
The correct pattern is to download immediately on success, copy the file to your own object storage, and record the task ID, business order number, object path, file size, and checksum. Only then write the internal address into your business database. This way, even after the upstream link expires, historical orders can still be replayed and delivered.
The download step must also account for large files, resumable transfers, concurrency limits, and retry on failure. If the response also returns a first-frame image or audio, store each field separately instead of saving only the video.
5. Webhook or polling
Both approaches can deliver results. The difference is latency and operational cost:
| Approach | Advantages | Disadvantages | Suitable for |
|---|---|---|---|
| Webhook | Low latency, fewer wasted queries | Requires a public endpoint, signature verification, and replay protection | Production async tasks |
| Polling | Simple to implement, no public endpoint required | Adds latency and extra requests | Internal tools, testing, fallback |
| Hybrid | Callback first, polling as fallback | Requires state deduplication | Most production systems |
The more robust production pattern is callback plus reconciliation: callbacks provide low latency, while a scheduled job scans records that have stayed out of a terminal state for too long and acts as the safety net. The callback endpoint must verify signatures and be idempotent. It must not insert a record or trigger downstream work twice just because a notification arrived. Lost callbacks are not rare, so they cannot be the only notification mechanism.
6. Idempotency and duplicate submissions
Video tasks are expensive and slow, so duplicate submissions cost far more than they do for text APIs. Control this at four levels:
- Generate a business idempotency key before submission, such as the order number plus a version, and check the database before submitting.
- Put a unique index on the task ID and business order number so the database blocks duplicate records.
- A request timeout does not mean the task failed. Look up the idempotency key, or query the task list, and confirm nothing was created before retrying.
- Retry only 429, 5xx, and network errors. Do not blindly retry 400 parameter errors or content moderation rejections.
Record the reason for cancellations and resubmissions as well. Otherwise one business order may produce several videos, which raises costs and makes reconciliation difficult. Run a daily reconciliation job that compares task status, billing, and output artifacts.
7. Common errors and troubleshooting
401 AuthenticationError: the key is missing or invalid, the request header is malformed, or the base URL does not match the key.403 AccessDenied,AccountOverdueError: insufficient permission, an account in arrears, or a service that is not enabled.404 ModelNotOpen,UnsupportedModel: the model is not enabled, or its name is misspelled.400 SensitiveContentDetected: the prompt or source material triggered content review. Replace the material instead of retrying repeatedly.400 InvalidParameter: a field name, duration, ratio, or resolution is outside the allowed range.429 RateLimitExceeded: reduce concurrency and apply exponential backoff; request a higher quota if needed.failedorexpired: readerror.codeanderror.messageto distinguish parameter problems, moderation rejection, and upstream outages.
Error code strings may change as the platform evolves, so rely on the actual response and the error code documentation. Logging the raw error code, request ID, and redacted request parameters together significantly shortens diagnosis time.
8. Migration checklist
When moving from the official interface to a gateway, or from one gateway to another platform, confirm each item below:
- The base URL and authentication method are replaced as a set, not just the key.
- Whether
modeltakes a model ID or an endpoint ID, and whether that matches the current authentication method. - Request field names, duration, ratio, and resolution are within the new channel's supported range.
- The status enumeration covers queued, running, succeeded, failed, expired, and cancelled.
- The result link's validity period, download limit, and copy-to-storage logic have been verified.
- The callback address is publicly reachable, with signature verification and idempotent handling in place.
- Idempotency keys, the task table, reconciliation jobs, and alerts are live.
- Rate limits, timeouts, retries, and concurrency caps have been load-tested.
After migration, run a small batch first and compare success rate, average latency, and cost per video before scaling up. Do not switch all traffic over without a reconciliation mechanism.
FAQ
Does the Seedance API return a video synchronously?
Usually not. Creating a task returns only a task ID. You need to poll or wait for a callback, then download the video after success. Designing around a synchronous interface leads to timeouts and duplicate submissions.
How long are task IDs and results retained?
According to official documentation, task records are usually queryable for about 7 days, and result video links are valid for about 24 hours. Long-term retention requires copying results to your own object storage.
What polling interval is appropriate?
Start at 5 seconds and back off gradually to 15 or 30 seconds, with an overall timeout. Fixed high-frequency polling wastes requests and is more likely to trigger rate limiting.
Does it support Webhook callbacks?
The official create-task endpoint provides a callback_url field, but delivery depends on network conditions and platform policy. Whether a gateway supports callbacks should be confirmed in its documentation, and production systems should keep polling as a fallback.
Are failed tasks billed?
Rules differ by platform and failure type. Before integrating, confirm how moderation rejections, timeouts, and cancellations are billed, and verify with a small batch against your invoice.
Next steps
First run one task with the shortest duration and a lower resolution, then fill in the task table, polling, storage, and reconciliation. If you need a unified entry point, register with the ZSQH AI Gateway and confirm the Seedance channel and billing method on the model pricing page.
Related reading:
