Assets API
The Assets API is used to create and manage portrait material assets, which can be used as reference images for video generation models such as Seedance.
Version Overview
| Version | Base URL | Authentication | Notes |
|---|---|---|---|
| Domestic (CN) | https://open.volcengineapi.com | AK/SK Signature | Volcengine Ark Assets API |
| Global | https://api.agentsflare.com/byteplus/_unstable/open | Bearer Token | Agentsflare global node |
Domestic (CN) API
Basic Information
- Region:
cn-beijing - Service:
ark - Version:
2024-01-01 - Auth: Volcengine Access Key (AK/SK)
Image Requirements
Uploaded assets must meet the following criteria:
| Item | Requirement |
|---|---|
| Format | jpeg, png, webp, bmp, tiff, gif, heic/heif |
| Aspect ratio | Width/Height within (0.4, 2.5) |
| Dimensions | Each side within (300, 6000) px |
| File size | Less than 30 MB per image |
| Compliance | No unauthorized trademarks, no resemblance to real persons, no illegal content |
Rate Limits
| Endpoint | QPS per Account | Concurrency Note |
|---|---|---|
| CreateAssetGroup | 30 | Max 30 concurrent creation tasks |
| CreateAsset | 30 | Same as above |
| ListAssetGroups | 30 | — |
| ListAssets | 30 | — |
| GetAsset | 100 | — |
| GetAssetGroup | 100 | — |
| UpdateAsset | 30 | — |
| UpdateAssetGroup | 30 | — |
Core Endpoints
CreateAssetGroup
Create an Asset Group to manage assets for the same project or character.
POST /open/CreateAssetGroup
| Parameter | Required | Type | Description |
|---|---|---|---|
| Name | Yes | string | Group name, max 64 chars |
| Description | No | string | Group description, max 300 chars |
| GroupType | No | string | Group type, optional AIGC |
| ProjectName | No | string | Project name, default default |
Response
| Field | Type | Description |
|---|---|---|
| Id | string | Asset Group Id |
CreateAsset
Create an asset within a specified Asset Group.
POST /open/CreateAsset
| Parameter | Required | Type | Description |
|---|---|---|---|
| GroupId | Yes | string | Parent Asset Group Id |
| URL | Yes | string | Publicly accessible URL of the asset |
| Name | No | string | Asset name, max 64 chars |
| AssetType | Yes | string | Asset type, currently only Image |
| ProjectName | No | string | Project name, default default |
Response
| Field | Type | Description |
|---|---|---|
| Id | string | Asset Id |
GetAsset
Query a single asset. Use this to poll the preprocessing status.
POST /open/GetAsset
| Parameter | Required | Type | Description |
|---|---|---|---|
| Id | Yes | string | Asset Id |
| ProjectName | No | string | Project name, default default |
Response
| Field | Type | Description |
|---|---|---|
| Id | string | Asset Id |
| Name | string | Asset name |
| URL | string | Access URL (valid for 12 hours) |
| AssetType | string | Image |
| GroupId | string | Parent Group Id |
| Status | string | Active / Processing / Failed |
| Error | object | Error info (Code, Message) |
| CreateTime | string | Creation time |
| UpdateTime | string | Update time |
| ProjectName | string | Project name |
Other Management Endpoints
| Endpoint | Path | Description |
|---|---|---|
| ListAssetGroups | POST /open/ListAssetGroups | List asset groups with pagination and filters |
| ListAssets | POST /open/ListAssets | List assets, filterable by GroupId, Status, Name |
| GetAssetGroup | POST /open/GetAssetGroup | Get a single asset group |
| UpdateAssetGroup | POST /open/UpdateAssetGroup | Update group (Name, Description only) |
| UpdateAsset | POST /open/UpdateAsset | Update asset (Name only) |
Code Examples (Domestic)
The following demonstrates the full workflow: create group → upload asset → poll until Active.
# The domestic API requires AK/SK signature auth.
# It is recommended to call directly via the Python script below.
python3 << 'PYEOF'
import json, hmac, hashlib, datetime, urllib.request
AK = "<YOUR_AK>"
SK = "<YOUR_SK>"
REGION = "cn-beijing"
SERVICE = "ark"
HOST = "open.volcengineapi.com"
def sign_request(method, uri, body_dict):
body = json.dumps(body_dict, separators=(',', ':'), ensure_ascii=False)
now = datetime.datetime.utcnow()
x_date = now.strftime('%Y%m%dT%H%M%SZ')
date_stamp = now.strftime('%Y%m%d')
credential_scope = f"{date_stamp}/{REGION}/{SERVICE}/request"
body_hash = hashlib.sha256(body.encode('utf-8')).hexdigest()
canonical_headers = f"host:{HOST}\nx-date:{x_date}\n"
signed_headers = "host;x-date"
canonical_request = f"{method}\n{uri}\n\n{canonical_headers}\n{signed_headers}\n{body_hash}"
string_to_sign = f"HMAC-SHA256\n{x_date}\n{credential_scope}\n{hashlib.sha256(canonical_request.encode('utf-8')).hexdigest()}"
k_date = hmac.new(f"VolcEngine{SK}".encode('utf-8'), date_stamp.encode('utf-8'), hashlib.sha256).digest()
k_region = hmac.new(k_date, REGION.encode('utf-8'), hashlib.sha256).digest()
k_service = hmac.new(k_region, SERVICE.encode('utf-8'), hashlib.sha256).digest()
k_signing = hmac.new(k_service, b"request", hashlib.sha256).digest()
signature = hmac.new(k_signing, string_to_sign.encode('utf-8'), hashlib.sha256).hexdigest()
auth = f"HMAC-SHA256 Credential={AK}/{credential_scope}, SignedHeaders={signed_headers}, Signature={signature}"
req = urllib.request.Request(
f"https://{HOST}{uri}",
data=body.encode('utf-8'),
headers={
"Content-Type": "application/json",
"X-Date": x_date,
"Host": HOST,
"Authorization": auth
},
method=method
)
with urllib.request.urlopen(req) as resp:
return json.loads(resp.read().decode('utf-8'))
# 1. Create asset group
group_resp = sign_request("POST", "/open/CreateAssetGroup", {
"Name": "my-character-group",
"Description": "Character assets for Seedance",
"GroupType": "AIGC"
})
print("CreateAssetGroup:", json.dumps(group_resp, indent=2, ensure_ascii=False))
# 2. Create asset (replace with your actual URL)
asset_resp = sign_request("POST", "/open/CreateAsset", {
"GroupId": group_resp.get("Result", {}).get("Id", ""),
"URL": "https://example.com/your-image.png",
"AssetType": "Image",
"Name": "character-01"
})
print("CreateAsset:", json.dumps(asset_resp, indent=2, ensure_ascii=False))
# 3. Poll asset status
asset_id = asset_resp.get("Result", {}).get("Id", "")
import time
for _ in range(40):
time.sleep(3)
get_resp = sign_request("POST", "/open/GetAsset", {"Id": asset_id})
status = get_resp.get("Result", {}).get("Status", "")
print(f"Status: {status}")
if status == "Active":
print("Asset is ready:", json.dumps(get_resp, indent=2, ensure_ascii=False))
break
elif status == "Failed":
print("Asset processing failed")
break
PYEOFimport json
import hmac
import hashlib
import datetime
import time
import urllib.request
AK = "<YOUR_AK>"
SK = "<YOUR_SK>"
REGION = "cn-beijing"
SERVICE = "ark"
HOST = "open.volcengineapi.com"
def sign_request(method: str, uri: str, body_dict: dict) -> dict:
body = json.dumps(body_dict, separators=(',', ':'), ensure_ascii=False)
now = datetime.datetime.utcnow()
x_date = now.strftime('%Y%m%dT%H%M%SZ')
date_stamp = now.strftime('%Y%m%d')
credential_scope = f"{date_stamp}/{REGION}/{SERVICE}/request"
body_hash = hashlib.sha256(body.encode('utf-8')).hexdigest()
canonical_headers = f"host:{HOST}\nx-date:{x_date}\n"
signed_headers = "host;x-date"
canonical_request = (
f"{method}\n{uri}\n\n{canonical_headers}\n"
f"{signed_headers}\n{body_hash}"
)
string_to_sign = (
f"HMAC-SHA256\n{x_date}\n{credential_scope}\n"
f"{hashlib.sha256(canonical_request.encode('utf-8')).hexdigest()}"
)
k_date = hmac.new(
f"VolcEngine{SK}".encode('utf-8'),
date_stamp.encode('utf-8'), hashlib.sha256
).digest()
k_region = hmac.new(k_date, REGION.encode('utf-8'), hashlib.sha256).digest()
k_service = hmac.new(k_region, SERVICE.encode('utf-8'), hashlib.sha256).digest()
k_signing = hmac.new(k_service, b"request", hashlib.sha256).digest()
signature = hmac.new(
k_signing, string_to_sign.encode('utf-8'), hashlib.sha256
).hexdigest()
auth = (
f"HMAC-SHA256 Credential={AK}/{credential_scope}, "
f"SignedHeaders={signed_headers}, Signature={signature}"
)
req = urllib.request.Request(
f"https://{HOST}{uri}",
data=body.encode('utf-8'),
headers={
"Content-Type": "application/json",
"X-Date": x_date,
"Host": HOST,
"Authorization": auth,
},
method=method,
)
with urllib.request.urlopen(req) as resp:
return json.loads(resp.read().decode('utf-8'))
def create_asset_group(name: str, description: str = "") -> str:
resp = sign_request("POST", "/open/CreateAssetGroup", {
"Name": name,
"Description": description,
"GroupType": "AIGC",
})
return resp.get("Result", {}).get("Id", "")
def create_asset(group_id: str, image_url: str, name: str = "") -> str:
resp = sign_request("POST", "/open/CreateAsset", {
"GroupId": group_id,
"URL": image_url,
"AssetType": "Image",
"Name": name,
})
return resp.get("Result", {}).get("Id", "")
def poll_asset_active(asset_id: str, timeout_sec: int = 120, interval_sec: int = 3) -> dict:
deadline = time.time() + timeout_sec
while time.time() < deadline:
resp = sign_request("POST", "/open/GetAsset", {"Id": asset_id})
status = resp.get("Result", {}).get("Status", "")
if status == "Active":
return resp
if status == "Failed":
raise RuntimeError(f"Asset processing failed: {resp}")
time.sleep(interval_sec)
raise TimeoutError("Polling asset status timed out")
if __name__ == "__main__":
# 1. Create asset group
group_id = create_asset_group("my-character-group", "For Seedance video gen")
print(f"GroupId: {group_id}")
# 2. Upload asset
asset_id = create_asset(
group_id,
"https://example.com/your-image.png",
"character-01"
)
print(f"AssetId: {asset_id}")
# 3. Poll until ready
result = poll_asset_active(asset_id)
print("Asset ready:", json.dumps(result, indent=2, ensure_ascii=False))
# 4. Use in video generation API
asset_url = f"Asset://{asset_id}"
print(f"Use in video gen: {asset_url}")Using Assets in Video Generation
Once the asset status is Active, format its Id as Asset://<Asset_Id> and pass it as the image_url in video generation APIs such as Seedance 2.0:
{
"type": "image_url",
"image_url": {
"url": "Asset://Asset-2026********-*****"
},
"role": "reference_image"
}Global API
Basic Information
- Base URL:
https://api.agentsflare.com/byteplus/_unstable/open - Auth:
Authorization: Bearer <API_KEY> - Content-Type:
application/json
CreateAsset
Create a material asset.
POST /byteplus/_unstable/open/CreateAsset
| Parameter | Required | Type | Description |
|---|---|---|---|
| Name | No | string | Asset name |
| URL | Yes | string | Publicly accessible URL of the asset |
| AssetType | Yes | string | Asset type, currently only Image |
Response
| Field | Type | Description |
|---|---|---|
| Id | string | Asset Id |
| base_resp.status_code | int | 0 indicates success |
| base_resp.status_msg | string | Status message |
GetAsset
Query asset information.
POST /byteplus/_unstable/open/GetAsset
| Parameter | Required | Type | Description |
|---|---|---|---|
| Id | Yes | string | Asset Id |
Response
| Field | Type | Description |
|---|---|---|
| Id | string | Asset Id |
| Status | string | Active / Processing / Failed |
| AssetType | string | Image |
| Name | string | Asset name |
| URL | string | Access URL (valid for 12 hours) |
| CreateTime | string | Creation time |
| UpdateTime | string | Update time |
| base_resp.status_code | int | 0 indicates success |
| base_resp.status_msg | string | Status message |
Code Examples (Global)
# Create asset
export API_KEY="your_api_key"
curl -X POST "https://api.agentsflare.com/byteplus/_unstable/open/CreateAsset" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $API_KEY" \
-d '{
"Name": "test asset",
"URL": "https://static.example.com/character.png",
"AssetType": "Image"
}'
# Query asset status
curl -X POST "https://api.agentsflare.com/byteplus/_unstable/open/GetAsset" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $API_KEY" \
-d '{
"Id": "asset-20260602115008-vvd9q"
}'import time
import requests
API_KEY = "your_api_key"
BASE_URL = "https://api.agentsflare.com/byteplus/_unstable/open"
HEADERS = {
"Content-Type": "application/json",
"Authorization": f"Bearer {API_KEY}",
}
def create_asset(name: str, image_url: str) -> str:
resp = requests.post(
f"{BASE_URL}/CreateAsset",
headers=HEADERS,
json={"Name": name, "URL": image_url, "AssetType": "Image"},
)
resp.raise_for_status()
data = resp.json()
if data.get("base_resp", {}).get("status_code") != 0:
raise RuntimeError(f"CreateAsset failed: {data}")
return data["Id"]
def get_asset(asset_id: str) -> dict:
resp = requests.post(
f"{BASE_URL}/GetAsset",
headers=HEADERS,
json={"Id": asset_id},
)
resp.raise_for_status()
return resp.json()
def poll_asset_active(asset_id: str, timeout_sec: int = 120, interval_sec: int = 3) -> dict:
deadline = time.time() + timeout_sec
while time.time() < deadline:
data = get_asset(asset_id)
status = data.get("Status", "")
print(f"Asset status: {status}")
if status == "Active":
return data
if status == "Failed":
raise RuntimeError(f"Asset processing failed: {data}")
time.sleep(interval_sec)
raise TimeoutError("Polling asset status timed out")
if __name__ == "__main__":
asset_id = create_asset("test asset", "https://static.example.com/character.png")
print(f"Created asset: {asset_id}")
result = poll_asset_active(asset_id)
print("Asset ready:", result)