Appearance
用户
B 端用户以交易所自己的用户 ID(customerRefId)为键:你不需要保存平台的内部 ID,所有用户接口都在路径中直接使用 customerRefId。邮箱是可选的。
账号从哪里来
托管 C 端的自助注册已永久停用(POST /app/v1/auth/register/code、/auth/register 一律 403)。用户只能由租户在你的交易所侧建档后,通过 POST /v1/users(可选设置初始密码与昵称)或租户后台内部开户创建;已有 C_DIRECT 账号不受影响。托管 C 端门户为 https://{slug}.wallet.fablewallet.top,平台自营(slug platform)为 https://wallet.fablewallet.top。详见 认证。
所有接口都需要 签名认证。路径中的 {customerRefId} 必须做 URL 编码,并用编码后的路径签名。
用户对象
POST /v1/users、GET /v1/users/{customerRefId}、PATCH /v1/users/{customerRefId} 返回的用户对象:
| 字段 | 类型 | 说明 |
|---|---|---|
id | string (UUID) | 平台内部用户 ID(一般无需使用) |
tenantId | string (UUID) | 所属租户 |
uid | string | 平台分配的 8 位数字用户号,租户内唯一 |
email | string | null | 邮箱(小写),可能为 null |
nickname | string | null | 昵称;创建时可传,未传则为 null |
totpEnabled | boolean | 用户是否绑定了 TOTP 两步验证(与 X-User-2FA-Code 相关) |
source | string | B_API:通过本接口创建;C_DIRECT:用户在托管 C 端自行注册 |
customerRefId | string | null | 交易所侧用户 ID |
status | string | ACTIVE / FROZEN / CLOSED |
cooldownUntil | string | null | 安全冷静期结束时间(RFC 3339),冷静期内资金操作受限;通常为 null |
冻结(FROZEN)的效果:该用户不能发起提现或转账(POST /v1/transactions 返回 403 FORBIDDEN,user is frozen),不能新建钱包(403 FORBIDDEN,user is not active),也不能作为 END_USER 收款人;充值仍会正常入账。
创建用户
http
POST /v1/users按 customerRefId 创建用户;若该 customerRefId 已存在,直接返回已有用户,且不会修改其邮箱、密码或昵称(改邮箱请用 PATCH)。通常不需要单独调用,获取充值地址 会自动创建用户。
请求头:X-API-Key、Authorization、Content-Type: application/json
请求体
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
customerRefId | string | 是 | 交易所侧用户 ID,1–128 个字符(首尾空白会被去掉),租户内唯一 |
email | string | 否 | 邮箱;仅在新建用户时使用。若提供,在租户内必须唯一 |
password | string | 否 | 同时为托管 C 端开通登录密码:10–128 位、须含字母和数字。必须与 email 一起提供,否则 422 BAD_REQUEST |
nickname | string | 否 | 昵称,最多 32 个字符(首尾空白会被去掉);仅在新建用户时使用 |
json
{ "customerRefId": "u-10001", "email": "alice@example.com", "password": "S3cretPassw0rd", "nickname": "Alice" }幂等与凭据
重复调用同一 customerRefId 返回首次创建的账号,本次传入的 email/password/nickname 不会覆盖已有值。password 只写入新账号,响应永不返回密码或哈希;如需重置密码请走租户后台流程。
响应 200 OK:用户对象
json
{
"id": "0192a4c1-7a3e-7c51-9a64-2f0d3b8e4a10",
"tenantId": "0191f0aa-1b2c-7d3e-8f40-5a6b7c8d9e0f",
"uid": "48213907",
"email": "alice@example.com",
"nickname": "Alice",
"totpEnabled": false,
"source": "B_API",
"customerRefId": "u-10001",
"status": "ACTIVE",
"cooldownUntil": null
}常见错误
| HTTP | code | 场景 |
|---|---|---|
| 422 | BAD_REQUEST | customerRefId must be 1-128 chars;invalid email;password requires an email;密码不合规;JSON 格式错误 |
| 409 | EMAIL_TAKEN | 邮箱已被本租户另一个用户使用 |
用户列表
http
GET /v1/users?limit=50&cursor=<nextCursor>&status=ACTIVE列出通过 B 端接口创建(source = B_API)的用户,按创建时间倒序。
查询参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
limit | integer | 否 | 1–200,默认 50 |
cursor | string (UUID) | 否 | 上一页返回的 nextCursor |
status | string | 否 | 按状态筛选:ACTIVE / FROZEN / CLOSED |
响应 200 OK
json
{
"items": [
{
"uid": "48213907",
"customerRefId": "u-10001",
"email": "alice@example.com",
"status": "ACTIVE",
"createdAt": "2026-10-03T04:55:49.123456Z"
}
],
"nextCursor": null
}nextCursor 为 null 表示没有更多数据。
查询用户
http
GET /v1/users/{customerRefId}返回用户及其全部钱包。
响应 200 OK
json
{
"user": {
"id": "0192a4c1-7a3e-7c51-9a64-2f0d3b8e4a10",
"tenantId": "0191f0aa-1b2c-7d3e-8f40-5a6b7c8d9e0f",
"uid": "48213907",
"email": "alice@example.com",
"nickname": null,
"totpEnabled": false,
"source": "B_API",
"customerRefId": "u-10001",
"status": "ACTIVE",
"cooldownUntil": null
},
"wallets": [
{
"id": "0192a4c1-8b10-7e22-b3a1-6f1e2d3c4b5a",
"tenantId": "0191f0aa-1b2c-7d3e-8f40-5a6b7c8d9e0f",
"userId": "0192a4c1-7a3e-7c51-9a64-2f0d3b8e4a10",
"chainFamily": "EVM",
"name": "EVM 1",
"seq": 1,
"isDefault": true,
"status": "ACTIVE",
"address": "0x8ba1f109551bd432803012645ac136ddd64dba72",
"createdAt": "2026-10-03T04:55:50.002311Z"
}
]
}钱包字段见 钱包对象。
常见错误:404 NOT_FOUND(user not found)。
修改用户
http
PATCH /v1/users/{customerRefId}设置/修改邮箱,冻结或解冻用户。字段都可选,未提供的字段保持不变。
请求体
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
email | string | 否 | 新邮箱(会转为小写),在租户内必须唯一。不支持清空 |
status | string | 否 | ACTIVE(解冻)或 FROZEN(冻结) |
json
{ "status": "FROZEN" }响应 200 OK:修改后的 用户对象。
常见错误
| HTTP | code | 场景 |
|---|---|---|
| 422 | BAD_REQUEST | invalid email;status must be ACTIVE or FROZEN |
| 404 | NOT_FOUND | user not found |
| 409 | EMAIL_TAKEN | 邮箱已被本租户另一个用户使用 |
获取充值地址(一次调用)
http
POST /v1/users/{customerRefId}/deposit_address交易所最常用的接口。一次调用完成:
- 若用户不存在,按
customerRefId创建(可同时设置email); - 若用户在该网络所属链族(
EVM/TRON/BTC/SOL)下还没有默认钱包,创建一个; - 返回该默认钱包的充值地址。
接口幂等:重复调用返回同一个钱包、同一个地址。所有 EVM 网络共用一个地址:对 ethereum 和 bsc(示例)分别调用,得到的 walletId 与 address 相同。
地址分配是异步的。接口最多等待约 6 秒;仍未就绪时返回 status = "PROVISIONING"、address = null,请稍后用相同参数再次调用(或查询 GET /v1/wallets/{walletId}/addresses)。
请求体
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
networkKey | string | 是 | 网络标识,必须是本租户已开通的网络(见 GET /v1/networks) |
email | string | 否 | 仅在本次调用新建用户时使用 |
json
{ "networkKey": "ethereum" }响应 200 OK
json
{
"customerRefId": "u-10001",
"uid": "48213907",
"walletId": "0192a4c1-8b10-7e22-b3a1-6f1e2d3c4b5a",
"networkKey": "ethereum",
"chainFamily": "EVM",
"address": "0x8ba1f109551bd432803012645ac136ddd64dba72",
"status": "READY"
}| 字段 | 说明 |
|---|---|
walletId | 默认钱包 ID,发起提现时作为 source.id。若默认钱包已冻结或隐藏,返回该链族下另一个可用钱包;都不可用时新建一个 |
address | 充值地址;PROVISIONING 时为 null |
status | READY:地址可用;PROVISIONING:分配中,稍后重试 |
某个资产在该网络上的最小充值额、充值手续费、是否暂停充值,请查 GET /v1/wallets/{walletId}/addresses 或 GET /v1/supported_assets。
常见错误
| HTTP | code | 场景 |
|---|---|---|
| 422 | BAD_REQUEST | customerRefId must be 1-128 chars;invalid email |
| 403 | FORBIDDEN | 用户已冻结且尚无该链族钱包(user is not active) |
| 409 | EMAIL_TAKEN | 新建用户时邮箱冲突 |
| 422 | NETWORK_DISABLED | 网络未对本租户开通(network not available for this tenant),或该链族暂停开新钱包 |
| 429 | RATE_LIMITED | 该用户 24 小时内新建钱包过多 |
查询用户余额
http
GET /v1/users/{customerRefId}/balances按资产汇总该用户所有钱包的余额(最小单位)。
响应 200 OK
json
{
"customerRefId": "u-10001",
"items": [
{ "assetId": "ETH", "availableRaw": "250000000000000000", "frozenRaw": "0" },
{ "assetId": "USDT_ERC20", "availableRaw": "75000000", "frozenRaw": "10000000" }
]
}| 字段 | 说明 |
|---|---|
availableRaw | 可用余额 |
frozenRaw | 冻结余额(处理中的提现:金额 + 手续费;待审批的转账等) |
只返回有过记账的资产。按钱包查询见 查询钱包余额。
常见错误:404 NOT_FOUND(user not found)。