异步任务响应结构
- 图像与视频任务共用同一套查询响应
- 任务本身查询成功,失败信息在响应体里
- 判断终态看
status,不要看 HTTP 状态码
响应字段
任务唯一标识。与提交时返回的一致。
任务状态。取值 pending、processing、completed、failed、cancelled。
只有 completed、failed、cancelled 是终态,其余状态都应继续轮询。
进度百分比,0 到 100。仅供参考,不要用它判断完成。
本次任务扣费金额。
本次任务扣费积分。
结果容器,completed 时才出现。
生成的图像数组,属于图像任务。每个元素含 url(数组)、sizes、output_formats、expires_at。
生成的视频数组,属于视频任务。每个元素含 url(数组)与 expires_at。
创建时间,Unix 秒。
完成时间,Unix 秒,仅在任务结束后出现。
预计耗时,单位秒。
实际耗时,单位秒,仅在任务结束后出现。
失败详情,仅在 failed 时出现。
错误代码。注意这里是字符串,与同步错误的数字 code 类型不同。
错误描述。可通过查询参数 language 切换语言。
错误类型,用于程序分支判断。
The unique task identifier. Matches what was returned at submission.
The task status: pending, processing, completed, failed, or cancelled.
Only completed, failed, and cancelled are terminal; keep polling for any other status.
Progress percentage, 0 to 100. For reference only; don't use it to decide completion.
The amount charged for this task.
The credits charged for this task.
The result container; appears only when completed.
The array of generated images, for image tasks. Each element has url (an array), sizes, output_formats, and expires_at.
The array of generated videos, for video tasks. Each element has url (an array) and expires_at.
Creation time, in Unix seconds.
Completion time, in Unix seconds; appears only after the task ends.
Estimated duration in seconds.
Actual duration in seconds; appears only after the task ends.
Failure details; appears only when failed.
The error code. Note this is a string, unlike the numeric code on synchronous errors.
The error description. The language can be switched with the language query parameter.
The error type, for program branching.
四种状态的响应形态
排队中:
{
"code": 200,
"data": {
"id": "task_01KA",
"status": "pending",
"progress": 0,
"created": 1763088289
}
}处理中:
{
"code": 200,
"data": {
"id": "task_01KA",
"status": "processing",
"progress": 45,
"created": 1763088289
}
}成功(图像任务):
{
"code": 200,
"data": {
"id": "task_01KA",
"status": "completed",
"progress": 100,
"cost": 0.045,
"credits_cost": 0.45,
"result": {
"images": [
{
"url": ["https://cdn.oairoute.com/f/image/task_01KA_0.png"],
"sizes": ["2048x1152"],
"output_formats": ["png"],
"expires_at": [1763174708]
}
],
"videos": []
},
"created": 1763088289,
"completed": 1763088379,
"estimated_time": 90,
"actual_time": 88
}
}成功(视频任务):
{
"code": 200,
"data": {
"id": "task_01KA",
"status": "completed",
"progress": 100,
"cost": 0.9,
"result": {
"videos": [
{
"url": ["https://cdn.oairoute.com/f/video/task_01KA.mp4"],
"expires_at": 1763174708
}
]
},
"created": 1763088289,
"completed": 1763088400
}
}失败:
{
"code": 200,
"data": {
"id": "task_01KA",
"status": "failed",
"progress": 100,
"cost": 0,
"error": {
"code": "content_policy_violation",
"message": "提示词触发内容审核",
"type": "invalid_request_error"
},
"created": 1763088289,
"completed": 1763088301
}
}url 是数组而不是字符串,下游模型可能返回多张结果。取第 0 项即可。地址带 expires_at 过期时间,请及时转存。
Queued:
{
"code": 200,
"data": {
"id": "task_01KA",
"status": "pending",
"progress": 0,
"created": 1763088289
}
}Processing:
{
"code": 200,
"data": {
"id": "task_01KA",
"status": "processing",
"progress": 45,
"created": 1763088289
}
}Success (image task):
{
"code": 200,
"data": {
"id": "task_01KA",
"status": "completed",
"progress": 100,
"cost": 0.045,
"credits_cost": 0.45,
"result": {
"images": [
{
"url": ["https://cdn.oairoute.com/f/image/task_01KA_0.png"],
"sizes": ["2048x1152"],
"output_formats": ["png"],
"expires_at": [1763174708]
}
],
"videos": []
},
"created": 1763088289,
"completed": 1763088379,
"estimated_time": 90,
"actual_time": 88
}
}Success (video task):
{
"code": 200,
"data": {
"id": "task_01KA",
"status": "completed",
"progress": 100,
"cost": 0.9,
"result": {
"videos": [
{
"url": ["https://cdn.oairoute.com/f/video/task_01KA.mp4"],
"expires_at": 1763174708
}
]
},
"created": 1763088289,
"completed": 1763088400
}
}Failure:
{
"code": 200,
"data": {
"id": "task_01KA",
"status": "failed",
"progress": 100,
"cost": 0,
"error": {
"code": "content_policy_violation",
"message": "The prompt triggered content moderation",
"type": "invalid_request_error"
},
"created": 1763088289,
"completed": 1763088301
}
}url is an array, not a string, because downstream models may return several results. Take index 0. URLs carry an expires_at; copy the files promptly.
判断终态
轮询代码必须同时检查 HTTP 状态码与响应体的 status。只看 HTTP 状态码会漏掉任务级失败 —— 这类失败的任务本身查询是成功的,HTTP 仍是 200。
轮询间隔建议 5 到 10 秒。图像任务通常 1 到 3 分钟,视频任务 1 到 10 分钟。客户端总超时建议设到 15 分钟。
Polling code must check both the HTTP status code and the body's status. Checking only the HTTP status misses task-level failures — for those, the query itself succeeds and HTTP stays 200.
Poll every 5 to 10 seconds. Image tasks usually take 1 to 3 minutes and video tasks 1 to 10. Set the client's overall timeout to 15 minutes.
常见任务错误码
| code | 含义 | 处理方式 |
|---|---|---|
invalid_request_error | 参数不合法 | 检查字段名与取值,不要重试 |
authentication_error | 认证失败 | 换 Key,不要重试 |
permission_error | 余额不足或无权限 | 充值或换模型 |
not_found_error | 任务不存在 | 任务保留约 3 天,超期查询会返回 404 |
content_policy_violation | 内容审核未通过 | 改提示词,原样重试仍会失败 |
SensitiveContentDetected | 素材或产物触发审核 | 换素材 |
InvalidParameter.TaskTypeMismatch | 声明的任务类型与提示词不符 | 改 omni_reference_task_type 或改提示词 |
upstream_timeout | 上游超时 | 可以重试 |
internal_error | 服务端异常 | 可以重试 |
| code | Meaning | Handling |
|---|---|---|
invalid_request_error | Invalid parameters | Check field names and values; don't retry |
authentication_error | Authentication failed | Change key; don't retry |
permission_error | Insufficient balance or no permission | Top up or switch models |
not_found_error | Task not found | Tasks are kept about 3 days; querying after that returns 404 |
content_policy_violation | Failed content moderation | Change the prompt; retrying as-is fails again |
SensitiveContentDetected | Input material or output triggered moderation | Use different material |
InvalidParameter.TaskTypeMismatch | Declared task type doesn't match the prompt | Change omni_reference_task_type or the prompt |
upstream_timeout | Upstream timed out | Can retry |
internal_error | Server-side error | Can retry |
计费影响
| 错误类型 | 是否扣费 | 是否退款 |
|---|---|---|
| 参数错误 | 不建任务,不扣费 | 不涉及 |
| 内容审核未通过 | 建了任务、扣了费 | 自动全额退款 |
| 上游超时 | 扣了费 | 自动全额退款 |
| 成功但结果不满意 | 扣了费 | 不退款 |
退款由系统自动完成,不需要手动申请。在用量接口里能看到对应的冲正记录。
| Error type | Charged? | Refunded? |
|---|---|---|
| Parameter error | No task created, no charge | N/A |
| Failed content moderation | Task created and charged | Fully refunded automatically |
| Upstream timeout | Charged | Fully refunded automatically |
| Succeeded but unsatisfying result | Charged | Not refunded |
Refunds are automatic; no request needed. The corresponding reversal entries appear in the usage endpoint.
重试策略
按错误码分三类:
不要重试:参数错误、认证失败、权限不足、内容审核。这些重试多少次结果都一样。
可以重试:上游超时、服务端异常。用指数退避,最多两三次。
先改再试:任务类型不匹配。重试前要改 omni_reference_task_type 或提示词,否则一定同样失败。
Three groups by error code:
Don't retry: parameter errors, authentication failures, permission issues, content moderation. Retrying gives the same result every time.
Can retry: upstream timeouts, server-side errors. Use exponential backoff, two or three attempts at most.
Change something first: task type mismatch. Fix omni_reference_task_type or the prompt before retrying, or it will fail the same way.
与同步错误的区别
同步接口失败时返回 HTTP 4xx 或 5xx,响应体是 { error: { code, message, type } },code 是数字。
异步任务失败时,任务查询本身返回 HTTP 200,失败信息在 data.status 与 data.error 里,error.code 是字符串。
When a synchronous endpoint fails, it returns HTTP 4xx or 5xx with a body of { error: { code, message, type } }, where code is a number.
When an async task fails, the task query returns HTTP 200, and the failure is in data.status and data.error, where error.code is a string.
The two structures can't share one parsing path. For complete status codes and retry guidance see Error codes and rate limits. For troubleshooting steps on common errors see the FAQ.