# 查询任务
> Flow Music 的任务查询接口
> 与 Suno 系列的查询是同一个端点
> 路径 `/v1/music/tasks/{task_id}`
`GET /v1/music/tasks/{task_id}`
## 认证
- `Authorization` (string / 必填) — 所有接口均使用 Bearer Token 进行认证。 获取 API Key：[访问控制台](https://api.oairoute.com/keys) 创建。 请求时在请求头中添加： ```http Authorization: Bearer YOUR_OAIRoute_KEY ```
## 请求参数
### 路径参数
- `task_id` (string / 必填) — 提交任务时返回的 ID，取自提交响应里的 `data[0].task_id`。
### 查询参数
- `language` (string / 可选) — 错误信息与提示文案的语言，默认 `zh`。 可选值：`zh`、`en`、`ja`、`ko`。 只影响错误描述的语言，不改变其他内容。
> **Note:** 
> Flow Music 与 Suno 共用这一个查询端点。无论你提交的是 `flowmusic` 还是 `suno` 任务，都用同一个地址查。
## 响应
### 顶层
- `code` (integer) — 状态码，成功为 200。
- `data` (object) — 任务详情容器。
### data 任务字段
- `data.id` (string) — 任务 ID。
- `data.status` (string) — 任务状态，取值 `pending`、`processing`、`completed`、`failed`。
- `data.progress` (integer) — 进度，0 到 100。
- `data.created` (integer) — 创建时间，Unix 时间戳。
- `data.completed` (integer) — 完成时间，Unix 时间戳。
- `data.actual_time` (integer) — 实际耗时，单位秒。
- `data.cost` (number) — 实际扣费金额。失败通常为 0。
- `data.credits_cost` (number) — 实际消耗的 credits。
- `data.result` (object) — 生成结果。**按能力不同结构不同**，这是本接口最需要注意的地方。
### result.music[] 音乐类任务
- `clip_id` (string) — 片段 ID。
- `title` (string) — 标题。
- `duration_seconds` (string) — 时长，单位秒。注意是**字符串形式的数值**。
- `audio_url` (string) — 音频地址，m4a 格式。
- `wav_url` (string) — WAV 地址。
- `video_url` (string) — 视频地址，如视频渲染结果。
- `file_url` (string) — 附加文件地址，如分轨 zip。
### result.lyrics[] 歌词类任务
- `title` (string) — 歌词标题。
- `lyrics` (string) — 歌词正文，带段落标记。
### 错误响应
- `error.message` (string) — 错误描述。
- `error.type` (string) — 错误类型，如 `invalid_request`、`rate_limit_error`。
- `error.param` (string) — 出错的参数名。无特定参数时为空串。
- `error.code` (string) — 错误码，如 `task_not_found`、`rate_limit_error`。
## 结果结构随能力变化
这是最容易踩的坑：同一个端点，不同任务类型返回的 `result` 结构不同。
| 任务类型 | 结果位置 |
|---|---|
| 生成音乐 | `result.music[]` |
| 生成歌词 | `result.lyrics[]` |
| 分轨（Flow Music） | `result.music[].file_url` |
| 视频渲染 | `result.music[].video_url` 或 `result.videoUrl` |
| 歌词时间轴 | `result.alignment` |
| BPM 分析 | `result` 下的速度字段 |
写解析代码时，先按任务类型分支，再取对应字段。指望一个通用的读取函数适配全部，会到处拿不到值。
> **Note:** 
> `duration_seconds` 是字符串。直接参与算术会变成字符串拼接，需要先转数值。
## 轮询建议
| 任务类型 | 间隔 | 预期耗时 |
|---|---|---|
| 音乐生成 | 3 到 5 秒 | 30 到 120 秒 |
| 歌词、标签增强 | 3 到 5 秒 | 10 到 40 秒 |
| 下载任务 | 2 秒 | 通常 15 秒内 |
| 模型训练 | 10 到 30 秒 | 数分钟到 20 分钟 |
## 错误码
错误响应的格式、状态码与重试建议见[错误码与限流](../../../support/errors.html)，常见报错的排查步骤见[常见问题](../../../support/faq.html)。
## 使用示例
提交一个任务并拿到 `task_id`：
> **Note:** 
> 提交成功只表示任务已受理。真正的产物要拿返回的 `task_id` 去任务查询接口轮询，`status` 变成 `completed` 之后才有结果。
**查询任务{Get task}::cURL**
```
curl -X GET 'https://api.oairoute.com/v1/music/tasks/task_01K8SGYNNNVBQTXNR4MM964S7K?language=zh' \
  -H 'Authorization: Bearer YOUR_OAIRoute_KEY'
```
**查询任务{Get task}::Python**
```
import requests
res = requests.get(
    "https://api.oairoute.com/v1/music/tasks/task_01K8SGYNNNVBQTXNR4MM964S7K",
    headers={"Authorization": "Bearer YOUR_OAIRoute_KEY"},
    params={"language": "zh"},
)
d = res.json()["data"]
print(d["status"], d.get("progress"))
```
**查询任务{Get task}::JavaScript**
```
const res = await fetch(
  "https://api.oairoute.com/v1/music/tasks/task_01K8SGYNNNVBQTXNR4MM964S7K?language=zh",
  { headers: { Authorization: "Bearer YOUR_OAIRoute_KEY" } }
);
const { data } = await res.json();
console.log(data.status, data.progress);
```
**200 查询任务{Get task}**
```
{
  "code": 200,
  "data": {
    "id": "task_01K8SGYNNNVBQTXNR4MM964S7K",
    "status": "completed",
    "progress": 100,
    "created": 1763088289,
    "completed": 1763088387,
    "actual_time": 98,
    "cost": 0.048,
    "credits_cost": 0.48,
    "result": {
      "music": [
        {
          "clip_id": "c_01KA",
          "title": "窗边",
          "duration_seconds": "180.0",
          "audio_url": "https://cdn.oairoute.com/m/c_01KA.m4a",
          "wav_url": "https://cdn.oairoute.com/m/c_01KA.wav"
        }
      ]
    }
  }
}
```
