错误码
请求失败时,先看 HTTP 状态码,再看响应体。业务错误带机器可读的 code;框架层失败只带 message。
业务错误始终返回可程序化分支的 code:
{ "code": "insufficient_balance", "message": "Insufficient balance for this submission."}code 是契约令牌 —— 不要翻译它、不要展示它,也不要拿 message 的文本做分支判断:那是给人看的措辞,随时可能改写。
错误码对照表
Section titled “错误码对照表”该接口返回的错误码正好是以下 22 个,状态码对应如下。
| code | HTTP | 说明 |
|---|---|---|
unauthorized | 401 | API Key 缺失、无效或已停用。 |
account_banned | 403 | 账号已被封禁,请联系客服。 |
invalid_realtime_request | 400 | 实时检测请求格式错误(例如 country 留空时号码缺少 + 国际区号前缀)。 |
idempotency_key_required | 400 | 实时检测请求必须携带 Idempotency-Key 头。 |
invalid_idempotency_key | 422 | Idempotency-Key 格式非法:仅允许 1-128 位字母、数字及 . _ : - 字符。 |
idempotency_conflict | 409 | 同一 Idempotency-Key 被用于内容不同的请求。 |
request_in_progress | 409 | 完全相同的实时请求正在处理中,请稍后重试(Retry-After: 1)。 |
empty_input | 422 | 上传的文件没有可用数据行。 |
product_not_found | 422 | 提交的产品 slug 不存在或未启用。 |
product_mode_not_supported | 422 | 该端点不接受此产品模式(实时产品不能提交到批量端点)。 |
invalid_country | 422 | 该产品不支持所提交的国家——标准代码见国家代码列表。 |
too_few_numbers | 422 | 提交数量低于该产品的最低起量。 |
too_many_numbers | 422 | 提交数量超过平台上限。 |
insufficient_balance | 402 | 余额不足以覆盖本次提交,请充值后重试。 |
realtime_disabled | 403 | 该账号未开通实时检测。 |
realtime_rate_limited | 429 | 实时检测触发限流,请遵循 retry_after。 |
product_pricing_unavailable | 503 | 该产品尚未配置价格,请联系客服。 |
detection_capacity_unavailable | 503 | 当前没有可用检测通道容量,请稍后重试。 |
realtime_route_unavailable | 503 | 当前没有可用的实时检测路由,请稍后重试。 |
realtime_fact_cache_unavailable | 503 | 实时检测依赖服务暂时不可用,请稍后重试。 |
realtime_rate_limiter_unavailable | 503 | 限流器暂时不可用,请稍后重试。 |
internal_error | 500 | 服务器内部错误。携带相同 Idempotency-Key 重试是安全的。 |
不带错误码的失败
Section titled “不带错误码的失败”并非所有失败都有 code。任务类接口有四类情况只通过 HTTP 状态码和 message 上报 —— 因为它们在走到业务错误分支之前就已经被拦下了:
| HTTP | 情况 | 响应体 |
|---|---|---|
404 | task_id 不存在,或属于其他账号 | 只有 message |
404 | GET /v1/tasks/{token}/download —— 结果文件不可用、已过期,或该任务已不处于可下载状态 | 只有 message |
422 | GET /v1/tasks/{token}/result —— 结果尚未就绪:任务未完成、文件尚未生成,或文件已过期 | 只有 message |
422 | 请求参数未通过校验 | { "message": …, "errors": { … } } |
这几种情况请按 HTTP 状态码分支。message 是给你看日志、给处理事故的人看的,不是用来做流程控制的。
对失败的正确处理,取决于「重复这个请求是否可能得到不同答案」。
| 分组 | 错误码 | 该怎么办 |
|---|---|---|
| 必须先处理 —— 原样重试只会重复同样的失败 | unauthorized、account_banned、invalid_realtime_request、idempotency_key_required、invalid_idempotency_key、idempotency_conflict、empty_input、product_not_found、product_mode_not_supported、invalid_country、too_few_numbers、too_many_numbers、insufficient_balance、realtime_disabled、product_pricing_unavailable | 修正请求、Key 或余额,然后重新发起。继续重试只是白费流量。 |
| 等待后重试 —— 瞬时的,同样的请求稍后应当成功 | realtime_rate_limited、request_in_progress、detection_capacity_unavailable、realtime_route_unavailable、realtime_fact_cache_unavailable、realtime_rate_limiter_unavailable | 有 Retry-After 就先遵守它,再按指数退避。请求本身没有问题。 |
| 结果不确定 —— 请求可能生效了,也可能没有 | internal_error | 用相同请求体 + 相同 Idempotency-Key 重试。 |
internal_error 是唯一无法从响应判断检测是否真的发生的情况。请用同一个 Idempotency-Key 重试:重放会返回已存结果,绝不二次扣费。换一个新的 key 才是一次扣费变两次的真正原因。
任务类接口那两种不带错误码的失败,按状态码归入上面的分组:任务接口返回 404 说明令牌不对,处理方式与「必须先处理」一致;结果接口返回 422 属于「等待后重试」—— 它的意思是再轮询一次,而不是去修什么。查询任务进度里的轮询循环就是靠读 status 来处理它,而不是靠捕获错误。
429 上完整的响应头集合见限流规则。