asset_id, and then reference it as asset://<asset_id> in your Seedance video-generation tasks. Once an asset reaches the Active state, every subsequent generation that references it benefits from stable character consistency across shots and skips re-processing of that asset on every request.POST /api/v1/asset/upload (Section 3) and reuse the resulting asset://<id> across many tasks. The asset is pre-vetted once, then referenced for free. Counts toward your per-plan quota (Section 2), TTL is auto-refreshed on every reference.auto_upload_assets: true on your task and pass raw URLs directly (Section 7). The service uploads them, runs your task, and cleans them up after the retention window. Independent per-plan cap (Section 7.5), no manual lifecycle work.| Pattern | Recommended setup | When it fits |
|---|---|---|
| Managed only | Upload your cast (Section 3) → reference asset://... in every task. auto_upload_assets omitted. | A stable cast / brand library that you generate against repeatedly. The cast is small, well-defined, and reused so often that upfront vetting pays back many times. |
| Ephemeral only | Pass raw URLs in image_urls / video_urls / audio_urls. Set auto_upload_assets: true. | Every task uses fresh references (on-demand user content, throwaway avatars, A/B variants). You don't want to track or clean up asset state at all. |
| Mixed — managed cast + ephemeral additions | image_urls: ["asset://main-character", "https://cdn/guest-of-the-day.png"] with auto_upload_assets: true. | A stable protagonist appears in every task, but each task also brings in a one-off guest character, secondary actor, or variant. Main cast stays canonical; the rotating cast is ingested per-task. |
| Mixed — managed cast + raw scenery | image_urls: ["asset://main-character", "https://cdn/scene-today.png"] with auto_upload_assets: false (or omitted). | A stable cast plus a varying scene / background / prop image. The scene doesn't need cross-task consistency, so don't waste your ephemeral cap or quota on it — let it pass through as a raw URL consumed once. |
Rule of thumb: a reference that will appear in more than one future task → make it a managed asset. A reference that will only ever be used once → ephemeral (if you want auto cleanup) or raw URL (if it's just a background that doesn't need to be vetted as an asset at all).
Processing → Active (usable) or Failed (fetch failed / asset rejected / multi-face violation)list / get / Seedance references refresh last_used_atX-API-Key HTTP header. Asset endpoints additionally require an account plan ≥ hobbyist.| Plan | Max Assets | TTL (auto-purged when idle) |
|---|---|---|
| hobbyist | 50 | 3 days |
| developer | 200 | 7 days |
| premium | 500 | 15 days |
| enterprise | 1000 | 15 days |
Failed state do not count toward your quota.The numbers above apply to persistent assets (uploaded via Section 3). If you only want one-off references for a single task, see Section 7 (auto-upload mode) — those use a separate pool with an independent hard cap and do not consume your per-plan quota.
| Field | Required | Description |
|---|---|---|
url | ✅ | Publicly reachable URL. Must remain reachable for at least 24 hours so the service can fetch it asynchronously. |
asset_type | optional | Image / Video / Audio. Inferred from the URL suffix when omitted. |
name | optional | Display name for the asset. Defaults to the last path segment (e.g. example1.png). |
| Type | Extensions | Size limit | Other |
|---|---|---|---|
| Image | jpeg / jpg / png / webp / bmp / tiff / gif / heic / heif | < 30 MB | Aspect ratio (0.4, 2.5); width/height (300, 6000) px |
| Video | mp4 / mov | ≤ 50 MB | 480p / 720p / 1080p; 2–15 s; 24–60 FPS |
| Audio | mp3 / wav | ≤ 15 MB | 2–15 s |
{
"asset_id": "asset-20260607154123-6nxk8",
"status": "Processing",
"upload_at": "2026-06-07T15:41:23Z",
"expires_at": "2026-06-22T15:41:23Z"
}{
"total": 4,
"success": 4,
"failed": 0,
"results": [
{"asset_id": "asset-20260607154123-aaaa1", "status": "Processing"},
{"asset_id": "asset-20260607154124-bbbb2", "status": "Processing"},
{"asset_id": "asset-20260607154124-cccc3", "status": "Processing"},
{"asset_id": "asset-20260607154125-dddd4", "status": "Processing"}
]
}error field describing the cause.Processing. Poll until they reach Active before referencing them in a generation request.| Param | Default | Description |
|---|---|---|
page | 1 | Page number |
size | 20 | Page size (≤ 100) |
status | all | Comma-separated subset, e.g. active,processing,failed |
order | -last_used_at | Sort key; - prefix for descending order |
{
"items": [
{
"asset_id": "asset-20260607154123-aaaa1",
"name": "char-female",
"asset_type": "Image",
"status": "Active",
"url": "https://your-cdn.com/example1.png",
"last_used_at": "2026-06-07T15:41:23Z",
"expires_at": "2026-06-22T15:41:23Z",
"created_at": "2026-06-07T15:41:23Z"
}
],
"total": 4,
"page": 1,
"size": 20,
"quota": {
"used": 4,
"limit": 500,
"ttl_days": 15
}
}url field echoes back the original URL you uploaded with — keep it persistent if you want it as a thumbnail preview source.last_used_at (preventing LRU purge).{
"asset_id": "asset-20260607154123-aaaa1",
"name": "char-female",
"asset_type": "Image",
"status": "Active",
"url": "https://your-cdn.com/example1.png",
"last_used_at": "2026-06-07T15:50:00Z",
"expires_at": "2026-06-22T15:50:00Z",
"created_at": "2026-06-07T15:41:23Z"
}status=Failed, the response carries an error object with details:{
"asset_id": "asset-...",
"status": "Failed",
"error": {
"code": "ImageFormatNotSupported",
"message": "Image format heif is not supported by current version"
}
}{
"deleted": 4,
"failed": 0,
"results": [
{"asset_id": "asset-...aaaa1", "status": "deleted"},
{"asset_id": "asset-...bbbb2", "status": "deleted"},
{"asset_id": "asset-...cccc3", "status": "deleted"},
{"asset_id": "asset-...dddd4", "status": "deleted"}
]
}asset://<asset_id> instead of a regular URL.seedance-2-less-restriction (std) and seedance-2-fast-less-restriction (fast)seedance-2 / seedance-2-fast); requests carrying asset:// references will fast-fail. Use the corresponding -less-restriction variant instead.Image 1 / Image 2 / Video 1 / Audio 1 notation. The index matches the position inside image_urls / video_urls / audio_urls.@image1 / @video2 / @audio1 reference syntax is also accepted; the service rewrites it to the canonical form automatically.{
"code": 200,
"data": {
"task_id": "3f5ab17a-0b2e-44a3-b31d-3e6075e2b974",
"status": "pending"
},
"message": "success"
}asset:// reference belongs to the calling accountstatus=Activetask_type is one of the -less-restriction variants{
"code": 200,
"data": {
"task_id": "3f5ab17a-...",
"status": "processing"
}
}{
"code": 200,
"data": {
"task_id": "3f5ab17a-...",
"status": "completed",
"input": {
"prompt": "Cinematic. Photo realistic. A cyber female Image 1 stands in courtyard Image 3. Cyber warrior Image 2 next to her. Cyber boss Image 4 emerges. 5s scene.",
"image_urls": ["asset://asset-...aaaa1", "asset://asset-...bbbb2", "asset://asset-...cccc3", "asset://asset-...dddd4"],
"aspect_ratio": "16:9",
"duration": 5,
"resolution": "720p"
},
"output": {
"video": "https://img.theapi.app/ephemeral/026610ac-5b23-4105-ac06-30f2044f304d.mp4"
},
"meta": {
"usage": {
"type": "point",
"consume": 10000000
}
}
}
}The video URL is valid for 24 hours — download or consume it within that window.
| status | Meaning |
|---|---|
pending | Accepted, queued for scheduling |
processing | Generation in progress |
completed | Success; output.video is ready |
failed | Failure; inspect error.message |
auto_upload_assets: true on your Seedance task. Any non-asset:// URL inside image_urls / video_urls / audio_urls is auto-ingested as an ephemeral private asset before the task runs, and cleaned up afterwards.asset://... references pass through untouched while raw URLs get auto-ingested. See the Overview's pattern table for the four common combinations and when each one is the right choice.| Field | Type | Default | Notes |
|---|---|---|---|
auto_upload_assets | bool | false | Enable auto-upload. Requires a -less-restriction task type. |
asset_retention_hours | int | 3 | Clamped to [3, 8]. How long the auto-uploaded asset stays after the task completes — useful if you want follow-up tasks to reference the same inputs. |
GET /api/v1/asset/list with lifecycle: "ephemeral".asset_retention_hours so follow-up tasks can reference them by their assigned asset://<id>. After that window the service deletes them automatically.DELETE /api/v1/asset/:asset_id at any time.| Plan | Concurrent ephemeral cap |
|---|---|
| hobbyist | 20 |
| developer | 50 |
| premium | 100 |
| enterprise | 200 |
429 ephemeral asset hard cap reached. Wait for in-flight tasks to complete, delete some ephemeral assets via Section 5, or upgrade to a higher plan.auto_upload_assets flag:auto_upload_assets: true){
"input": {
"image_urls": [
"asset://asset-20260607154123-aaaa1", // recurring protagonist (Section 3)
"https://your-cdn.com/guest-actor.png" // one-off guest — auto-ingested as ephemeral asset
],
"auto_upload_assets": true,
"asset_retention_hours": 3
}
}auto_upload_assets: false){
"input": {
"image_urls": [
"asset://asset-20260607154123-aaaa1", // recurring protagonist (Section 3)
"https://your-cdn.com/scene-today.png" // background — consumed once, not made into an asset
],
"auto_upload_assets": false
}
}asset:// reference gets its TTL refreshed (same as Sections 4.1 / 4.2).| HTTP | Message | Meaning / Resolution |
|---|---|---|
| 400 | invalid request: 'url' is required | Missing url field on upload |
| 400 | unsupported asset_type: xxx | The file extension is not in the whitelist |
| 400 | quota exceeded: plan hobbyist allows 50 assets, currently 50 | Quota full — delete old assets or upgrade plan |
| 400 | auto_upload_assets requires a -less-restriction task type | Auto-upload mode only works with seedance-2-less-restriction or seedance-2-fast-less-restriction |
| 400 | auto-upload image url[N] timed out waiting for ingestion | Auto-upload failed to ingest within 90 s — verify the URL is reachable and the file is valid |
| 400 | auto-upload image url[N] rejected: <reason> | Upstream rejected the file (format / size / safety) — fix the asset and retry |
| 403 | asset not owned by this account | The referenced asset_id belongs to another account |
| 404 | asset not found | Wrong asset_id or already deleted |
| 409 | asset still processing | Wait a few seconds and retry |
| 422 | asset:// references are only allowed on -less-restriction task types | Switch task_type to seedance-2-(fast-)less-restriction |
| 422 | asset xxx status=Failed | The referenced asset failed processing; GET its details to see why |
| 429 | ephemeral asset hard cap reached: plan <plan> allows N concurrent ephemeral assets | Too many auto-upload assets in flight — wait, delete some, or upgrade plan (Section 7.5) |
status=Active the original URL is no longer required, but keeping it alive for at least 24 hours is the safe default.last_used_at, so frequently-used assets never hit the LRU TTL.auto_upload_assets: false so they don't consume your ephemeral cap. See the Overview's pattern table for the four common combinations.asset_retention_hours — if you only ever submit a single task per upload, leave it at the default 3. If you chain follow-up tasks (e.g. an edit pass on the same characters), set it closer to 8 so the assets stick around long enough to be reused without re-ingesting.Image 1 maps to image_urls[0], Image 2 to image_urls[1], etc. Indexes beyond the array length are ignored by the model.image_urls, video_urls, and audio_urls can all appear in the same request, with the prompt referencing each via Image N / Video N / Audio N.list response contains quota.{used, limit, ttl_days} for persistent assets. Surface this on your dashboard so users know when they are close to the limit.Failed assets do not count toward quota, but they still clutter the list. Delete them explicitly to keep the view clean.