> ## Documentation Index
> Fetch the complete documentation index at: https://waffo.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# 提现与余额 API

> 让你从自己的系统提取结算资金并读取余额的五个签名接口：consult → create → inquiry 的调用顺序、withdrawRequestId 幂等键、余额查询返回哪些账户，以及账户历史查询的时间窗口和字段。

提现和余额不仅在 Portal 中可用，也提供 API。Portal 页面、费用、账单和自动提现合约见[提现与批量 Payout FAQ](/docs/zh/support/withdrawal-and-batch-payout-faq)，
各项余额的含义见[余额与账户历史](/docs/zh/support/balance-and-account-history-faq)，
签名见[认证与签名 FAQ](/docs/zh/support/auth-signature-faq)。

## 有哪些接口，调用它们需要什么？

五个接口都是 `POST`，JSON 进 JSON 出，签名方式与 `/api/v1/order/create` 完全一致。

| 接口 | 用途 |
| - | - |
| `/api/v1/withdraw/consult` | 试算：限额、费用、预期到账金额、收款账户。不动资金。 |
| `/api/v1/withdraw/create` | 创建提现订单。 |
| `/api/v1/withdraw/inquiry` | 按任一 id 读取一笔提现订单。 |
| `/api/v1/account/balance/inquiry` | 按币种的结算账户余额。 |
| `/api/v1/account/history/inquiry` | 你的结算账户和保证金账户的流水行。 |

两条访问规则拦住了大多数首次调用。**API 密钥是有作用域的**：仅为 payin 签发的密钥不能调用这些接口，会在签名校验之前就以 `A0004` "Permission denied" 失败——
如果一个在别处签名正确的请求返回 `A0004`，请向 Waffo 申请作用域包含提现的密钥。并且**请求体中的 `merchantId` 必须与你的密钥所对应的 MID 一致**，否则返回 `A0003`。
`/api/v1/withdraw/inquiry` 是例外：它不带 `merchantId`——MID 来自密钥，属于其他 MID 的订单会被报告为未找到。

## 三个提现调用是怎么配合的？

1. **`consult`**——发送 `currency`，可选 `amount`。返回费用、预期到账金额、你协议的限额和收款账户，以便你在提交前校验。
2. **`create`**——发送你确定的金额，加上你自己的 `withdrawRequestId`。
3. **`inquiry`**——轮询直到状态为终态，或等待发到你 `notifyUrl` 的回调。

`create` 刻意不等于一笔已完成的提现：审批记录和余额扣减是异步发起的，所以成功的 `create` 通常返回 `IN_PROGRESS`——把它当作「已受理」，绝不要当作「已打款」。

## consult 会告诉我什么，不传金额会怎样？

省略 `amount`，consult 回答的是「我现在一次最多能提多少」：你的**可提现余额**——结算账户的可用余额，在保证金余额为负时减去保证金缺口——以协议的最大值为上限。

| 字段 | 说明 |
| - | - |
| `amount`、`currency` | 试算的金额，或计算出的最大值 |
| `beforeAvailableBalance`、`afterAvailableBalance` | 本次提现前/后的可用余额 |
| `receiveCurrency`、`expectedReceiveAmount` | 同币种：`amount` − `fee`。跨币种：`expectedReceiveAmount` **完全不返回**，因为汇率尚未确定 |
| `feeCurrency`、`fee` | **内扣**；费用会吞掉全部金额的请求会被拒绝。跨币种提现以 `feeCurrency` 收取固定费用 |
| `minWithdrawAmount`、`maxWithdrawAmount` | 来自你的提现协议；`maxWithdrawAmount` 缺失表示无上限 |
| `merchantBankAccount` | `bankName`、`bankAccountNo`、`bankAccountName` |

实际的 `fxRate` 和 `actualReceiveAmount` 在订单完成后出现在 `inquiry` 上。

## create 需要什么，幂等是怎么工作的？

| 字段 | 必填 | 约束 |
| - | - | - |
| `withdrawRequestId` | 是 | ≤ 64 字符，每个 MID 内唯一，幂等键 |
| `currency`、`amount` | 是 | 金额为字符串，最多 2 位小数 |
| `description` | 是 | ≤ 128 字符 |
| `merchantInfo.merchantId` | 是 | 必须等于你密钥的 MID；`subMerchantId` 可选 |
| `withdrawRequestedAt` | 是 | `yyyy-MM-dd'T'HH:mm:ss.SSS'Z'` |
| `notifyUrl` | 是 | `http`/`https`，≤ 256 字符 |
| `bankAccountId` | 否 | 协议下哪个银行账户接收资金 |
| `accountNo` | 否 | 指定某一个具体的余额账户 |
| `extendInfo` | 否 | 合法 JSON，≤ 128 字符，在 inquiry 时原样返回 |

省略 `bankAccountId` 时自动使用协议下唯一绑定的账户；如果协议绑定了**多个**账户，省略它会以参数错误失败并要求提供。
`accountNo` 只在你同一币种持有多个余额账户时才有意义——这发生在与另一个 Waffo 实体重新签约之后。

`withdrawRequestId` 是幂等键，作用域为你的 MID。用相同的 `amount` 和 `currency` 重放它，你会得到**原**订单的结果——不会产生第二笔提现。
用不同的 `amount` 或 `currency` 重放，调用以 `A0011` "Idempotent param mismatch error" 失败。所以超时后用完全相同的请求体重试是安全的；真正的新提现需要新的 id。

## 怎么轮询状态，各状态是什么意思？

`inquiry` 至少需要 `withdrawRequestId` 或 `withdrawOrderId` 之一；两者都不传是参数错误。
两者都传时以 `withdrawOrderId` 为准，若两者不一致，调用会失败而不是返回错误的订单。

| API 状态 | 含义 |
| - | - |
| `IN_PROGRESS` | 尚未终态——涵盖未提交、审核中、已批准和渠道处理中 |
| `SUCCESS` | 已完成 |
| `FAILURE` | 审核拒绝、失败、关闭，或银行确认退回 |
| `BANK_DISPUTE_NOTIFIED` | 收款银行发起了退回；结果仍未确定 |

Portal 对同一订单显示更长、更细的状态列表——映射关系见
[提现与批量 Payout FAQ](/docs/zh/support/withdrawal-and-batch-payout-faq)。成功时 `inquiry` 补充 `actualReceiveAmount`、`fxRate`（同币种始终为 `1.00`）、`bankRefId` 和
`withdrawCompleteTime`；失败时带有 `failureCode` 和 `failureReason`。

## 余额查询返回哪些账户？

只有你的**结算账户**——每个结算币种一行，按签约实体合并。传 `currency` 可以缩小范围，省略则返回全部币种。待结算余额不在这里暴露。

| 字段 | 含义 |
| - | - |
| `accountNo`、`currency` | 账号全局唯一；同一币种可能有多个 |
| `totalBalance` / `availableBalance` / `frozenBalance` | 账户余额、可用部分，以及因拒付活动而冻结的部分（`available = total − frozen`） |
| `reserveBalance` | 该币种和实体的保证金余额；为负时，用 `availableBalance` 减去其绝对值即为你实际可提现的金额 |

## 账户历史查询最多能查多久以前，每行有什么？

**该接口上的所有时间均为 UTC**——包括你发送的 `startTime` / `endTime`（ISO-8601 本地日期时间，如 `2026-08-01T00:00:00`）和返回的 `transactionTime`（`...Z`）。
Portal 的账户历史则以 UTC+8 展示。

* 两个边界都省略时只返回**当天**；其他情况需同时发送两者。窗口不得超过 **180 天**，解析出超过 **60,000 行**的查询会被拒绝。
* 与 Portal 的账户历史不同，该接口**同时**覆盖结算账本和保证金账本。用 `accountType` = `MERCHANT_SETTLEMENT` 或 `MERCHANT_RESERVE` 筛选；省略则两者都返回。
  `currency` 和 `accountNo` 可进一步缩小范围，筛选一个你并不持有的账户会返回账户未找到错误而不是空列表。

每行带有 `accountNo`、`accountType`、`currency`、`amount`、`accountDirection`（`CREDIT` / `DEBIT`）、`newBalance`（该笔变动之后的余额）、`transactionTime`、
`businessId`（关联的业务订单）和 `businessType`——诸如 `SETTLEMENT`、`WITHDRAWAL`、`RESERVE_WITHHOLDING`、`RESERVE_RELEASING`、`RESERVE_ADJUSTMENT` 和 `ADJUSTMENT` 等代码，
最好不区分大小写地匹配。它们的含义见[余额与账户历史](/docs/zh/support/balance-and-account-history-faq)。

## 我应该显式处理哪些错误？

| 代码 | 何时发生 |
| - | - |
| `A0003` / `A0004` | 参数校验失败（包括 `merchantId` 与你的密钥不匹配）/ 你密钥的作用域不覆盖该接口 |
| `A0007` / `A0008` | 你不支持该提现币种 / 金额超出你协议的范围 |
| `A0010` / `A0012` | 你的合约不允许 / 余额不足 |
| `A0011` | 同一 `withdrawRequestId` 以不同参数重放 |
| `E0001` | 状态未知——持续轮询 `inquiry` 直到终态；不要创建第二笔订单 |

***

还是卡住了？[联系支持](mailto:support@waffo.com)并提供 `withdrawRequestId` 或 `withdrawOrderId` 以及调用的时间戳。


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.