结果查询GET
按幂等键或结果 ID 查询任意调用的状态与输出,重新获取生成文件的下载链接。用于异步任务、超时与断线恢复。
GET https://api.tokentosea.com/v1/results/{key}
GET https://api.tokentosea.com/v1/tasks/{id}
GET https://api.tokentosea.com/v1/videos/{id}
GET https://api.tokentosea.com/v1/assets/{asset_id}/download-url
每一次被受理的调用(同步、流式、异步、实时会话)都会在平台保存一份结果记录。网络中断、请求超时、流式连接断开或异步任务排队时,用这些接口取回结果,不要换新的幂等键重新提交——那会被当作一次新的调用并再次计费。
查询接口不产生费用。所有查询都必须使用发起原调用的那把密钥:结果与资产按密钥隔离,其他密钥(包括同一账号的其他密钥)查询会得到 404。
前提:原调用使用的密钥,以及原请求的 Idempotency-Key(或结果信封中的 id)。Python 示例需要 pip install requests,Node.js 示例需要 Node.js 18+。
按幂等键查询#
GET /v1/results/{key},key 是原请求的 Idempotency-Key(未传时为响应头 X-Request-Id 中的 tts-auto-…)。
按结果 ID 查询#
GET /v1/tasks/{id} 与 GET /v1/videos/{id} 接受结果信封中的 id(result_ + 64 位十六进制),返回与 /v1/results/{key} 相同的内容。两个路径等价,/v1/videos/{id} 便于视频任务使用。
结果信封#
{
"id": "result_9a1d…",
"run_id": "cm2…",
"status": "upstream_pending"
}{
"id": "result_9a1d…",
"run_id": "cm2…",
"status": "succeeded",
"billing_status": "succeeded",
"output": {
"id": "…",
"model": "wan2.7-t2v",
"data": [{ "url": "https://…?sign=…", "asset_id": "asset_…", "mime_type": "video/mp4" }]
},
"status_code": 200,
"response_type": "application/json"
}{
"id": "result_9a1d…",
"run_id": "cm2…",
"status": "failed",
"billing_status": "failed",
"error": { "code": "provider_http_400" }
}| 字段 | 说明 |
|---|---|
id | 结果 ID |
run_id | 账单中的调用记录 ID,联系支持时请提供 |
status | 处理状态,见下表 |
billing_status | succeeded 已按实际用量扣费;failed 未扣费,预留已释放;needs_review 待人工核对。结算前可能缺省 |
error.code | 未成功时的原因,例如 provider_http_<状态码>、provider_outcome_uncertain、provider_result_error、result_processing_pending |
output | 成功时的输出,见下文 |
status_code | 原调用的 HTTP 状态码 |
response_type | application/json 或 text/event-stream |
status | 含义 | 下一步 |
|---|---|---|
planned、sending、streaming | 已预留费用,正在调用上游 | 稍后再查 |
upstream_pending | 厂商异步任务处理中,平台每 5 秒查询一次,最长 24 小时 | 稍后再查 |
billing、archiving | 正在结算,或正在把生成文件转存到私有存储 | 稍后再查 |
succeeded | 完成 | 读取 output |
failed | 失败 | 根据 error.code 调整请求后,用新的幂等键提交 |
needs_review | 厂商结果或用量无法确认,等待人工核对;平台不会重新生成 | 不要重复提交;核对完成后状态会更新 |
输出内容#
| 原调用 | output |
|---|---|
| 同步 JSON 调用(对话、向量、System One 等) | 原响应体 |
| 流式调用 | 厂商最终数据,另有 stream 字段,内容为完整的 SSE 文本 |
| 生成文件(图像、视频、音频、3D 等) | { id, model, data: [{ url, asset_id, mime_type }], usage?, extra_info? };每次查询都会重新签发 url,最多 300 秒内有效 |
| 实时音频会话 | { model, events, usage }:会话中厂商发出的全部事件与累计用量 |
结果记录自最后一次更新起保留 31 天;生成文件在私有存储中保留 30 天。
重新获取下载链接#
GET /v1/assets/{asset_id}/download-url 为生成文件重新签发下载链接:
{
"url": "https://tokentosea-media-cn-….cos.ap-nanjing.myqcloud.com/…?sign=…",
"expires_in": 300
}expires_in 为链接剩余有效秒数,最多 300 秒,并且不会超过文件剩余的保留时间。链接只用于下载,不要把它公开分享或长期保存;需要长期保存的文件请下载到你自己的存储中。文件过期或 asset_id 不属于当前密钥时返回 404 asset_not_found。
示例#
# 按幂等键查询
curl "https://api.tokentosea.com/v1/results/$REQUEST_KEY" \
-H "Authorization: Bearer $TOKENTOSEA_API_KEY"
# 按结果 ID 查询
curl "https://api.tokentosea.com/v1/tasks/result_9a1d…" \
-H "Authorization: Bearer $TOKENTOSEA_API_KEY"
# 重新获取下载链接
curl "https://api.tokentosea.com/v1/assets/asset_…/download-url" \
-H "Authorization: Bearer $TOKENTOSEA_API_KEY"import os
import time
import requests
API = "https://api.tokentosea.com/v1"
HEADERS = {"Authorization": "Bearer " + os.environ["TOKENTOSEA_API_KEY"]}
PENDING = {"planned", "sending", "streaming", "upstream_pending", "billing", "archiving", "needs_review"}
def wait_for(request_key: str, interval_s: float = 5, timeout_s: float = 1800) -> dict:
"""轮询直到成功或失败;needs_review 会继续等待人工核对。"""
deadline = time.monotonic() + timeout_s
while time.monotonic() < deadline:
response = requests.get(f"{API}/results/{request_key}", headers=HEADERS, timeout=30)
if response.status_code == 404:
raise LookupError("没有该键的已受理调用")
response.raise_for_status()
result = response.json()
if result["status"] not in PENDING:
return result
time.sleep(interval_s)
raise TimeoutError("仍在处理,稍后用同一个键继续查询")
def fresh_url(asset_id: str) -> str:
response = requests.get(f"{API}/assets/{asset_id}/download-url", headers=HEADERS, timeout=30)
response.raise_for_status()
return response.json()["url"]const API = 'https://api.tokentosea.com/v1';
const headers = { Authorization: `Bearer ${process.env.TOKENTOSEA_API_KEY}` };
const PENDING = new Set(['planned', 'sending', 'streaming', 'upstream_pending', 'billing', 'archiving', 'needs_review']);
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
/** 轮询直到成功或失败;needs_review 会继续等待人工核对。 */
export async function waitFor(requestKey, { intervalMs = 5000, timeoutMs = 1_800_000 } = {}) {
const deadline = Date.now() + timeoutMs;
while (Date.now() < deadline) {
const response = await fetch(`${API}/results/${requestKey}`, { headers });
if (response.status === 404) throw new Error('没有该键的已受理调用');
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
const result = await response.json();
if (!PENDING.has(result.status)) return result;
await sleep(intervalMs);
}
throw new Error('仍在处理,稍后用同一个键继续查询');
}
export async function freshUrl(assetId) {
const response = await fetch(`${API}/assets/${assetId}/download-url`, { headers });
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
return (await response.json()).url;
}何时返回 404#
404 result_not_found / task_not_found 表示当前密钥下没有这个键或 ID 的已受理调用,常见原因:
- 请求在预留费用之前就被拒绝(例如余额不足、参数错误),平台没有创建调用记录。这种情况下可以用同一个键、修正后的请求重新提交。
- 请求还在平台入口处理(例如正在下载参考视频测量时长),尚未创建调用记录。稍后再查。
- 使用了另一把密钥,或键 / ID 拼写错误。
- 记录已超过保留期。
不确定原请求是否已被受理时,用同一个键、同一个请求体重发是安全的:已受理的调用只会返回原结果或 409,不会重复执行。
错误#
| 状态码 | code | 原因 |
|---|---|---|
401 | invalid_api_key、main_key_authorization_failed | 密钥缺失、格式错误、已撤销或已删除 |
404 | result_not_found | 见何时返回 404 |
404 | task_not_found | 结果 ID 不存在或不属于当前密钥 |
404 | asset_not_found | 资产不存在、已过期,或不属于当前密钥 |