任务
创建任务、跟踪状态、读取结果,以及 wait、任务列表、重试和清除的用法。
每一次生成都是一个任务。你用一次调用创建它,它自己在后台运行;结果准备好后,你可以主动查询、在第一次请求里等它,或者通过 Webhook 接收。
POST /jobs/createTasktaskIdGET /jobs/recordInfostateGET output.assets[].url
创建任务
curl -X POST "https://api.popnow.ai/api/v1/jobs/createTask" \
-H "Authorization: Bearer $POPNOW_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"model": "alibaba/wan-3.0/image-to-video",
"input": {
"image_url": "https://media.popnow.ai/movie/lighthouse.webp",
"prompt": "Waves roll in slowly, the camera drifts toward the lighthouse",
"resolution": "480p",
"duration_seconds": 5
},
"callBackUrl": "https://your-app.example.com/hooks/popnow"
}'请求体
| 字段 | 必填 | 含义 |
|---|---|---|
model | 是 | 模型页里的模型 ID |
input | 是 | 这个模型自己的字段,按它的输入 schema 校验 |
callBackUrl | 否 | 公开的 HTTPS 地址,任务完成后接收结果。见 Webhook |
quoteId、expectedCredits | 否 | 锁定你用 jobs/quote 确认过的价格 |
请求头
| 请求头 | 含义 |
|---|---|
Authorization: Bearer sk-popnow-… | 你的 API 密钥 |
Idempotency-Key | 强烈建议带上。用同一个键重试会拿回原来的任务。见幂等 |
X-PopNow-Retention | 可选。这个任务的产物和提示词保留多少秒。只能缩短保留时间,不能延长 |
Accept-Language | 可选。错误说明的语言。见错误码 |
响应
新任务返回 HTTP 202:
{
"code": 200,
"msg": "success",
"data": {
"taskId": "job_01JH8Z4Q5W2N7R3K9M6P1C0VXD",
"state": "queued",
"estimatedCredits": 34,
"estimatedCost": "0.34",
"deadlineAt": "2026-10-16T09:40:00Z"
},
"request_id": "req_…"
}202 表示已受理,不是已完成。estimatedCredits 是从余额里冻结的积分——这个任务最多花这么多(estimatedCost 是同一笔金额的美元表示)。如果创建失败,就什么都不会创建、也不会冻结;code 会告诉你原因(见错误码)。
状态
queuedrunningsucceededfailedexpired| 状态 | 终态? | 含义 |
|---|---|---|
queued | 否 | 已受理,等待开始 |
running | 否 | 正在生成 |
succeeded | 是 | 完成,文件在 output.assets 里 |
failed | 是 | 没能完成,见 errorCode 和 errorMessage。冻结的积分会退回 |
expired | 是 | 超过截止时间仍未完成。冻结的积分会退回 |
canceled | 是 | 只出现在历史记录里。现在已受理的任务无法取消 |
遇到不认识的状态,一律当作「还没结束」,继续查询。
用 wait 省掉轮询
给 createTask 加上 ?wait=<秒数>(最多 60),连接会一直保持,直到任务结束或时间用完:
- 在时限内结束 → HTTP
200,返回完整的任务记录,格式和recordInfo一样。注意检查data.state:终态不一定是成功。 - 没结束 → 照常返回
202,你继续轮询,或等 Webhook。
适合图片和短音频;视频几乎都会超过 60 秒。提前断开连接不会中止或取消任务。
查询任务
curl "https://api.popnow.ai/api/v1/jobs/recordInfo?taskId=job_01JH8Z4Q5W2N7R3K9M6P1C0VXD" \
-H "Authorization: Bearer $POPNOW_API_KEY"| 字段 | 含义 |
|---|---|
taskId、model、state | 哪个任务、哪个模型、走到了哪一步 |
input | 实际运行时的输入,包括你没传 seed 时自动选的那个值 |
output.assets[] | 生成的文件。每个都有 url、expiresAt、mime,视情况还有 width、height、durationSeconds、bytes、role |
errorCode、errorMessage | 任务失败的原因。程序按 errorCode 判断,errorMessage 给人看 |
credits、cost、settled | settled 为 false 时,credits 是冻结额;为 true 后就是最终扣费。cost 是同一笔金额的美元表示 |
createdAt、completedAt、deadlineAt | 时间戳;deadlineAt 是没完成的任务过期的时间 |
retention.outputsExpireAt | 这个任务的文件什么时候删除 |
contentState | present;内容被删除后变成 expired 或 purged |
三个不同的到期时间
deadlineAt:任务最多能跑多久。过了这个时间,任务变成expired,冻结的积分退回。output.assets[].expiresAt:这一条签名链接的有效期,大约 20 分钟。再读一次任务就有新链接,文件本身还在。retention.outputsExpireAt:存储的文件什么时候被删除。想保留的话,在这之前下载下来,或存进素材库。
output 里有什么
大多数任务只返回一个文件。有些会返回多个:模型一次出几张变体时会有多张图;视频续写会先给拼接好的完整视频(role: "video"),再给新生成的那一段(role: "segment");图层拆分会给一张底图加若干透明图层(每个带 layer 对象)。语音转文字的结果在 output.text 里。
产物链接是凭链接访问的:拿到 URL 的人在它过期前都能下载。下载时不要带上你的 API 密钥。
Webhook 为主,轮询兜底
轮询能用,但 Webhook 对双方都更省:结果一出来你就知道,中间也不用浪费请求。稳妥的做法是两者都用——平时靠 Webhook,偶尔用 recordInfo 扫一遍没收到回调的任务。
轮询时请放慢节奏:图片每 2–3 秒一次,视频每 10–15 秒一次,到 deadlineAt 就停。
任务列表
GET /api/v1/jobs 返回这个密钥创建的任务,最新的在前,不含输入和输出:
curl "https://api.popnow.ai/api/v1/jobs?state=failed&from=2026-10-01&limit=50" \
-H "Authorization: Bearer $POPNOW_API_KEY"筛选条件:from 和 to(UTC 日期,最多相隔 92 天;默认最近七天)、state、model、limit(最多 100)。hasMore 为 true 时,把 nextCursor 作为 cursor 传回去,其他筛选条件保持不变。
重试失败的任务
POST /api/v1/jobs/retry,请求体 { "taskId": "…" },会用一个 failed 或 expired 任务的原始输入、按今天的价格创建一个新任务。原任务不会被改动。源任务还没结束时返回 409;已经成功的任务不能重试,请直接新建。
删除任务内容
POST /api/v1/jobs/purge,请求体 { "taskId": "…" },会删掉任务的文件、结果和保存的提示词。账单记录保留:扣费、模型、状态和时间戳都还在,响应里的 billingRetained: true 就是在说明这一点。只有已结束的任务能清除,重复调用是安全的。

