API 错误及其含义
Didit API 返回的每种 HTTP 状态在实际使用中通常代表什么 - 401 和 403 与密钥和权限有关,402 类的余额问题,429 速率限制,以及如何读取错误响应体。
先读响应体。 Didit 的错误会附带一条消息,通常还有一个说明真实问题的详情代码, 因为状态码本身很少能充分说明情况。 401 是密钥问题,403 是权限或环境问题,429 是速率限制,余额错误则与额度而非代码有关。
#先阅读响应体
HTTP 状态码告诉你问题的类别。 响应体告诉你实际发生了什么。 在 API 集成中,几乎所有可以避免的调试时间,都花在了猜测状态码上,而答案其实就在那个被丢弃的响应体里。

- 密钥被禁用或属于错误的应用,是 401 错误的常见原因。
- 最近使用时间可以确认你以为发送的密钥,是否真的是抵达的那个。
- 如果密钥可能已泄露,就轮换密钥:401 好过数据泄露。
在每个环境中,对每一次失败的调用,都要记录完整的错误响应体,包括状态码、请求头和负载。 你之后会用到它,而且事后重建要困难得多。
#每种状态码通常代表什么
| 状态码 | 常见原因 |
|---|---|
| 400 | 请求格式错误:缺少必填字段、枚举值不正确、嵌套对象结构错误 |
| 401 | 认证失败。x-api-key 请求头缺失、格式错误,或不是有效的密钥 |
| 403 | 已认证但不被允许。环境错误、密钥没有该权限,或账户未启用该功能 |
| 404 | 资源不存在,或存在于与你所用密钥不同的应用下 |
| 409 | 与现有状态冲突,例如某个操作已经执行过 |
| 422 | 请求格式正确,但取值不可接受:这是校验失败而非语法失败 |
| 429 | 触发速率限制。详见下文 |
| 5xx | Didit 一侧的问题。请使用退避重试,并查看 status.didit.me |
#401 与 403 的区别:能帮你省时间
401 表示密钥完全没有被接受。
请检查是否发送了 x-api-key,其值是否包含多余的空格或引号,以及你是否误把 webhook 签名密钥当成了 API 密钥粘贴进去。这是两个不同的东西,也是常见的错误。
403 表示密钥有效,但这次调用不被允许。按可能性排序,有三个原因:
- 环境不匹配。 仅限沙盒使用的字段(例如
sandbox_scenario)在正式应用上会被拒绝,反之亦然。正式环境和沙盒是两个独立的应用,拥有各自的密钥。 - 缺少权限。 部分操作需要你的密钥或角色不具备的权限。如果你需要会话创建和管理权限但目前没有,这应该向支持团队提出请求,而不是修改代码。
- 功能未启用。 部分能力是按组织开通的。如果你认为自己应该拥有某个功能却收到 403,值得先询问一下,再重写调用逻辑。
没有内置的方式能通过外观分辨沙盒密钥和正式密钥,因此请在你的密钥管理工具中用清晰不同的名称存储它们, 永远不要让一个环境变量保存"当前用的那个密钥"。 在测试环境中使用正式密钥会消耗真实额度。
#404 但资源明明应该存在
如果一个会话或工作流返回 404,而你确定它是存在的,通常的答案是它存在于另一个应用下,而不是你用来认证的那个密钥所属的应用。 资源是按应用划分的;应用 A 的密钥看不到应用 B 的会话。
#余额和额度错误
因额度不足而失败的调用,不是代码问题。 工作流中包含付费功能,而你的余额无法覆盖它。 这是迄今为止最常见的"API 坏了"报告,其原因几乎总是白标、AML 或 NFC 出现在了本应免费的工作流中。 参见修复"额度不足"错误。
#429 速率限制
限制按标识符应用:你的 x-api-key,或在未发送密钥时按客户端 IP,每个作用域在 60 秒滑动窗口内都有独立的计数器。
全局默认值:
| 作用域 | 方法 | 限制 |
|---|---|---|
| 通用读取 | GET | 600 次/分钟 |
| 通用写入 | POST、PATCH、DELETE | 300 次/分钟 |
部分高影响端点在全局限制之外还有更严格的限制,先超出计数器的作用域会返回 429。 完整表格参见速率限制。
处理 429 时应使用带抖动的指数退避。 针对速率限制的密集重试循环只会让问题更严重,甚至可能让你被无限期限制。
429 的常见来源是批处理任务,例如夜间导入任务在几秒内触发数百次创建请求。 应把任务分散执行,而不是不断提高并发直到不再报错。
#功能级详情代码
除了 HTTP 状态码之外,各项独立检查还会针对提供方层面的问题返回自己的详情代码,例如某个注册表集成在某个国家没有访问某个产品的权限。 遇到详情代码时,它会精确说明具体情况,因此在咨询时请直接引用该代码。
如果响应中缺少了你从目录中预期会有的详情代码,这值得报告,而不是绕过它。缺失的代码是一个真实的缺口,也会让下一个人更难排查同样的问题。
#空响应不等于成功
由提供方支持的检查如果返回空响应体,并不等同于一个干净的结果。 应在代码中把"无数据"当作独立的情况处理,而不是将其映射为通过,这一点对数据库验证和钱包筛查尤其重要,因为服务未开通和真正的无匹配从外部看起来可能很相似。
#测试错误路径
沙盒会确定性地强制触发特定的失败,这是测试你的错误处理逻辑的唯一可靠方式。 参见在沙盒中测试。
