# MediaAsync 外部接入文档

MediaAsync 是异步媒体生成服务。调用方通过公开 `model` 提交图片、视频或图片工具任务，服务立即返回任务 `id`，后台 Worker 完成 Provider 调用、轮询、产物上传后，再通过查询接口返回最终产物 URL。

## 快速开始

默认本地服务地址：

```text
https://media.kitt.tools
```

所有业务 API 都需要 Bearer token。API token 由服务管理员在 Admin 中创建，形如 `sk_...`。

```text
Authorization: Bearer sk_...
```

`sk_...` 只用于访问 MediaAsync，不是上游 Provider key。创建任务默认使用调用方自带 Provider key 的 BYOK/OpenAI-compatible 路由：

```text
X-MediaAsync-Provider-Key: upstream-provider-key
X-MediaAsync-Provider-Base-URL: https://api.example.com/v1
```

`X-MediaAsync-Provider-Base-URL` 可省略，省略时使用服务端 `[byok].base_url`。调用方传入的 base URL 必须是公网 HTTP(S) 地址；`localhost`、私网 IP、Docker/container 主机名、单标签主机名、`.local`、`.internal` 等内网目标都会被拒绝。

最小图片生成请求：

```bash
curl -sS https://media.kitt.tools/v1/images/generations \
  -H "Authorization: Bearer sk_..." \
  -H "X-MediaAsync-Provider-Key: upstream-provider-key" \
  -H "X-MediaAsync-Provider-Base-URL: https://api.example.com/v1" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-image-2",
    "prompt": "a small ceramic teapot on a walnut table",
    "size": "1024x1024",
    "output_format": "png"
  }'
```

创建成功会返回异步任务：

```json
{
  "id": "0f0d4e89-...",
  "object": "image.generation",
  "status": "queued"
}
```

随后轮询任务：

```bash
curl -sS https://media.kitt.tools/v1/images/0f0d4e89-... \
  -H "Authorization: Bearer sk_..."
```

## 接入流程

1. 调用 `GET /v1/models/catalog` 获取可用模型、能力和价格信息。
2. 选择路由：默认 BYOK/OpenAI-compatible 需要传上游 Provider key；托管渠道需要传 `X-MediaAsync-Route: managed`。
3. 选择支持目标能力的公开 `model`，不要传内部 `format` 或渠道 ID。
4. 调用对应的创建接口，拿到任务 `id`。
5. 使用单任务查询或批量查询轮询状态。
6. 当 `status` 为 `succeeded` 时，从 `data[].url` 获取产物。
7. 当 `status` 为 `failed` 或 `canceled` 时，根据业务需要重试或结束。

## 公共页面

| 页面 | 说明 |
| --- | --- |
| `/usage.html` | 本文档的 HTML 渲染版 |
| `/usage.md` | 本文档的 Markdown 原文 |
| `/docs` | Swagger UI |
| `/api-docs/openapi.json` | OpenAPI JSON |
| `/playground.html` | 浏览器调试页面 |
| `/dashboard.html` | 浏览器监控页面 |

`/playground.html` 和 `/dashboard.html` 是公开页面外壳，页面内实际调用业务 API 时仍需要 `sk_...` token。

## 认证

所有创建、查询、取消、重试、批量查询、模型目录和 quote 接口都使用：

```text
Authorization: Bearer sk_...
```

缺失或无效 token 返回：

```json
{
  "error": {
    "message": "missing or invalid API key"
  }
}
```

Bearer token 只能访问同一个 API key 创建的任务。不同 key 创建的任务在查询、取消、重试和批量查询中不可见。

## 上游路由

创建任务有两套上游路由：

| 路由 | 请求头 | Provider key 来源 | 说明 |
| --- | --- | --- | --- |
| BYOK/OpenAI-compatible | 不传 `X-MediaAsync-Route`，或传 `X-MediaAsync-Route: byok` | 调用方请求头 `X-MediaAsync-Provider-Key` | 默认路由。适合调用方把价格、充值和额度放在自己的上游 Provider 账户里，MediaAsync 只负责异步任务和产物托管 |
| Managed | `X-MediaAsync-Route: managed` | MediaAsync Admin 托管渠道 | 适合使用服务方自有渠道、包月权益或更高成功率路由 |

BYOK 路由目前只支持 OpenAI-compatible 图片生成和图片编辑，即 `/v1/images/generations` 和 `/v1/images/edits`。请求必须包含：

```text
X-MediaAsync-Provider-Key: upstream-provider-key
```

如果服务端没有配置 `[byok].base_url`，请求还必须包含：

```text
X-MediaAsync-Provider-Base-URL: https://api.example.com/v1
```

托管渠道请求不要传 `X-MediaAsync-Provider-Key` 或 `X-MediaAsync-Provider-Base-URL`，否则会返回 `400`。Provider-compatible 入口、视频、图片工具和非 OpenAI-compatible 能力必须使用：

```text
X-MediaAsync-Route: managed
```

## 模型目录

### 简化模型列表

`GET /v1/models`

```bash
curl -sS https://media.kitt.tools/v1/models \
  -H "Authorization: Bearer sk_..."
```

响应：

```json
{
  "object": "list",
  "data": [
    {
      "id": "gpt-image-2",
      "object": "model",
      "created": 1778470000,
      "owned_by": "openai"
    }
  ]
}
```

### 完整模型目录

`GET /v1/models/catalog`

```bash
curl -sS https://media.kitt.tools/v1/models/catalog \
  -H "Authorization: Bearer sk_..."
```

响应重点字段：

```json
{
  "object": "list",
  "data": [
    {
      "id": "gpt-image-2",
      "object": "model",
      "owned_by": "openai",
      "display_name": "GPT Image 2",
      "task_type": "image.generate",
      "task_types": ["image.generate", "image.edit"],
      "capabilities": { "image": true, "provider": "openai" },
      "channels": [
        {
          "channel_id": "openai-main",
          "provider_format": "openai",
          "provider_model": "gpt-image-2",
          "enabled": true
        }
      ],
      "pricing_profiles": [
        {
          "id": "default-gpt-image-2-image-generate",
          "version": 1,
          "channel_id": null,
          "task_type": "image.generate",
          "currency": "usd",
          "rules": [{ "type": "per_image", "micro_usd_per_image": 40000 }],
          "enabled": true
        }
      ]
    }
  ]
}
```

调用方只需要传公开 `model`。模型绑定、真实 Provider、Provider model、渠道优先级和重试策略由 MediaAsync 内部决定。

## 通用响应

### 创建任务响应

```json
{
  "id": "task-id",
  "object": "image.generation",
  "status": "queued"
}
```

`object` 随任务类型变化，常见值包括：

| 任务 | object |
| --- | --- |
| 图片生成 | `image.generation` |
| 图片编辑 | `image.edit` |
| 图片放大 | `image.upscale` |
| 区域擦除 | `image.erase_region` |
| 去背景 | `image.remove_background` |
| 矢量化 | `image.vectorize` |
| 视频生成 | `video` |

### 查询任务响应

轮询接口返回的是任务当前快照。处理中时 `data` 通常为空数组；成功后 `data` 是产物数组；失败或取消时 `data` 通常为空，错误信息在 `error`。

处理中示例：

```json
{
  "id": "task-id",
  "object": "image.generation",
  "status": "running",
  "stage": "provider_processing",
  "progress": 40,
  "model": "gpt-image-2",
  "task_type": "image.generate",
  "data": [],
  "error": null,
  "created_at": 1778470000,
  "updated_at": 1778470010,
  "completed_at": null
}
```

成功示例：

```json
{
  "id": "task-id",
  "object": "image.edit",
  "status": "succeeded",
  "stage": "succeeded",
  "progress": 100,
  "model": "gpt-image-2",
  "task_type": "image.edit",
  "data": [
    {
      "id": "artifact-id",
      "object": "image",
      "url": "https://cdn.example.com/result.png",
      "content_type": "image/png",
      "size_bytes": 123456
    }
  ],
  "error": null,
  "created_at": 1778470000,
  "updated_at": 1778470030,
  "completed_at": 1778470030
}
```

失败示例：

```json
{
  "id": "task-id",
  "object": "image.generation",
  "status": "failed",
  "stage": "failed",
  "progress": 100,
  "model": "gpt-image-2",
  "task_type": "image.generate",
  "data": [],
  "error": {
    "message": "provider error: upstream request failed"
  },
  "created_at": 1778470000,
  "updated_at": 1778470030,
  "completed_at": 1778470030
}
```

响应字段：

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `id` | string | MediaAsync 任务 ID，创建接口返回的同一个值 |
| `object` | string | 响应对象类型，图片任务如 `image.generation`、`image.edit`，视频任务为 `video` |
| `status` | string | 任务总状态 |
| `stage` | string | 当前处理阶段 |
| `progress` | number | 0 到 100 的进度估计；不同 Provider 粒度可能不同 |
| `model` | string/null | 调用方提交的公开模型 ID |
| `task_type` | string | 任务类型，如 `image.generate`、`image.edit`、`video.generate` |
| `data` | array | 产物数组。任务未完成、失败或取消时通常为空 |
| `error` | object/null | 失败原因。成功和处理中为 `null` |
| `created_at` | number | Unix timestamp，秒 |
| `updated_at` | number | Unix timestamp，秒 |
| `completed_at` | number/null | 完成、失败或取消时间；未结束时为 `null` |

`data` 数组里的每一项是一个 artifact：

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `id` | string | 产物 ID |
| `object` | string | 产物媒体类型。常见为 `image`、`video`、`audio` |
| `url` | string | 可访问的产物 URL。调用方应保存或转存这个 URL |
| `content_type` | string | MIME 类型，如 `image/png`、`image/webp`、`image/svg+xml`、`video/mp4` |
| `size_bytes` | number | 产物文件大小，单位 bytes |

常见 `data` 形态：

图片任务成功：

```json
"data": [
  {
    "id": "artifact-image-1",
    "object": "image",
    "url": "https://cdn.example.com/tasks/task-id/image/artifact.png",
    "content_type": "image/png",
    "size_bytes": 345678
  }
]
```

多图任务成功：

```json
"data": [
  {
    "id": "artifact-image-1",
    "object": "image",
    "url": "https://cdn.example.com/tasks/task-id/image/1.png",
    "content_type": "image/png",
    "size_bytes": 345678
  },
  {
    "id": "artifact-image-2",
    "object": "image",
    "url": "https://cdn.example.com/tasks/task-id/image/2.png",
    "content_type": "image/png",
    "size_bytes": 331024
  }
]
```

视频任务成功：

```json
"data": [
  {
    "id": "artifact-video-1",
    "object": "video",
    "url": "https://cdn.example.com/tasks/task-id/video/result.mp4",
    "content_type": "video/mp4",
    "size_bytes": 8923441
  }
]
```

矢量化任务成功时通常返回 SVG：

```json
"data": [
  {
    "id": "artifact-svg-1",
    "object": "image",
    "url": "https://cdn.example.com/tasks/task-id/image/result.svg",
    "content_type": "image/svg+xml",
    "size_bytes": 48210
  }
]
```

调用方判断产物类型时优先看 `content_type`。例如 `content_type` 为 `video/mp4` 时按视频处理，为 `image/svg+xml` 时按 SVG 文本/矢量图处理。

`status` 取值：

| status | 含义 |
| --- | --- |
| `queued` | 已入队，等待后台处理 |
| `running` | 正在提交、轮询或上传 |
| `succeeded` | 已完成，`data` 中包含产物 |
| `failed` | 失败，`error` 中包含失败信息 |
| `canceled` | 已取消 |

`stage` 取值：

| stage | 含义 |
| --- | --- |
| `queued` | 等待处理 |
| `channel_selecting` | 正在选择可用渠道 |
| `provider_submitting` | 正在提交 Provider |
| `provider_processing` | Provider 处理中 |
| `artifact_uploading` | 正在上传产物 |
| `succeeded` | 已成功 |
| `failed` | 已失败 |
| `canceled` | 已取消 |

## 图片生成

`POST /v1/images/generations`

`Content-Type: application/json`

默认 BYOK 路由需要传 `X-MediaAsync-Provider-Key`，也可传 `X-MediaAsync-Provider-Base-URL` 覆盖默认上游。BYOK 只支持这个图片生成接口和 `/v1/images/edits`。要改用 Admin 托管渠道，在请求头加 `X-MediaAsync-Route: managed`，且不要传 Provider key 相关请求头。

| 字段 | 必填 | 类型 | 说明 |
| --- | --- | --- | --- |
| `model` | 是 | string | 公开模型 ID |
| `prompt` | 是 | string | 图片提示词 |
| `size` | 否 | string | 如 `auto`、`1024x1024`、`1536x1024`、`1024x1536` |
| `n` | 否 | number | 图片数量，默认 1 |
| `quality` | 否 | string | 如 `auto`、`high`、`medium`、`low` |
| `background` | 否 | string | 如 `auto`、`opaque` 或 Provider 支持值 |
| `output_format` | 否 | string | `png`、`jpeg`、`webp` 等 |
| `output_compression` | 否 | number | 有损格式压缩比例 |
| `response_format` | 否 | string | Provider 支持时可传 `url` 或 `b64_json` |
| `user` | 否 | string | 上游调用方关联 ID |

示例：

```bash
curl -sS https://media.kitt.tools/v1/images/generations \
  -H "Authorization: Bearer sk_..." \
  -H "X-MediaAsync-Provider-Key: upstream-provider-key" \
  -H "X-MediaAsync-Provider-Base-URL: https://api.example.com/v1" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-image-2",
    "prompt": "a clean product photo of a tiny ceramic teapot",
    "size": "1024x1024",
    "output_format": "png"
  }'
```

## 图片编辑

`POST /v1/images/edits`

图片编辑支持 JSON 和 multipart form-data。

默认 BYOK 路由需要传 `X-MediaAsync-Provider-Key`，也可传 `X-MediaAsync-Provider-Base-URL` 覆盖默认上游。BYOK 只支持这个图片编辑接口和 `/v1/images/generations`。要改用 Admin 托管渠道，在请求头加 `X-MediaAsync-Route: managed`。

### JSON 请求

| 字段 | 必填 | 类型 | 说明 |
| --- | --- | --- | --- |
| `model` | 是 | string | 公开模型 ID，模型能力需包含 `image.edit` |
| `prompt` | 是 | string | 编辑指令 |
| `image` | 否 | image reference | 单张输入图；`image` 和 `images` 至少传一个 |
| `images` | 否 | image reference[] | 多张输入图 |
| `mask` | 否 | image reference | 可选 mask 图 |
| `size` | 否 | string | 输出尺寸 |
| `n` | 否 | number | 输出图片数量 |
| `quality` | 否 | string | 质量档位 |
| `background` | 否 | string | 背景策略 |
| `input_fidelity` | 否 | string | 输入保真策略 |
| `output_format` | 否 | string | `png`、`jpeg`、`webp` 等 |
| `response_format` | 否 | string | Provider 支持时可传 `url` 或 `b64_json` |
| `user` | 否 | string | 上游调用方关联 ID |

JSON 示例：

```bash
curl -sS https://media.kitt.tools/v1/images/edits \
  -H "Authorization: Bearer sk_..." \
  -H "X-MediaAsync-Provider-Key: upstream-provider-key" \
  -H "X-MediaAsync-Provider-Base-URL: https://api.example.com/v1" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-image-2",
    "prompt": "turn the sketch into a clean watercolor illustration",
    "image": {
      "filename": "source.png",
      "mime_type": "image/png",
      "data": "<base64-without-data-url-prefix>"
    },
    "size": "1024x1024",
    "output_format": "png"
  }'
```

### Multipart 请求

| 字段 | 必填 | 类型 | 说明 |
| --- | --- | --- | --- |
| `model` | 是 | text | 公开模型 ID |
| `prompt` | 是 | text | 编辑指令 |
| `image` | 是 | file | 输入图片，多图可重复传多个 `image` 字段 |
| `image[]` | 否 | file | 多图兼容写法 |
| `mask` | 否 | file | mask 图片 |
| `size` / `n` / `quality` / `background` / `output_format` | 否 | text | 同 JSON |

Multipart 示例：

```bash
curl -sS https://media.kitt.tools/v1/images/edits \
  -H "Authorization: Bearer sk_..." \
  -H "X-MediaAsync-Provider-Key: upstream-provider-key" \
  -H "X-MediaAsync-Provider-Base-URL: https://api.example.com/v1" \
  -F "model=gpt-image-2" \
  -F "prompt=turn the sketch into a clean watercolor illustration" \
  -F "image=@source.png;type=image/png" \
  -F "size=1024x1024" \
  -F "output_format=png"
```

## 图片工具

这些接口使用 JSON。`image` 和 `mask` 字段使用下方“媒体输入引用格式”。

图片工具目前使用 Admin 托管渠道，请传 `X-MediaAsync-Route: managed`。

| 接口 | 任务类型 | 必填字段 | 可选字段 |
| --- | --- | --- | --- |
| `POST /v1/images/upscale` | `image.upscale` | `model`, `image` | `mode`, `response_format`, `user` |
| `POST /v1/images/erase-region` | `image.erase_region` | `model`, `image`, `mask` | `prompt`, `response_format`, `user` |
| `POST /v1/images/remove-background` | `image.remove_background` | `model`, `image` | `response_format`, `user` |
| `POST /v1/images/vectorize` | `image.vectorize` | `model`, `image` | `svg_compression`, `limit_num_shapes`, `max_num_shapes`, `response_format`, `user` |

示例：

```bash
curl -sS https://media.kitt.tools/v1/images/upscale \
  -H "Authorization: Bearer sk_..." \
  -H "X-MediaAsync-Route: managed" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "recraft-crisp-upscale",
    "image": { "url": "https://example.com/source.png" },
    "mode": "crisp"
  }'
```

## 视频生成

`POST /v1/videos`

`Content-Type: application/json`

视频生成目前使用 Admin 托管渠道，请传 `X-MediaAsync-Route: managed`。

| 字段 | 必填 | 类型 | 说明 |
| --- | --- | --- | --- |
| `model` | 是 | string | 公开视频模型 ID |
| `prompt` | 是 | string | 视频提示词 |
| `input_reference` | 否 | image/video reference | 首帧、参考图或参考视频，取决于模型和渠道 |
| `seconds` | 否 | string | 时长，例如 `"6"` |
| `size` | 否 | string | 分辨率或尺寸，例如 `1280x720` |
| `quality` | 否 | string | Provider 支持的质量档位 |
| `user` | 否 | string | 上游调用方关联 ID |

示例：

```bash
curl -sS https://media.kitt.tools/v1/videos \
  -H "Authorization: Bearer sk_..." \
  -H "X-MediaAsync-Route: managed" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "google-veo-3.1-generate-preview",
    "prompt": "a cinematic product shot of a ceramic teapot",
    "seconds": "6",
    "size": "1280x720"
  }'
```

## 查询、批量查询、取消和重试

图片任务查询：

```bash
curl -sS https://media.kitt.tools/v1/images/task-id \
  -H "Authorization: Bearer sk_..."
```

视频任务查询：

```bash
curl -sS https://media.kitt.tools/v1/videos/task-id \
  -H "Authorization: Bearer sk_..."
```

批量查询：

```bash
curl -sS https://media.kitt.tools/v1/media/batch \
  -H "Authorization: Bearer sk_..." \
  -H "Content-Type: application/json" \
  -d '{ "ids": ["task-id-1", "task-id-2"] }'
```

批量响应：

```json
{
  "object": "list",
  "data": [
    {
      "id": "task-id-1",
      "object": "image.edit",
      "status": "running",
      "stage": "provider_processing",
      "progress": 40,
      "model": "gpt-image-2",
      "task_type": "image.edit",
      "data": [],
      "error": null,
      "created_at": 1778470000,
      "updated_at": 1778470010,
      "completed_at": null
    }
  ],
  "missing": ["task-id-2"]
}
```

`/v1/media/batch` 的 `data` 数组与单任务查询响应结构一致，只是一次返回多个任务快照。`missing` 表示这些 ID 对当前 API key 不可见，可能是任务不存在，也可能是由其他 API key 创建。批量查询不会因为部分 ID 缺失而整体失败。

取消：

```bash
curl -sS -X POST https://media.kitt.tools/v1/images/task-id/cancel \
  -H "Authorization: Bearer sk_..."
```

重试：

```bash
curl -sS -X POST https://media.kitt.tools/v1/images/task-id/retry \
  -H "Authorization: Bearer sk_..."
```

视频任务使用 `/v1/videos/{video_id}/cancel` 和 `/v1/videos/{video_id}/retry`。

`cancel` 只允许 `queued` 或 `running` 任务；`retry` 只允许 `failed` 或 `canceled` 任务。

## 媒体输入引用格式

图片编辑、参考图、参考视频和图片工具输入通常支持以下格式。

URL 字符串：

```json
"https://example.com/source.png"
```

URL 对象：

```json
{ "url": "https://example.com/source.png" }
```

Data URL：

```json
"data:image/png;base64,iVBORw0KGgo..."
```

Base64 对象：

```json
{
  "filename": "source.png",
  "mime_type": "image/png",
  "data": "iVBORw0KGgo..."
}
```

`data` 字段传纯 base64，不需要 `data:image/png;base64,` 前缀。

内部文件引用：

```json
{
  "kind": "mediaasync_file",
  "file_id": "file_..."
}
```

普通第三方最常用的是 HTTP URL、data URL、base64 对象，或图片编辑 multipart 文件上传。

## Quote 估价

`POST /internal/quote`

`Content-Type: application/json`

请求：

```json
{
  "model": "gpt-image-2",
  "task_type": "image.generate",
  "channel_id": null,
  "input": {
    "prompt": "a small ceramic teapot",
    "n": 1,
    "quality": "high"
  }
}
```

响应：

```json
{
  "quote_id": "qt_...",
  "quote_version": 1,
  "currency": "usd",
  "estimated_cost_usd": "0.040000",
  "max_cost_usd": "0.040000",
  "expires_at": "2026-05-11T03:40:00Z",
  "pricing_snapshot": {
    "model": "gpt-image-2",
    "task_type": "image.generate",
    "channel_policy": "auto",
    "pricing_profile": "default-gpt-image-2-image-generate"
  }
}
```

Quote 是估价能力，不代表 MediaAsync 内部完成扣费。余额冻结、扣款、退款通常由上游网关或业务系统负责。

## Provider-compatible API

Provider-compatible 入口用于降低已有调用方迁移成本。请求体更接近供应商原生格式，但不会绕过 MediaAsync 的模型目录、渠道调度、重试、轮询、上传和 artifact 状态机。

| Provider | 接口 |
| --- | --- |
| Google/Gemini | `POST /google/v1beta/models/{model}:generateContent` |
| Google/Veo | `POST /google/v1beta/models/{model}:predictLongRunning` |
| MiniMax 图片 | `POST /minimax/v1/image_generation` |
| MiniMax 视频 | `POST /minimax/v1/video_generation` |
| MiniMax 音频 | `POST /minimax/v1/t2a_async_v2` |
| Volcengine 图片 | `POST /volcengine/v1/images/generations` |
| Volcengine 视频 | `POST /volcengine/v1/contents/generations/tasks` |
| Volcengine 视频查询 | `GET /volcengine/v1/contents/generations/tasks/{task_id}` |
| Recraft Crisp Upscale | `POST /recraft/v1/images/crispUpscale` |
| Recraft Creative Upscale | `POST /recraft/v1/images/creativeUpscale` |
| Recraft Erase Region | `POST /recraft/v1/images/eraseRegion` |
| Recraft Remove Background | `POST /recraft/v1/images/removeBackground` |
| Recraft Vectorize | `POST /recraft/v1/images/vectorize` |

这些入口仍要求 `Authorization: Bearer sk_...`。创建成功返回 MediaAsync 任务 `{ id, object, status }`，最终结果仍通过 MediaAsync 查询接口轮询。

## 错误和状态码

错误响应：

```json
{
  "error": {
    "message": "bad request: model gpt-image-2 not found"
  }
}
```

常见 HTTP 状态：

| 状态码 | 含义 |
| --- | --- |
| `400` | 参数错误或请求体格式错误 |
| `401` | API key 缺失或无效 |
| `404` | 任务不存在或当前 API key 不可见 |
| `502` | Provider 或存储调用失败 |
| `503` | Redis 或队列不可用 |

## 重要约定

- 调用方只传公开 `model`，不要传内部 `format`、物理渠道 ID 或持久化字段。Provider key 只在默认 BYOK 创建请求中通过 `X-MediaAsync-Provider-Key` 传入；Managed 路由不要传 Provider key。
- 创建接口是异步接口，创建成功不代表生成完成。
- 最终产物 URL 来自 `data[].url`，可能是本地 `/files/*` URL，也可能是 R2/CDN URL。
- Provider-compatible 入口的响应仍是 MediaAsync 异步任务响应，不保证完全复刻 Provider 原始同步响应。
- MediaAsync 不做终端用户体系、余额扣减或内容审核；这些通常由上游网站、网关和 Provider 策略负责。
