---
url: /guide/errors.md
---
# 错误处理

失败时返回非 200 状态码和统一的错误体：

```json
{
  "code": 400,
  "reason": "AMOUNT_BELOW_MIN",
  "message": "amount below minimum",
  "metadata": { "minAmount": "10" }
}
```

| 字段 | 说明 |
|---|---|
| `code` | HTTP 状态码 |
| `reason` | 稳定的错误标识，**请按它分支处理** |
| `message` | 英文说明，只给开发者看，可能变化，不要解析 |
| `metadata` | 动态参数（字符串键值），见下表 |

## reason 一览

| reason | HTTP | 说明 | metadata |
|---|---|---|---|
| `BAD_REQUEST` | 400 | 参数不合法（缺字段、格式错误等） | |
| `VALIDATOR` | 400 | 参数校验失败，`message` 指出哪个字段 | |
| `TOO_MANY_REQUESTS` | 429 | 请求过于频繁，稍后重试 | |
| `NOT_FOUND` | 404 | 资源不存在 | |
| `MERCHANT_AUTH_FAILED` | 401 | API key 无效 / 停用、商户停用、缺少签名请求头 | |
| `SIGNATURE_INVALID` | 401 | 签名不匹配 | |
| `REQUEST_EXPIRED` | 401 | `X-Timestamp` 缺失或超出 ±30 秒 | |
| `NONCE_REPLAYED` | 401 | `X-Nonce` 重复或长度不对 | |
| `IP_NOT_ALLOWED` | 403 | 来源 IP 不在白名单 | |
| `PERMISSION_DENIED` | 403 | API key 没有该接口需要的权限范围 | |
| `CHAIN_NOT_SUPPORTED` | 400 | 链不存在或未启用 | |
| `TOKEN_NOT_SUPPORTED` | 400 | 币种不存在或该链未配置 | |
| `ADDRESS_INVALID` | 400 | 地址格式不正确 | |
| `USER_NOT_FOUND` | 404 | 用户钱包不存在（还没获取过地址） | |
| `INSUFFICIENT_BALANCE` | 400 | 用户余额不足（内部转账） | |
| `TX_NOT_CREDITABLE` | 400 | 补单：交易查不到、未上链、执行失败或没有转入平台地址 | |
| `RECREDIT_REJECTED` | 403 | 补单：收款地址不属于该用户 | |
| `WITHDRAW_DISABLED` | 403 | 商户未开通提现 | |
| `WITHDRAW_NOT_ALLOWED` | 400 | 该币种在该链上不允许提现 | |
| `AMOUNT_BELOW_MIN` | 400 | 低于最小提现金额 | `minAmount` |
| `DUPLICATE_REQUEST` | 409 | `biz_id` 已存在 | `withdrawId`、`status` |
| `INVALID_STATE` | 409 | 当前状态不允许该操作 | |
| `HOT_WALLET_INSUFFICIENT` | 409 | 平台出账钱包余额不足，请稍后重试或联系我们 | |
| `SIGNER_UNAVAILABLE` | 503 | 签名服务暂不可用，可稍后重试 | |
| `CHAIN_RPC_UNAVAILABLE` | 503 | 链节点暂不可用，可稍后重试 | |
| `INTERNAL` | 500 | 服务器内部错误 | |

## 重试建议

* **5xx 与网络错误**：可以重试。对 `POST /v1/withdraws` 务必用**同一个 `biz_id`** 重试。
* **4xx**：修正请求后再发，原样重试不会成功。`DUPLICATE_REQUEST` 表示之前已经成功创建，按 `metadata.withdrawId` 继续即可。
* 以后可能新增 reason，未识别的请按 HTTP 状态码兜底处理。
