Asset library (virtual characters)
POST /v1/assets · GET /v1/assets · GET /v1/assets/{id} · DELETE /v1/assets/{id}
Seedance videos on the overseas line (-hw series) support a virtual-character asset library: upload a portrait image as an asset to get an asset://<asset ID>, then use it as a person / character reference in video generation requests so the character's face, outfit, and other features stay consistent across the generated video.
Org-private + isolated: the assets you upload belong only to your organization, and only you can reference them; another org cannot use your
asset://ID even if they obtain it, and listing only ever shows your own assets.Virtual characters only: the asset library accepts only synthetic / virtual characters; material must not resemble a real natural person (upstream reviews it and rejects anything that looks like a real person).
1. Upload an asset: POST /v1/assets
Two upload methods, pick one:
1.1 Method A: upload the image file directly (multipart/form-data, recommended)
| Field | Type | Required | Description |
|---|---|---|---|
file |
file | Yes | Image file. Formats jpeg / png / webp / bmp / tiff / gif / heic; aspect ratio (0.4, 2.5); width/height 300–6000px; < 30 MB. |
name |
string | No | Asset name for your own management (not used in generation). |
curl https://api.portal.aiin1.ai/v1/assets \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "file=@portrait.jpg" \
-F "name=hero-mei"1.2 Method B: provide a public image URL (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
source_url |
string | Yes | A publicly accessible http(s) image URL (upstream must be able to fetch it). |
name |
string | No | Asset name. |
curl https://api.portal.aiin1.ai/v1/assets \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "source_url": "https://example.com/portrait.jpg", "name": "hero-mei" }'1.3 Response
Upload is asynchronous preprocessing (upstream review + ingestion, typically ~10 seconds). The endpoint waits inline for a short while:
- Preprocessing done →
200,status: "active"(ready to use in generation immediately). - Still processing →
202,status: "processing"(poll via Query untilactivelater). - Review failed →
200,status: "failed", with afail_reason.
{
"id": "asset-20260722081357-abcde",
"asset": "asset://asset-20260722081357-abcde",
"status": "active",
"name": "hero-mei",
"asset_type": "Image"
}| Field | Description |
|---|---|
id |
Asset ID. |
asset |
The reference string you can paste straight into a video request's image_url / reference_image_urls. |
status |
processing / active / failed. Only active can be used in generation. |
Only an asset with
status=activecan be referenced in a video request; aprocessing/failedone is rejected by the video endpoint with 400.
2. Query an asset: GET /v1/assets/{id}
Look up a single asset by ID; if it is still processing, its latest status is refreshed once automatically.
curl https://api.portal.aiin1.ai/v1/assets/asset-20260722081357-abcde \
-H "Authorization: Bearer YOUR_API_KEY"{ "id": "asset-20260722081357-abcde", "asset": "asset://asset-20260722081357-abcde", "status": "active", "name": "hero-mei", "asset_type": "Image", "created_at": "2026-07-22T08:13:57+00:00" }An asset not belonging to your org returns 404.
3. List assets: GET /v1/assets
List all of your org's assets (excluding deleted ones), newest first.
curl https://api.portal.aiin1.ai/v1/assets \
-H "Authorization: Bearer YOUR_API_KEY"{
"object": "list",
"data": [
{ "id": "asset-20260722081357-abcde", "asset": "asset://asset-20260722081357-abcde", "status": "active", "name": "hero-mei", "asset_type": "Image", "created_at": "2026-07-22T08:13:57+00:00" }
]
}4. Delete an asset: DELETE /v1/assets/{id}
curl -X DELETE https://api.portal.aiin1.ai/v1/assets/asset-20260722081357-abcde \
-H "Authorization: Bearer YOUR_API_KEY"{ "id": "asset-20260722081357-abcde", "deleted": true }An asset not belonging to your org returns 404.
5. Using an asset in a video
Once you have an active asset://<id>, put it in a video generation request's image_url (single) or reference_image_urls (multiple). The model must be an overseas -hw line name, and refer to it in prompt by @Image1 / @Image2 index (do not write the asset ID):
curl https://api.portal.aiin1.ai/v1/videos \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "doubao-seedance-2-0-hw",
"prompt": "@Image1 portrait smiling and waving at the camera in a café, natural light",
"seconds": "5",
"size": "1280x720",
"reference_image_urls": ["asset://asset-20260722081357-abcde"]
}'6. Common errors
| HTTP | Scenario | Notes |
|---|---|---|
| 400 | Missing file / source_url |
You must provide one of the two. |
| 400 | Unsupported image type | Only jpeg / png / webp / bmp / tiff / gif / heic. |
| 400 | Video referenced an asset that isn't yours | asset:// must be an asset your org has uploaded and that is active; otherwise the video endpoint returns 400. |
| 401 | Invalid API key | Check the Authorization header. |
| 404 | Asset not found / not your org | The queried/deleted ID is wrong or not owned by your org. |
| 413 | Image too large | Each image must be < 30 MB. |
| 503 | Asset library unavailable | Your org doesn't have the overseas (-hw) line enabled, or storage is temporarily unavailable. |