> ## Documentation Index
> Fetch the complete documentation index at: https://heygen-1fa696a7.mintlify.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Assets

> Upload, list, and manage images, audio, and video files via the HeyGen Assets API. Reference uploaded assets in any avatar video, translation, or lipsync.

Upload images, videos, audio, or PDFs to get an `asset_id` you can reference in other endpoints — like `POST /v3/video-agents`, `POST /v3/videos`, or `POST /v3/avatars`.

## Upload an Asset

```bash theme={null}
curl -X POST https://api.heygen.com/v3/assets \
  -H "x-api-key: YOUR_API_KEY" \
  -F "file=@./my-photo.png"
```

```json Response theme={null}
{
  "data": {
    "asset_id": "ast_abc123",
    "url": "https://files.heygen.com/asset/ast_abc123.png",
    "mime_type": "image/png",
    "size_bytes": 204800
  }
}
```

## Supported File Types

| Category | Formats   |
| -------- | --------- |
| Image    | PNG, JPEG |
| Video    | MP4, WebM |
| Audio    | MP3, WAV  |
| Document | PDF       |

Max file size: **32 MB**. MIME type is auto-detected from file bytes. For larger files, use the direct upload flow below.

## Direct Upload for Large Files

`POST /v3/assets` proxies file bytes through the API, which is why it's capped at 32 MB. For larger files, use the presigned direct upload flow — three required steps:

1. [`POST /v3/assets/direct-uploads`](/reference/create-asset-upload) with `filename`, `content_type`, and exact `size_bytes` → returns `asset_id`, a presigned `upload_url`, and `upload_headers`.
2. `PUT` the raw file bytes to `upload_url`, sending `upload_headers` verbatim, before the URL expires (`expires_in_seconds`).
3. [`POST /v3/assets/{asset_id}/complete`](/reference/complete-asset-upload) to finalize. Idempotent. The `asset_id` is not usable until this step succeeds.

```bash theme={null}
# 1. Initialize
curl -X POST https://api.heygen.com/v3/assets/direct-uploads \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filename": "footage.mp4", "content_type": "video/mp4", "size_bytes": 134217728}'

# 2. PUT the file bytes to the returned upload_url (with upload_headers)
curl -X PUT "UPLOAD_URL" -H "Content-Type: video/mp4" --upload-file ./footage.mp4

# 3. Complete
curl -X POST https://api.heygen.com/v3/assets/ASSET_ID/complete \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'
```

The per-upload cap for this flow is returned as `max_bytes` in the initialize response. See [Upload Assets](/docs/upload-assets#upload-large-files-direct-upload) for full examples in Python and Node.js.

## Using Assets

Once uploaded, reference the `asset_id` anywhere the API accepts asset inputs:

```json theme={null}
// In POST /v3/video-agents (file attachments)
{
  "prompt": "Explain this diagram",
  "files": [{ "type": "asset_id", "asset_id": "ast_abc123" }]
}
```

```json theme={null}
// In POST /v3/avatars (photo avatar)
{
  "type": "photo",
  "name": "My Avatar",
  "file": { "type": "asset_id", "asset_id": "ast_abc123" }
}
```

Anywhere that accepts an asset also accepts a direct URL (`{"type": "url", "url": "https://..."}`) or base64 (`{"type": "base64", "media_type": "image/png", "data": "..."}`). The 32 MB per-file limit applies to URL inputs too — for larger files, upload via the direct upload flow and pass the `asset_id`. Use `asset_id` when you need to reuse the same file across multiple requests.
