PopNowAPI 文档
参考
正文

错误码

每个业务码的含义、该怎么处理,以及哪些错误值得重试。

调用出错时,响应会给你一个说明问题类型的数字(code),和一句给人看的说明(msg)。程序按数字分支,说明拿来展示或写日志。

响应外壳

{ "code": 40201, "msg": "Insufficient balance", "request_id": "req_…" }
  • code 是业务码。200 表示成功,其他值都列在下面。
  • 失败时没有 data 字段,只有少数素材库错误会多一个 data.reason。
  • HTTP 状态码也会正确设置(40201 对应 HTTP 402)。两者选一个判断,不要混用——我们建议用更具体的 code。
  • request_id 同时出现在 X-Request-Id 响应头里。联系客服时请附上。

如果响应根本不是 JSON(比如中间网络返回的 HTML 或纯文本页面),就按 HTTP 状态码处理,并把响应体开头记进日志。

错误说明的语言

msg 和失败任务的 errorMessage 默认是英文。请求时带上 Accept-Language(en、ja、ko、de、fr、es、pt-BR、ru、it、pl 之一),或在控制台设置 API 错误语言,就能拿到对应语言;其他语言(包括中文)会退回英文。错误响应带有 Content-Language 头。错误码不会随语言变化——这也是永远不要解析 msg 的原因之一。

当模型给出了具体的失败原因(比如参考图读不出来),errorMessage 会把这个原因以英文原样转达,内部细节已去掉。

通用错误码

codeHTTP含义要重试吗?
200200 / 202成功—
400400请求或 input 不合法;msg 会指出问题不要,先修正
40003400上传的文件和上传票据对不上(大小、类型或内容)不要,重新申请票据再上传
40004400请求本身合法,但模型现在无法支持这组参数组合不要,改掉 msg 里点名的参数
401401缺少密钥、密钥不认识或已吊销(详情)不要
403403没有权限(见权限)不要
404404不存在,或属于另一个密钥不要
409409和当前状态冲突(何时重试)视情况
40901409报价过期或价格变了重新报价
413413请求体太大不要,改为上传素材,别内嵌
429429请求太多要,等 Retry-After 之后
500500我们这边出了问题要,退避后重试
503503某个支撑服务暂时不可用要,等 Retry-After 之后

余额与上限

codeHTTP含义怎么办
40201402积分不够冻结这个任务的金额购买积分后再发
40202402达到了密钥的消费上限在 API 控制台调高上限,或等它重置

权限

codeHTTP含义怎么办
40301403这个密钥不能调用这个模型把模型加进密钥的允许列表
40302403请求来源不在密钥的 IP 白名单里加上这个地址,或去掉该限制
40303403所在地区不提供服务无法绕过
40310403账户邮箱还没验证打开注册邮件里的链接;验证后密钥立即可用

如果密钥有效却收到一个普通的 403,说明账户暂时不能使用 API,请带上 request_id 联系客服。

模型可用性

codeHTTP含义要重试吗?
50301503这个模型现在接不了任务要,稍后再试,或换个模型
40004400模型正常,但不支持这组设置不要,改设置

这两种情况都不会创建任务,也不会冻结积分。

任务失败码

任务被受理后又失败的,state 是 "failed",errorCode 是下列之一。这个列表是封闭的:遇到其他值,一律按 upstream_failed 处理。

errorCode含义要重试吗?
invalid_request模型不接受这些参数不要,先修正
unsupported_combination暂不支持这组参数组合不要,换个设置
content_rejected模型拒绝了这段内容不要,改提示词或参考素材
invalid_asset参考文件读不出来或已失效重新上传后新建任务
rate_limited生成服务正忙要,退避后重试
upstream_unavailable生成服务暂时不可用要,稍后重试
generation_failed跑完了但没有产出看情况,同样的输入往往会同样失败
timeout任务超时看情况,试试更短或更低分辨率的输出
upstream_failed其他情况要,退避后重试

失败的任务会释放冻结的积分,不花钱(少数模型对内容拒绝也收费,会在模型页注明)。errorMessage 用文字说明原因;程序只按 errorCode 判断。

什么时候 409 值得重试

情形要重试吗?
带同一个 Idempotency-Key 的两个请求同时到达要,稍等片刻用同一个键重发
这个 Idempotency-Key 已用于别的请求或别的密钥不要
上传的文件或产物还在处理中要,几秒后再试
对还没结束的任务调用 jobs/retry要,等它进入终态后再试
对已成功的任务调用 jobs/retry不要,直接新建任务
上传票据或上传文件已过期不要,重新上传

怎么写重试

只重试第二次可能成功的错误;有 Retry-After 就按它等,没有就指数退避:

JavaScript
const RETRYABLE = new Set([429, 500, 503, 50301]);

async function call(path, init, attempts = 4) {
  for (let i = 0; i < attempts; i++) {
    const res = await fetch(`https://api.popnow.ai/api/v1${path}`, init);
    if (!res.headers.get('content-type')?.includes('json')) {
      throw new Error(`HTTP ${res.status}: ${(await res.text()).slice(0, 200)}`);
    }
    const body = await res.json();
    if (body.code === 200) return body.data;
    if (!RETRYABLE.has(body.code)) throw new Error(`${body.code} ${body.msg} (${body.request_id})`);
    const wait = Number(res.headers.get('retry-after')) * 1000 || 2 ** i * 1000 + Math.random() * 500;
    await new Promise((r) => setTimeout(r, wait));
  }
  throw new Error('out of retries');
}
Python
import random, time, requests

RETRYABLE = {429, 500, 503, 50301}

def call(method, path, attempts=4, **kwargs):
    for i in range(attempts):
        res = requests.request(method, f"https://api.popnow.ai/api/v1{path}", timeout=60, **kwargs)
        try:
            body = res.json()
        except ValueError:
            raise RuntimeError(f"HTTP {res.status_code}: {res.text[:200]}")
        if body["code"] == 200:
            return body["data"]
        if body["code"] not in RETRYABLE:
            raise RuntimeError(f'{body["code"]} {body["msg"]} ({body.get("request_id")})')
        retry_after = res.headers.get("retry-after")
        time.sleep(float(retry_after) if retry_after else 2**i + random.random() / 2)
    raise RuntimeError("out of retries")

重试 createTask 时,一定要带同一个 Idempotency-Key,这样一个其实已经成功的请求不会被执行、扣费两次。

排查

  1. 记下 request_id 和 code。
  2. 在 API 控制台的日志里,按任务 ID 或 request_id 查到这个任务。
  3. 还是解决不了?请联系客服,附上 request_id、时间(UTC)和 code。永远不要发送你的 API 密钥。

本页内容