> ## Documentation Index
> Fetch the complete documentation index at: https://docs.aihubmix.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Doubao Private Virtual Portrait Assets

> Create virtual portrait asset groups without personal verification, upload images, and use asset:// references with Doubao Seedance video generation.

Private virtual portrait assets let you reference a virtual character in video generation without personal verification. This guide covers asset group creation, image upload, status checks, and video generation. Public virtual portrait catalogs are outside this guide.

## Prerequisites

* Set `AIHUBMIX_API_KEY` in the environment.
* Enable the target video model and virtual portrait asset capability for your account.
* Prepare a public HTTPS image URL that the model provider can fetch.

## Create a group

Send `kind: "virtual_portrait"` to `POST /ai/v1/asset-groups`. A successful request returns `201`; the group normally becomes `active` with authorization status `not_required`.

```bash theme={null}
BASE_URL="https://aihubmix.com"
curl --fail-with-body -sS -X POST "$BASE_URL/ai/v1/asset-groups" \
  -H "Authorization: Bearer $AIHUBMIX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"My virtual portrait","kind":"virtual_portrait"}' | jq
```

Virtual portrait groups do not use verification sessions. Save the returned group ID and use it in the next request.

## Upload and wait for an image

```bash theme={null}
curl --fail-with-body -sS -X POST "$BASE_URL/ai/v1/asset-groups/<group_id>/assets" \
  -H "Authorization: Bearer $AIHUBMIX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com/virtual-portrait.jpg","asset_type":"image","client_reference_id":"portrait-001"}' | jq
```

The response normally starts with `status=processing`. Query `GET /ai/v1/assets/<asset_id>` until the status is `active`. Do not use an asset while it is `creating`, `processing`, or `reconciling`. Use a public URL without login, private-network access, Base64 data, or embedded credentials. Images should be smaller than 30 MB, between 300 and 6000 pixels in both dimensions, and have an aspect ratio between 0.4 and 2.5.

## Generate a video

Use the AIHubMix asset ID as `asset://<asset_id>`:

```bash theme={null}
curl --fail-with-body -sS -X POST "$BASE_URL/ai/v1/videos" \
  -H "Authorization: Bearer $AIHUBMIX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"doubao-seedance-2-5-260628","prompt":"Make the virtual portrait smile naturally and turn slightly toward the camera.","input_references":[{"type":"image_url","url":"asset://<asset_id>"}]}' | jq
```

Query `GET /ai/v1/videos/<video_id>` until `status=completed`. Treat `in_progress` as pending and stop on `failed` or `cancelled`. Retrieve the completed video with `GET /ai/v1/videos/<video_id>/content`. Existing `/v1/videos` clients can place the reference in `extra_body.content` and retrieve content from `/v1/videos/<id>/content`.

## Errors and deletion

`asset_not_ready` means that the asset is not active yet. `asset_binding_mismatch` means that the request references incompatible private assets. `channel_pin_conflict` means that an explicit channel does not match the asset binding. An unavailable channel returns `channel_unavailable`.

When a virtual group is `creating` or `reconciling`, its creation result is unknown. The service keeps the local record and recovery locator and does not automatically delete it. Keep API keys in environment variables and never include them in logs or support requests.
