## I. Getting Started

Complete these prerequisites before calling a BizyAir standard model API.

### 1. Register and Add Balance

Sign in or register for a BizyAir account and ensure that the paid balance is sufficient. **Standard model APIs use paid balance.**

### 2. Get an API Key

Move the cursor over the user avatar in the top-right corner and click **API Key** to obtain your key.

**Keep the API Key secure. Do not commit it to source control or print it in logs.**

## II. Submit a Request

You can now submit API requests.

### 1. Request Example

Set `BIZYAIR_API_KEY` in the runtime environment, then copy and run the example for your language.

Before running the request, you can adjust the parameters in the payload to generate the exact output you need.

Important: follow the parameter format and requirements in **2. Request Parameters** carefully.

```python
import os

import requests

api_key = os.environ["BIZYAIR_API_KEY"]
url = "https://api.bizyair.ai/v1/modelzoo/tasks/openapi/seedance-2-0-fast-official/reference-to-video"
headers = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {api_key}"
}
payload = {
  "prompt": "Using the reference figure, compose a midnight post-rain Tokyo runway walk. The figure emerges from neon haze, footsteps splashing on wet asphalt, puddles mirroring the neon skyline. Tracking shot with handheld breathing feel, background blurring into flowing color light streaks. Blade Runner aesthetics, deep blue-black, magenta, electric cyan, sustained low synthesizer pad throughout, one continuous shot.",
  "aspect_ratio": "16:9",
  "resolution": "720p",
  "duration": 15,
  "web_search": False,
  "generate_audio": True
}

response = requests.post(url, json=payload, headers=headers)
response.raise_for_status()
result = response.json()
if result.get("code") != 20000 or result.get("status") is not True:
    raise RuntimeError(result.get("message") or "BizyAir API request failed")
print(result)
```

If you add the header `X-Bizyair-Task-WebHook-Url: https://your-website/webhook` when submitting the request, the task will use asynchronous callback mode. When the task finishes, BizyAir sends a POST request with the task result to your URL. Example:

```python
import os

import requests

api_key = os.environ["BIZYAIR_API_KEY"]
webhook_url = os.environ["WEBHOOK_URL"]
webhook_authorization = os.environ["WEBHOOK_AUTHORIZATION"]
webhook_trace_id = os.environ["WEBHOOK_TRACE_ID"]
url = "https://api.bizyair.ai/v1/modelzoo/tasks/openapi/seedance-2-0-fast-official/reference-to-video"
headers = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {api_key}",
    "X-Bizyair-Task-WebHook-Url": webhook_url,
    "X-Bizyair-Task-Authorization": webhook_authorization,
    "X-Bizyair-Task-Trace-Id": webhook_trace_id
}
payload = {
  "prompt": "Using the reference figure, compose a midnight post-rain Tokyo runway walk. The figure emerges from neon haze, footsteps splashing on wet asphalt, puddles mirroring the neon skyline. Tracking shot with handheld breathing feel, background blurring into flowing color light streaks. Blade Runner aesthetics, deep blue-black, magenta, electric cyan, sustained low synthesizer pad throughout, one continuous shot.",
  "aspect_ratio": "16:9",
  "resolution": "720p",
  "duration": 15,
  "web_search": False,
  "generate_audio": True
}

response = requests.post(url, json=payload, headers=headers)
response.raise_for_status()
result = response.json()
if result.get("code") != 20000 or result.get("status") is not True:
    raise RuntimeError(result.get("message") or "BizyAir API request failed")
print(result)
```

The request body is the same whether or not a Webhook callback is configured. Pay special attention to these headers:

| Parameter | Type | Required | Description |
| :--- | :--- | :--- | :--- |
| X-Bizyair-Task-WebHook-Url | string | Optional | Callback URL that BizyAir calls when the task finishes. If omitted, no callback is sent; retrieve the result with the query endpoint in Section III. The callback must be an HTTP or HTTPS POST endpoint. BizyAir does not guarantee callback delivery for overseas endpoints. |
| X-Bizyair-Task-Authorization | string | Optional | If the callback endpoint requires authorization, place the credential here. It is the only header that gets rewritten: the `X-Bizyair-Task-` prefix is removed, so it arrives as `Authorization: ${YOUR_WEBHOOK_AUTHORIZATION}`. |
| X-Bizyair-Task-${HEADER_NAME} | string | Optional | Except for `X-Bizyair-Task-Authorization`, every header prefixed with `X-Bizyair-Task-` is copied into the callback request unchanged, prefix included, such as `X-Bizyair-Task-Trace-Id` in the example above. |

### 2. Request Parameters

Read **Request Parameters** below to refine your request. Following these parameter requirements improves the likelihood of a successful run.

| Parameter | Type | Required | Description |
| :--- | :--- | :--- | :--- |
| prompt | string | Required | Prompt |
| ref_images | string[] | Optional | Ref Images |
| ref_videos | string[] | Optional | Ref Videos |
| ref_audios | string[] | Optional | Ref Audios |
| aspect_ratio | string | Optional | ⟨bz_enum_json⟩["auto","16:9","9:16","4:3","3:4","1:1","21:9"]⟨/bz_enum_json⟩<br/>Aspect Ratio |
| resolution | string | Required | ⟨bz_enum_json⟩["480p","720p","1080p","4k"]⟨/bz_enum_json⟩<br/>Resolution |
| duration | number | Required | Value range: 4 ~ 15<br/>Duration |
| web_search | boolean | Optional | Web Search |
| generate_audio | boolean | Optional | Generate Audio |

> To protect sensitive business information such as prompt design, BizyAir supports masking specific fields in API call logs. Masked fields appear as `[Masked by caller]` in log queries without affecting execution or billing.
>
> **How to use it:** send `X-Bizyair-Log-Mask-Fields` in the request header and provide the fields to mask, separated by commas.
>
> ```http
> Content-Type: application/json
> Authorization: Bearer ${BIZYAIR_API_KEY}
> X-Bizyair-Log-Mask-Fields: prompt, ref_images
> ```

### 3. Response Example

After a successful submission, you receive a response similar to the following.

This is an **asynchronous task submission receipt**. It indicates that the request has been accepted and the task is queued for execution.

If you receive a different response, refer to **4. Response Fields** below for details.

```json
{
  "code": 20000,
  "message": "Ok",
  "status": true,
  "data": {
    "request_id": "4569bb94-1d30-417a-a987-9715de1e2633"
  }
}
```

### 4. Response Fields

Read the **Response Fields** section below for field meanings and possible values.

| Parameter | Type | Description |
| :--- | :--- | :--- |
| code | integer | Response code, 20000 indicates success. |
| message | string | Message about the API call itself. |
| status | boolean | Whether the API call succeeded. It is not the same field as the task-state string data.status. |
| data | object | Response data container. |
| data.request_id | string | Request ID for subsequent task status queries. |

## III. Query the Result

At this stage, use the generated **request_id** to check whether the task has finished and retrieve the final result.

### 1. Request Example

Set `BIZYAIR_API_KEY` in the runtime environment, and replace the sample `request_id` with the ID returned by the submit response.

```python
import os

import requests

api_key = os.environ["BIZYAIR_API_KEY"]
request_id = "${REQUEST_ID}"
url = f"https://api.bizyair.ai/v1/modelzoo/tasks/openapi/{request_id}"
headers = {
    "Authorization": f"Bearer {api_key}"
}

response = requests.get(url, headers=headers)
response.raise_for_status()
result = response.json()
if result.get("code") != 20000 or result.get("status") is not True:
    raise RuntimeError(result.get("message") or "BizyAir API request failed")
print(result)
```

### 2. Response Example

This is the final receipt returned by the BizyAir query endpoint after the task completes successfully and generates content.

It is the **final result** of the entire generation workflow. By examining this response, you can understand the outcome of every step above.

If you receive a different response, refer to **3. Response Fields** below for details.

```json
{
  "code": 20000,
  "message": "Ok",
  "status": true,
  "data": {
    "request_id": "4569bb94-1d30-417a-a987-9715de1e2633",
    "status": "Success",
    "message": null,
    "created_at": "2026-04-15T13:32:30Z",
    "executed_at": "2026-04-15T13:32:32Z",
    "ended_at": "2026-04-15T13:42:32Z",
    "outputs": {
      "videos": [
        "https://storage.bizyair.ai/outputs_examples/f42d73e6-8ac0-4d96-a2a3-1ab4146025ce.mp4"
      ]
    },
    "cost_times": {
      "total_cost_time": 600000,
      "inference_duration": 598000
    }
  }
}
```

### 3. Response Fields

Read the **Response Fields** section below for field meanings and possible values.

| Parameter | Type | Description |
| :--- | :--- | :--- |
| code | integer | Response code, 20000 indicates success. |
| message | string | Message about the API call itself; the reason a task failed is in data.message. |
| status | boolean | Whether the API call succeeded. It is not the same field as the task-state string data.status. |
| data | object | Response data container. |
| data.request_id | string | Request ID for subsequent task status queries. |
| data.status | string | Task status. Confirmed terminal states are Success and Failed; continue querying for other states. |
| data.message | string or null | Error details for Failed tasks; null or omitted for other states. |
| data.created_at | string | Task creation time in ISO 8601 UTC, e.g. 2026-09-07T07:34:56Z. |
| data.executed_at | string | Task execution start time in ISO 8601 UTC. |
| data.ended_at | string | Task end time in ISO 8601 UTC; some Failed responses omit this field. |
| data.outputs | object | Output object; an empty object {} while incomplete or when no output exists. |
| data.outputs.videos | string[] | Video outputs. Each URL is a downloadable file link (CDN URL). |
| data.cost_times | object | Timing object; an empty object {} before completion or when timing is unavailable. |
| data.cost_times.total_cost_time | integer | Total task duration in milliseconds. Returned after the task completes. |
| data.cost_times.inference_duration | integer | Model inference duration in milliseconds. Returned after the task completes. |

> Note: output URLs are CDN download links and are not guaranteed to stay available. Copy the files to your own storage soon after the task completes.

### 4. Webhook Callback

If you specify a Webhook callback URL with the `X-Bizyair-Task-WebHook-Url` header when creating the task, BizyAir sends a callback notification to that address when the task finishes.

When the task succeeds:

```json
{
  "code": 20000,
  "message": "Ok",
  "status": true,
  "data": {
    "request_id": "6b88a97e-76e8-480a-bae7-a6f7f37b4e97",
    "status": "Success",
    "message": null,
    "created_at": "2026-05-22T17:14:07Z",
    "executed_at": "2026-05-22T17:14:07Z",
    "ended_at": "2026-05-22T17:14:44Z",
    "outputs": {
      "videos": [
        "https://storage.bizyair.ai/outputs_examples/f42d73e6-8ac0-4d96-a2a3-1ab4146025ce.mp4"
      ]
    },
    "cost_times": {
      "total_cost_time": 36815,
      "inference_duration": 36090
    }
  }
}
```

When the task fails:

```json
{
  "code": 20000,
  "message": "Ok",
  "status": true,
  "data": {
    "request_id": "ee8f5246-77ff-4df7-af62-7c55f311bcb2",
    "status": "Failed",
    "message": "Third-party api response error. No image generated.",
    "created_at": "2026-05-25T13:13:04Z",
    "executed_at": "2026-05-25T13:13:04Z",
    "ended_at": "2026-05-25T13:13:06Z",
    "outputs": {
      "texts": [
        "Sorry, I can't provide an image for this kind of content."
      ]
    },
    "cost_times": {
      "total_cost_time": 1930
    }
  }
}
```

Refer to **Response Fields** above for the meaning and value range of each field.

## IV. File Upload

Use this workflow to upload image, audio, or video resources to the BizyAir server.

Uploaded files can then be referenced as input resources in your tasks: pass the returned URL to this endpoint's media parameter `ref_images`.

Note: upload credentials come from `https://api.bizyair.ai/v1`, while committing and listing input resources use the metadata service at `https://meta.bizyair.ai/v1`. The different hosts are expected.

### 1. Get Upload Credentials and Parameters

Call the upload-token endpoint. The server returns the OSS information and temporary STS credentials required for the upload.

```python
import os

import requests

api_key = os.environ["BIZYAIR_API_KEY"]
url = "https://api.bizyair.ai/v1/upload/token"
params = {
    "file_name": "example.webp",
    "file_type": "inputs_temp"
}
headers = {
    "Authorization": f"Bearer {api_key}"
}

response = requests.get(url, params=params, headers=headers)
response.raise_for_status()
result = response.json()
if result.get("code") != 20000 or result.get("status") is not True:
    raise RuntimeError(result.get("message") or "BizyAir API request failed")
print(result)
```

The credential response contains `data.file.object_key`, temporary STS credentials, and `data.storage`:

```json
{
  "code": 20000,
  "message": "Ok",
  "status": true,
  "data": {
    "file": {
      "object_key": "inputs_temp/20260907/example.png",
      "access_key_id": "STS.xxxx",
      "access_key_secret": "xxxx",
      "expiration": "2026-09-07T08:00:00Z",
      "security_token": "xxxx"
    },
    "storage": {
      "endpoint": "https://example-oss-endpoint",
      "bucket": "example-bucket",
      "region": "oss-example-region"
    },
    "access_url": "https://storage.example/inputs_temp/20260907/example.png"
  }
}
```

### 2. Upload to Alibaba Cloud OSS

Use the returned `endpoint`, `bucket`, `region`, `object_key`, and STS credentials to upload a local file to OSS. For more details, see [Alibaba Cloud OSS simple upload](https://help.aliyun.com/zh/oss/user-guide/simple-upload) and the [BizyAir upload guide](https://docs.bizyair.ai/en/api/upload-tutorial.html#oss).

```python
# pip install alibabacloud-oss-v2
import os
import alibabacloud_oss_v2 as oss

def upload_to_oss(region, endpoint, bucket, object_key, file_path, access_key_id, access_key_secret, security_token):
    os.environ["ALIBABA_CLOUD_ACCESS_KEY_ID"] = access_key_id
    os.environ["ALIBABA_CLOUD_ACCESS_KEY_SECRET"] = access_key_secret
    os.environ["ALIBABA_CLOUD_SECURITY_TOKEN"] = security_token

    cfg = oss.config.load_default()
    cfg.credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()
    cfg.region = region[4:] if region.startswith("oss-") else region
    cfg.endpoint = endpoint

    client = oss.Client(cfg)
    return client.put_object_from_file(
        oss.PutObjectRequest(bucket=bucket, key=object_key),
        file_path,
    )
```

Notes:

- Some SDKs require removing the `oss-` prefix from `region`, for example `oss-us-east-1` becomes `us-east-1`.
- It is recommended to set both `region` and `endpoint`, with the returned `endpoint` taking precedence.

### 3. Commit the Input Resource

After the OSS upload succeeds, commit the uploaded input resource so it can be referenced directly in subsequent tasks.

```python
import os

import requests

api_key = os.environ["BIZYAIR_API_KEY"]
url = "https://meta.bizyair.ai/v1/input_resource/commit"
payload = {
    "name": "example.webp",
    "object_key": "inputs_temp/20250911/abc123.webp"
}
headers = {
    "Authorization": f"Bearer {api_key}",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)
response.raise_for_status()
result = response.json()
if result.get("code") != 20000 or result.get("status") is not True:
    raise RuntimeError(result.get("message") or "BizyAir API request failed")
print(result)
```

The commit request must reuse `data.file.object_key` from the credential response. After commit succeeds, pass the returned `data.url` to this endpoint's media parameter `ref_images`:

```json
{
  "code": 20000,
  "message": "Ok",
  "status": true,
  "data": {
    "id": 1711,
    "name": "example.png",
    "ext": ".png",
    "url": "https://storage.example/inputs/20260907/example.png"
  }
}
```

### 4. Query the Inputs List (Optional)

You can query your inputs list to verify the uploaded content.

```python
import os

import requests

api_key = os.environ["BIZYAIR_API_KEY"]
url = "https://meta.bizyair.ai/v1/input_resource"
params = {
    "current": 1,
    "page_size": 20
}
headers = {
    "Authorization": f"Bearer {api_key}"
}

response = requests.get(url, params=params, headers=headers)
response.raise_for_status()
result = response.json()
if result.get("code") != 20000 or result.get("status") is not True:
    raise RuntimeError(result.get("message") or "BizyAir API request failed")
print(result)
```