Skip to content

通用约定 ​

请求与响应 ​

  • 请求体与响应体均为 JSON(UTF-8)。发送请求体时请带 Content-Type: application/json。
  • 字段名使用 lowerCamelCase;枚举值使用大写下划线(如 ONE_TIME_ADDRESS)。
  • 请求体中未定义的字段会被忽略(不会报错),请注意拼写。
  • ID(walletId、交易 id 等)为 UUID 字符串(按时间递增的 UUIDv7)。
  • 成功状态码:200 OK;创建回调端点 201 Created;POST /v1/wallets、POST /v1/transactions、POST /v1/webhooks/{id}/test 为 202 Accepted(异步处理);DELETE /v1/webhooks/{id} 为 204 No Content(无响应体)。

金额 ​

  • 所有金额字段都以 Raw 结尾(个别字段例外,见各接口说明),值为最小单位的十进制整数字符串,不带小数点、正负号和科学计数法,例如 "1500000"。
  • 不要用 JSON 数字传金额;请求中金额格式错误返回 422 BAD_REQUEST(invalid JSON: …)。
  • 精度(decimals)来自 GET /v1/supported_assets,换算公式:显示金额 = raw / 10^decimals。例如 USDT(decimals = 6)的 "1500000" 为 1.5;ETH(decimals = 18)的 "1000000000000000000" 为 1。
  • 请使用大整数或十进制库(JS BigInt、Python int/Decimal、Java BigInteger/BigDecimal、Go math/big)处理,避免浮点误差;数值范围可达 256 位。

时间 ​

所有时间字段为 RFC 3339 格式的 UTC 时间,例如 2026-10-03T04:55:49.123456Z(小数秒位数不固定,请用标准 RFC 3339 解析器)。查询参数中的时间(如 createdFrom)也必须是 RFC 3339(例如 2026-10-01T00:00:00Z),放入 URL 时注意对 + 等字符做编码。

分页 ​

列表按创建时间倒序(新的在前)返回。目前有三种游标形式:

接口请求参数响应结束条件
GET /v1/transactions、GET /v1/walletslimit(1–200,默认 50)、before(UUID){ "items": [...], "nextBefore": "<uuid>" | null }nextBefore 为 null。注意:本页恰好满 limit 条时也会返回 nextBefore,下一页可能为空
GET /v1/userslimit(1–200,默认 50)、cursor(UUID){ "items": [...], "nextCursor": "<uuid>" | null }nextCursor 为 null
GET /v1/webhooks/deliverieslimit(1–200,默认 50)、before(整数){ "items": [...] }返回条数 < limit;下一页把本页最后一条的 id 作为 before

翻页时把上一页返回的游标原样放入下一次请求。其余列表接口(资产、网络、钱包资产、钱包地址、回调端点)一次性返回全部数据,不分页。

幂等 ​

会产生资金或资源的接口支持幂等,防止网络超时后重试导致重复操作:

接口幂等键
POST /v1/transactions请求体 externalTxId(推荐);不传 externalTxId 时必须带请求头 Idempotency-Key
POST /v1/wallets必须带请求头 Idempotency-Key

Idempotency-Key:1–128 个字符,只能包含 A-Z a-z 0-9 _ - : .,否则返回 422 BAD_REQUEST。

规则:

  1. 幂等记录按 租户 + API Key + 接口 + 幂等键 区分,长期保留。
  2. 相同幂等键 + 字节完全相同的请求体 → 不会重复执行,直接返回第一次的状态码和响应体。
  3. 相同幂等键 + 不同请求体 → 409 IDEMPOTENCY_CONFLICT(Idempotency-Key reused with a different request)。重试时务必复用第一次序列化好的请求体字节。
  4. 第一次请求仍在处理中 → 409 IDEMPOTENCY_CONFLICT(a request with this idempotency key (Idempotency-Key header or externalTxId) is already in progress),稍后用同样的请求重试。
  5. 第一次请求以不可重试的错误结束(retryable = false,如余额不足)→ 幂等键被释放,可以用同一个键再次提交(请求体可以修改)。
  6. 第一次请求以可重试的错误结束(retryable = true,如 INTERNAL)→ 幂等键保持占用;60 秒后用同一个键、同一请求体重试会安全地重新执行,期间重试返回第 4 条的 409。
  7. externalTxId 在租户内全局唯一(不区分 API Key):用另一个 API Key 提交已存在的 externalTxId 返回 409 IDEMPOTENCY_CONFLICT(externalTxId already used)。

其他写接口本身就是幂等的:POST /v1/users 与 POST /v1/users/{customerRefId}/deposit_address 按 customerRefId 去重,重复调用返回同一用户/同一地址。POST /v1/webhooks 不幂等,重复调用会创建多个端点。

超时怎么办

提现请求超时后,不要换一个新的 externalTxId 重试,而是用原请求体原样重试,或先 GET /v1/transactions/external_tx_id/{externalTxId} 查询是否已创建。

限流 ​

维度限制超出
每个 API Key每秒请求数,默认 50,可在控制台设为 1–1000429 RATE_LIMITED
每个用户新建钱包24 小时内最多 5 个(租户可配置)429 RATE_LIMITED(too many wallets created in the last 24 hours)
终端用户两步验证码每用户 15 分钟内最多 10 次校验429 RATE_LIMITED

收到 429 时请指数退避后重试(每次重试都要重新签名)。

请求大小与超时 ​

项目限制超出时
请求体256 KiB422 BAD_REQUEST(body too large);超过 1 MiB 时为 HTTP 413,错误码同为 BAD_REQUEST
服务端处理时间30 秒HTTP 408,错误码 PROVIDER_UNAVAILABLE(retryable = true)

POST /v1/users/{customerRefId}/deposit_address 在地址分配中时最多会等待约 6 秒再返回,请把客户端超时设为 30 秒以上。

错误响应 ​

所有错误(4xx/5xx)都返回统一结构:

json
{
  "error": {
    "code": "INSUFFICIENT_BALANCE",
    "message": "insufficient available balance",
    "retryable": false,
    "requestId": "a24ccbad-daca-4385-bf07-dd6b07768a9f"
  }
}
字段说明
code稳定的机器可读错误码,程序应据此分支,完整列表见 错误码
message面向开发者的英文描述,可能调整,不要用于程序判断
retryabletrue 表示原样重试可能成功(限流、服务暂不可用、内部错误),false 表示需要修改请求或业务条件
requestId请求 ID,与响应头 X-Request-Id 相同。联系平台排查问题时请提供

请求 ID:每个响应(包括成功响应)都带 X-Request-Id 头。你也可以在请求中自带 X-Request-Id(例如你方的链路追踪 ID),平台会沿用它。

HTTP 状态码与错误码:HTTP 状态码由错误码决定(对照表见 错误码)。需要特别注意 BAD_REQUEST:

来源HTTP示例
请求体 JSON 错误、字段校验失败、缺少 Idempotency-Key 等业务校验422invalid JSON: missing field `assetId` 、customerRefId must be 1-128 chars
路径参数或查询参数无法解析(在认证之前就会返回)400Invalid URL: Cannot parse `id` …、Failed to deserialize query string: …
方法不支持405method not allowed
请求体超过 1 MiB413request body too large

请按 error.code 而不是 HTTP 状态码做程序判断。

未知路径返回 404 NOT_FOUND(route not found)。