Skip to content

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

VersionBase URLAuthenticationNotes
Domestic (CN)https://open.volcengineapi.comAK/SK SignatureVolcengine Ark Assets API
Globalhttps://api.agentsflare.com/byteplus/_unstable/openBearer TokenAgentsflare global node

Domestic (CN) API

Basic Information

Image Requirements

Uploaded assets must meet the following criteria:

ItemRequirement
Formatjpeg, png, webp, bmp, tiff, gif, heic/heif
Aspect ratioWidth/Height within (0.4, 2.5)
DimensionsEach side within (300, 6000) px
File sizeLess than 30 MB per image
ComplianceNo unauthorized trademarks, no resemblance to real persons, no illegal content

Rate Limits

EndpointQPS per AccountConcurrency Note
CreateAssetGroup30Max 30 concurrent creation tasks
CreateAsset30Same as above
ListAssetGroups30
ListAssets30
GetAsset100
GetAssetGroup100
UpdateAsset30
UpdateAssetGroup30

Core Endpoints

CreateAssetGroup

Create an Asset Group to manage assets for the same project or character.

POST /open/CreateAssetGroup

ParameterRequiredTypeDescription
NameYesstringGroup name, max 64 chars
DescriptionNostringGroup description, max 300 chars
GroupTypeNostringGroup type, optional AIGC
ProjectNameNostringProject name, default default

Response

FieldTypeDescription
IdstringAsset Group Id

CreateAsset

Create an asset within a specified Asset Group.

POST /open/CreateAsset

ParameterRequiredTypeDescription
GroupIdYesstringParent Asset Group Id
URLYesstringPublicly accessible URL of the asset
NameNostringAsset name, max 64 chars
AssetTypeYesstringAsset type, currently only Image
ProjectNameNostringProject name, default default

Response

FieldTypeDescription
IdstringAsset Id

GetAsset

Query a single asset. Use this to poll the preprocessing status.

POST /open/GetAsset

ParameterRequiredTypeDescription
IdYesstringAsset Id
ProjectNameNostringProject name, default default

Response

FieldTypeDescription
IdstringAsset Id
NamestringAsset name
URLstringAccess URL (valid for 12 hours)
AssetTypestringImage
GroupIdstringParent Group Id
StatusstringActive / Processing / Failed
ErrorobjectError info (Code, Message)
CreateTimestringCreation time
UpdateTimestringUpdate time
ProjectNamestringProject name

Other Management Endpoints

EndpointPathDescription
ListAssetGroupsPOST /open/ListAssetGroupsList asset groups with pagination and filters
ListAssetsPOST /open/ListAssetsList assets, filterable by GroupId, Status, Name
GetAssetGroupPOST /open/GetAssetGroupGet a single asset group
UpdateAssetGroupPOST /open/UpdateAssetGroupUpdate group (Name, Description only)
UpdateAssetPOST /open/UpdateAssetUpdate asset (Name only)

Code Examples (Domestic)

The following demonstrates the full workflow: create group → upload asset → poll until Active.

bash
# 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
PYEOF
python
import 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:

json
{
  "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

ParameterRequiredTypeDescription
NameNostringAsset name
URLYesstringPublicly accessible URL of the asset
AssetTypeYesstringAsset type, currently only Image

Response

FieldTypeDescription
IdstringAsset Id
base_resp.status_codeint0 indicates success
base_resp.status_msgstringStatus message

GetAsset

Query asset information.

POST /byteplus/_unstable/open/GetAsset

ParameterRequiredTypeDescription
IdYesstringAsset Id

Response

FieldTypeDescription
IdstringAsset Id
StatusstringActive / Processing / Failed
AssetTypestringImage
NamestringAsset name
URLstringAccess URL (valid for 12 hours)
CreateTimestringCreation time
UpdateTimestringUpdate time
base_resp.status_codeint0 indicates success
base_resp.status_msgstringStatus message

Code Examples (Global)

bash
# 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"
  }'
python
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)

This documentation is licensed under CC BY-SA 4.0.