搜索

搜索 HiAPI 模型、工具和资源。

返回博客
教程6 分钟阅读

HiAPI 任务输出 URL 过期(expireAt):在失效前下载并转存结果

终态 output[].url 带 expireAt,过期就 404——怎么判断、怎么及时下载、过期后怎么恢复。

hiapi问题排查任务接口HiAPI

你用 POST /v1/tasks 出图或出视频,任务跑完后从 data.output[0].url 拿到一条 temp.hiapi.ai 的链接——当时能打开,过几天再访问却变成一个 HTML 的「Not Found」页:

HTTP/2 404
content-type: text/html

返回的不是图片/视频字节,而是 Cloudflare 的 404 页面。原因只有一个:任务输出 URL 是带有效期的临时链接,终态里的 expireAt(Unix 时间戳)一到,temp.hiapi.ai 上的对象就被清理,热链失效。

先看懂终态里的字段

轮询任务终态(GET /v1/tasks/{taskId})成功时,关键字段长这样:

{
  "code": 200,
  "data": {
    "taskId": "tk-hiapi-xxxxxxxx",
    "status": "success",
    "storage": "temp",
    "created": 1791828181,
    "completed": 1791828201,
    "output": [
      {
        "artifactId": "...",
        "type": "image",
        "url": "https://temp.hiapi.ai/....png",
        "expireAt": 1792432981
      }
    ]
  },
  "message": "success"
}
  • data.status == "success" 才是终态成功(失败是 "fail",排队/处理中是 queued / handling / archiving)。
  • data.output 是数组,每个元素带自己的 url 和 expireAt。
  • expireAt 是 Unix 整数时间戳(不是 ISO 字符串)。判断是否过期只看它:now >= expireAt 即过期。
  • data.storage 的值是 "temp"——这本身就是提示:它是临时存储,不是给你长期引用的。

有效期多长?实测一个样本的 expireAt - completed = 604800 秒(正好 7 天)。但不要把「7 天」写死进代码——以每条输出自己的 expireAt 为准,不同模型/存储策略可能不一样。

常见原因(按命中概率排序)

  1. 把热链存进了数据库长期引用:落库时存的是 temp.hiapi.ai/... 这条临时 URL,过了 expireAt 就集体 404。这是最常见的坑。
  2. 拿到终态没立刻下载:任务跑完后隔了很久(超过 TTL)才去取字节。
  3. 以为重新轮询能「刷新」链接:对同一个 taskId 再 GET 一次,返回的是同一条 url 和同一个 expireAt——元数据持久,但对象本身过期后不会再生,重新 GET 不会给你新链接。
  4. 误把 404 当成任务失败:任务其实早就 success 了,只是输出资产过期了,这是两件事。

修复步骤

  1. 终态一到,立刻下载字节。 轮询到 data.status == "success" 后,马上对每个 output[].url 发 GET 把二进制拉下来,别排队、别延后。
  2. 转存到你自己的对象存储(R2 / S3 / 本地盘),换成一条你自己的持久 URL。
  3. 数据库里只存你自己的持久 URL,绝不存 temp.hiapi.ai 热链。
  4. 下载前先校验没过期:now < expireAt 再下;已过期直接走重跑逻辑。
  5. 过期了只能重跑任务。 没有「用 taskId 换新链」这回事——对同一个 taskId 再 GET,拿到的还是那条失效 url。要重新拿到可下载的结果,只能重新提交一次任务(会重新计费)。
  6. 批量任务控制下载时序:一批任务里最先完成的那条,expireAt 也最早到期。按完成先后立刻下载,别等整批都跑完再统一下载,否则早完成的可能已临近过期。

最小验证示例

确认你的 key 通、任务接口能出结果、并亲眼看到 expireAt。model id 用裸 id(z-image,别加 /text-to-image 之类后缀,会 400):

# 1. 提交任务
curl -s https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "z-image",
    "input": { "prompt": "a red apple on a wooden table" }
  }'
# → {"code":200,"data":{"taskId":"tk-hiapi-..."},"message":"success"}

# 2. 用上一步的 taskId 轮询终态,读出 url 和 expireAt
curl -s https://api.hiapi.ai/v1/tasks/tk-hiapi-xxxx \
  -H "Authorization: Bearer $HIAPI_API_KEY"
# data.status 变成 "success" 后,data.output[0].url / .expireAt 就有了

认证如果失败,返回的是 HTTP 401 + {"error":{"code":"permission_denied","type":"hiapi_error","request_id":"..."}}——那是 key 的问题,不是过期问题。查不到任务则是 {"code":404,"data":null,"message":"task not found"}——通常是 taskId 抄错或用错了环境的 key。

相关链接

FAQ

问:expireAt 到底是什么格式? 答:Unix 整数时间戳(秒),比如 1792432981,不是 ISO 字符串。用 now >= expireAt 判断过期即可。

问:链接过期后,能不能重新 GET 一次任务把链接「续期」? 答:不能。对同一个 taskId 再 GET,拿到的还是那条原始 url 和原始 expireAt,对象已被清理。要重新拿到可下载的结果,只能重跑任务(重新计费)。

问:过期后访问返回的是 403 还是 404? 答:是 HTTP 404,而且 body 是 text/html 的 Cloudflare「Not Found」页,不是图片字节、也不是 XML 的 AccessDenied。如果你的下载逻辑只认 200,记得把「非 200 一律按失败」处理。

问:有效期是不是固定 7 天? 答:实测样本是 7 天(604800 秒),但请以每条输出自己的 expireAt 为准,别在代码里写死天数。

问:一批任务怎么下载最稳? 答:按完成先后,谁先 success 就先下谁的字节。最先完成的输出 expireAt 也最早到期,拖到最后统一下载容易踩到临期。

现在就用 HiAPI 生成

选一个模型,输入你的提示词,直接查看生成结果。

HiAPI Blog

相关文章

HiAPI

现在就用 HiAPI 生成

开始生成