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

# 调用AI应用

> AI 应用三种调用模式（同步、异步轮询、WebHook 回调）及任务状态查询、取消与中断

## 调用模式总览

BizyAir 提供 3 种调用模式，通过 HTTP Header 切换，**无需修改请求体**：

| 模式      | 启用方式                                | 行为                                | 适用场景            |
| ------- | ----------------------------------- | --------------------------------- | --------------- |
| 同步阻塞    | 不设置任何特殊 Header                      | 连接保持打开直到任务完成，直接返回结果               | 短任务、简单调试        |
| 异步查询    | `X-BizyAir-Task-Async: enable`      | 立即返回 `request_id`，客户端轮询查结果        | 长任务、网络不稳定、无回调地址 |
| WebHook | `X-BizyAir-Task-WebHook-Url: <url>` | 立即返回 `request_id`，任务完成后主动 POST 回调 | 生产环境、高并发、长耗时任务  |

## 同步阻塞调用

默认模式。HTTP 连接保持打开直到任务完成。无需额外 Header。

```bash theme={null}
curl -X POST "https://api.bizyair.ai/v1/webapp/task/openapi/create" \
  -H "Authorization: Bearer $BIZYAIR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "web_app_id": 57302,
    "suppress_preview_output": false,
    "input_values": {
      "84:CLIPTextEncode.text": "a futuristic cityscape at sunset",
      "88:KSampler.seed": 354884000907176,
      "81:EmptySD3LatentImage.width": 1280,
      "81:EmptySD3LatentImage.height": 1280
    }
  }'
```

响应即任务结果，包含 `outputs[].object_url`。

<Note>
  同步模式需保持长连接，请确保 HTTP 客户端的**读取超时 (Read Timeout)** 至少 60 秒，避免任务执行过程中客户端主动断开。
</Note>

## 异步查询模式

启用方式：在请求头加入 `X-BizyAir-Task-Async: enable`。

### 步骤 1：发起异步任务，立即获取`request_id`

```bash theme={null}
curl -X POST "https://api.bizyair.ai/v1/webapp/task/openapi/create" \
  -H "Authorization: Bearer $BIZYAIR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "X-BizyAir-Task-Async: enable" \
  -d '{
    "web_app_id": 57302,
    "input_values": {
      "84:CLIPTextEncode.text": "a futuristic cityscape at sunset",
      "88:KSampler.seed": 354884000907176,
      "81:EmptySD3LatentImage.width": 1280,
      "81:EmptySD3LatentImage.height": 1280
    }
  }'
```

立即返回 `202 Accepted`：

```json theme={null}
{"request_id": "29f53793-12d3-4dd3-b2a8-4d9848e0c7da"}
```

### 步骤 2：轮询任务状态

```bash theme={null}
curl -X GET "https://api.bizyair.ai/v1/webapp/task/openapi/29f53793-12d3-4dd3-b2a8-4d9848e0c7da" \
  -H "Authorization: Bearer $BIZYAIR_API_KEY"
```

### 步骤 3：任务 Success 后获取结果

```bash theme={null}
curl -X GET "https://api.bizyair.ai/v1/webapp/task/openapi/29f53793-12d3-4dd3-b2a8-4d9848e0c7da/outputs" \
  -H "Authorization: Bearer $BIZYAIR_API_KEY"
```

### 完整 Python 示例

```python theme={null}
import time
import requests

API_KEY = "YOUR_API_KEY"
BASE = "https://api.bizyair.ai/v1/webapp/task/openapi"
HEADERS = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json",
    "X-BizyAir-Task-Async": "enable",
}

# 1. 提交任务
resp = requests.post(f"{BASE}/create", headers=HEADERS, json={
    "web_app_id": 57302,
    "input_values": {
        "84:CLIPTextEncode.text": "a futuristic cityscape at sunset",
        "88:KSampler.seed": 354884000907176,
        "81:EmptySD3LatentImage.width": 1280,
        "81:EmptySD3LatentImage.height": 1280,
    }
})
request_id = resp.json()["request_id"]
print(f"任务已提交: {request_id}")

# 2. 轮询状态
HEADERS.pop("X-BizyAir-Task-Async")
while True:
    r = requests.get(f"{BASE}/{request_id}", headers=HEADERS)
    status = r.json()["data"]["status"]
    print(f"当前状态: {status}")
    if status == "Success":
        break
    elif status in ("Failed", "Canceled"):
        print("任务失败或取消"); exit(1)
    time.sleep(2)

# 3. 获取结果
r = requests.get(f"{BASE}/{request_id}/outputs", headers=HEADERS)
for out in r.json()["data"]["outputs"]:
    print("结果 URL:", out["object_url"])
```

## WebHook 回调模式

启用方式：在请求头加入 `X-BizyAir-Task-WebHook-Url`。

### 步骤 1：发起带 WebHook 的任务

```bash theme={null}
curl -X POST "https://api.bizyair.ai/v1/webapp/task/openapi/create" \
  -H "Authorization: Bearer $BIZYAIR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "X-BizyAir-Task-WebHook-Url: https://your-server.com/api/callback" \
  -H "X-BizyAir-Task-Authorization: Bearer YOUR_CALLBACK_TOKEN" \
  -d '{
    "web_app_id": 35661,
    "input_values": {
      "1:EmptyLatentImage.width": "1024",
      "1:EmptyLatentImage.height": "1024",
      "2:BizyAir_BasicScheduler.steps": "20",
      "3:BizyAir_RandomNoise.noise_seed": "1",
      "4:BizyAirSiliconCloudLLMAPI.user_prompt": "小猫，梵高风格",
      "4:BizyAirSiliconCloudLLMAPI.system_prompt": "你是一个 stable diffusion prompt 专家..."
    }
  }'
```

立即返回 `202 Accepted` + `request_id`。

### 步骤 2：在回调端接收结果

任务完成后 BizyAir 会向你指定的 URL 发起 POST 请求：

* **Method**: `POST` - **Headers**: `Content-Type: application/json`、`User-Agent: Go-http-client/1.1`、以及你设置的 `X-BizyAir-Task-Authorization` 和其他 `X-BizyAir-Task-*` Header - **Body**: 包含完整任务结果

### 回调端 Node.js 示例

```javascript theme={null}
const express = require("express");
const app = express();
app.use(express.json());

const EXPECTED_TOKEN = process.env.CALLBACK_TOKEN;

app.post("/api/callback", (req, res) => {
  const auth = req.get("Authorization");
  if (EXPECTED_TOKEN) {
    const ok = auth?.startsWith("Bearer ") && auth.split(" ")[1] === EXPECTED_TOKEN;
    if (!ok) return res.status(401).json({ message: "invalid token" });
  }

  const payload = req.body;
  console.log("Received callback for request_id:", payload.request_id);

  res.status(200).json({ ok: true });
});

app.listen(3000, () => console.log("Callback server on :3000"));
```

<Warning>
  回调端**必须返回 HTTP 200 OK**。若返回非 200、超时或无响应，平台会按策略重试（约每 6 秒一次，最多 10 次）。单次回调超时时间约 10 秒。
</Warning>

## 如何选择调用模式

| 你的场景              | 推荐模式           | 理由               |
| ----------------- | -------------- | ---------------- |
| 本地脚本快速验证          | 同步阻塞           | 最简单，一次请求直接拿结果    |
| 短任务集成到后端          | 同步阻塞           | 短任务 HTTP 连接开销可接受 |
| 视频生成 / 3D 渲染（长任务） | WebHook        | 不阻塞服务、可大规模并行     |
| 客户端网络不稳定          | 异步查询           | 不依赖长连接，可按需轮询     |
| 批量并行上百个任务         | 异步查询 或 WebHook | 全部排队后慢慢回收        |
| 生产环境高可用           | WebHook        | 主动推送 + 重试机制      |

## 查询任务状态

获取任务的当前状态与详细元数据（排队信息、运行时长等）。

```bash theme={null}
curl -X GET "https://api.bizyair.ai/v1/webapp/task/openapi/{request_id}" \
  -H "Authorization: Bearer $BIZYAIR_API_KEY"
```

**响应字段**（`data` 内）：

| 字段                    | 类型             | 说明               |
| --------------------- | -------------- | ---------------- |
| `type`                | string         | 任务类型，如 `"API"`   |
| `status`              | string         | 任务状态枚举           |
| `created_at`          | string         | 创建时间（UTC+8）      |
| `updated_at`          | string         | 最后更新时间           |
| `executed_at`         | string         | 开始执行时间           |
| `ended_at`            | string \| null | 结束时间，未结束为 `null` |
| `expired_at`          | string         | 结果文件过期时间         |
| `inference_cost_time` | integer        | 推理耗时（秒）          |
| `queue_info`          | object \| null | 仅 `Queuing` 时出现  |

**状态枚举**：

| 状态值         | 含义              | 建议操作                        |
| ----------- | --------------- | --------------------------- |
| `Queuing`   | 排队中，等待资源调度      | 继续轮询，间隔 1-3 秒               |
| `Preparing` | 准备中，正在加载模型 / 环境 | 继续轮询                        |
| `Running`   | 运行中             | 继续轮询                        |
| `Success`   | 成功              | **停止轮询**，获取结果               |
| `Failed`    | 失败              | **停止轮询**，检查 `error_message` |
| `Canceled`  | 已取消             | **停止轮询**                    |

## 查询任务结果

获取**已完成任务**的产出物（`object_url` 等）。

```bash theme={null}
curl -X GET "https://api.bizyair.ai/v1/webapp/task/openapi/{request_id}/outputs" \
  -H "Authorization: Bearer $BIZYAIR_API_KEY"
```

**响应示例**：

```json theme={null}
{
  "code": 20000,
  "message": "Ok",
  "status": true,
  "data": {
    "request_id": "29f53793-12d3-4dd3-b2a8-4d9848e0c7da",
    "status": "Success",
    "outputs": [
      {
        "object_url": "https://storage.bizyair.ai/outputs/xxx.png",
        "output_ext": ".png",
        "cost_time": 10657,
        "audit_status": 2,
        "error_type": "NOT_ERROR"
      }
    ]
  }
}
```

**`outputs[].` 字段说明**：

| 字段             | 类型      | 说明                                       |
| -------------- | ------- | ---------------------------------------- |
| `object_url`   | string  | 结果文件下载 URL                               |
| `output_ext`   | string  | 文件扩展名（含 `.`）                             |
| `cost_time`    | integer | 从任务开始到产出此结果的耗时（毫秒）                       |
| `audit_status` | integer | 审核状态：`1` 未审核 / `2` 通过 / `3` 不通过 / `4` 报错 |
| `error_type`   | string  | 失败时为具体错误码，成功为 `"NOT_ERROR"`              |
| `error_msg`    | string  | 失败时的详细原因（可选）                             |

## 取消任务

仅对**排队中**（`Queuing`）的任务生效，将其从队列移除。

```bash theme={null}
curl -X PUT "https://api.bizyair.ai/v1/webapp/task/openapi/{request_id}/cancel" \
  -H "Authorization: Bearer $BIZYAIR_API_KEY" \
  -H "Content-Type: application/json"
```

<Note>
  取消操作是幂等的，重复调用不会产生副作用。若任务已进入运行态，请改用中断任务。
</Note>

## 中断任务

仅对**运行中**（`Running`）的任务生效，强制停止。

```bash theme={null}
curl -X PUT "https://api.bizyair.ai/v1/webapp/task/openapi/{request_id}/interrupt" \
  -H "Authorization: Bearer $BIZYAIR_API_KEY" \
  -H "Content-Type: application/json"
```

<Warning>
  中断运行中的任务，**已执行部分仍会产生费用**。仅当任务处于 `Queuing` 时取消才不计费。
</Warning>

## 获取 AI 应用信息

您可以通过 `web_app_id` 获取任意您有权限访问的 AI 应用（WebApp）的元数据，包括应用名称、作者信息、封面以及调用该应用所需的全部输入节点定义（`input_nodes`）。

开发者可以借此**动态发现**应用的输入参数：`input_nodes` 中的 `variable_name` 与「调用 AI 应用」接口请求体里 `input_values` 的 key 一一对应，因此非常适合 DIY 制作插件。插件可先请求本接口拿到输入项，再自动渲染表单并构造调用请求。

### 接口地址

```text theme={null}
GET https://meta.bizyair.ai/v1/webapp/{web_app_id}/detail
```

`{web_app_id}` 即应用 ID，与应用详情页 URL 中的数字 ID、以及调用 AI 应用接口请求体中的 `web_app_id` 相同。公开应用无需额外鉴权即可访问；应用不存在或无访问权限时将返回 404。

### 请求示例

```bash theme={null}
curl -X GET "https://meta.bizyair.ai/v1/webapp/57302/detail"
```

### 响应示例

```json theme={null}
{
  "code": 20000,
  "message": "Ok",
  "status": true,
  "data": {
    "id": 57302,
    "name": "Anima_HiresFix_1.5x Refinement",
    "user_id": "01kwv421t34pg5xtyrtbsvb3t7",
    "nick_name": "Gugugaga",
    "user_avatar": "https://storage.bizyair.ai/users/01kwv421t34pg5xtyrtbsvb3t7/...webp",
    "user_description": "Happy everyday",
    "base_model": "Anima",
    "description": "About $0.03 per run",
    "original_user_id": "01kwv421t34pg5xtyrtbsvb3t7",
    "created_at": "2026-08-05T10:10:55Z",
    "cover_urls": [
      "https://storage.bizyair.ai/img/20260805/431c5578-..._1536_1536.png"
    ],
    "counter": {
      "used_count": 14,
      "liked_count": 1
    },
    "input_nodes": [
      {
        "id": 37986,
        "node_id": 5,
        "node_name": "Positive Prompt",
        "node_type": "CLIPTextEncode",
        "field_name": "text",
        "field_type": "customtext",
        "field_options": "{\"hideOnZoom\":true,\"minNodeSize\":[400,200]}",
        "field_label": "Positive Prompt",
        "field_value": "masterpiece, best quality, ...",
        "variable_name": "5:CLIPTextEncode.text"
      }
    ],
    "source": "others",
    "ref_bizy_model_id": 56210
  }
}
```

`input_nodes` 包含该应用的全部输入节点，实际响应中可能有多个；示例省略了部分字段值。

### 响应字段说明

`data` 内字段：

| 字段                   | 类型        | 说明                                         |
| -------------------- | --------- | ------------------------------------------ |
| id                   | integer   | 应用 ID（web\_app\_id）                        |
| name                 | string    | 应用名称                                       |
| user\_id             | string    | 作者用户 ID                                    |
| nick\_name           | string    | 作者昵称                                       |
| user\_avatar         | string    | 作者头像 URL                                   |
| user\_description    | string    | 作者简介                                       |
| base\_model          | string    | 基础模型                                       |
| description          | string    | 应用简介（如单次运行成本）                              |
| original\_user\_id   | string    | 原作者用户 ID（Fork 时指向来源作者）                     |
| created\_at          | string    | 创建时间（ISO 8601，UTC）                         |
| cover\_urls          | string\[] | 封面图 URL 列表                                 |
| counter              | object    | 使用统计：`used_count`（使用次数）、`liked_count`（点赞数） |
| input\_nodes         | array     | 输入节点定义列表，用于构造调用参数                          |
| source               | string    | 应用来源，如 `"others"`                          |
| ref\_bizy\_model\_id | integer   | 关联的 BizyAir 模型 ID                          |

`input_nodes[]` 内字段：

| 字段             | 类型      | 说明                                                         |
| -------------- | ------- | ---------------------------------------------------------- |
| id             | integer | 输入字段 ID                                                    |
| node\_id       | integer | 节点 ID                                                      |
| node\_name     | string  | 节点名称                                                       |
| node\_type     | string  | 节点类型，如 `CLIPTextEncode`                                    |
| field\_name    | string  | 字段名                                                        |
| field\_type    | string  | 字段类型，如 `customtext`                                        |
| field\_options | string  | 节点配置（JSON 字符串）                                             |
| field\_label   | string  | 字段展示名，可用于渲染表单标签                                            |
| field\_value   | string  | 字段默认值                                                      |
| variable\_name | string  | 变量名，即调用应用时 `input_values` 的 key（如 `5:CLIPTextEncode.text`） |
| sort           | integer | 排序（可选）                                                     |

### 错误响应

应用不存在或无访问权限时返回 HTTP 404：

```json theme={null}
{
  "code": 20230,
  "message": "Resource version not found.",
  "data": null
}
```
