Z Zise Developers
POST /v1/deposits

上报会员入金

Scope deposits:write 代会员调用 · 必带 x-on-behalf-of x-idempotency-key 动钱 · 增会员 available,同额增 merchant.custody(我方替你记的负债)
这个端点会动钱

失败处置见下方响应表。超时(504)用同一把幂等键重试——我方可能已经处理完;业务失败要换新键,同键会原样返回那次失败。

全系统唯一一个凭空产生会员余额的端点。 六道闸一道都不能省:

1. 强制签名 —— 即便这把 Key 配了 signature_required=false

此端点仍强制。少了 x-signature / x-timestamp / x-nonce

一律 401,且时间戳容差 ±300 秒、nonce 不可重放;

2. 幂等键必须带租户前缀且由商户提供业务流水号(reference)——

重复上报同一笔链上入金 = 双倍记账;

3. 单笔与日累计上限(按商户配,总后台设);

4. 资产必须在该商户的白名单内,认不出的一律拒绝而不是挂账

5. 照常过平台风控与准入 —— 上报入金不等于绕开风控;

6. 全量审计 + 商户后台可见。

凭证是两条腿:member.available credit W / merchant.custody debit W

merchant.available 不参与 —— 上报入金不是一笔成本。

两把键,别混

  • x-idempotency-key(请求头,UUID)挡的是你的网络重试

同键同体 24 小时内原样回放首次结果,同键异体 409。

  • reference(请求体)挡的是同一笔链上入金被上报两次

它进的是账本幂等键 mdep:<商户>:<reference>

和你换没换幂等键无关。所以 reference 必须是你那边那笔

链上交易的稳定标识(txid + vout、或你自己的入金单号),

不许每次调用现生成一个

重复命中时返回 200 + replayed: true,首次成功是 201

replayed 这一位让你不用去比对余额就知道「这笔我方早就记过了」。

白名单的语义

一行都没配 = 该商户尚未启用白名单,按平台资产目录放行。

一旦配了任意一行,就必须逐资产命中且启用 —— 没有那一行的资产

是拒绝,不是「没配限额」。

失败之后怎么办

  • 收到 504 / 网络超时:用同一把 x-idempotency-key 重试

我方可能已经记过了;

  • 收到明确的 4xx:换新键重试,同键会把那次失败原样回放给你;
  • 收到 limit_exceeded:看 limit_typesingle 单笔 / daily

日累计),这不是重试能解决的,去商户后台看额度。

前置条件

  • 请求已签名(此端点强制,不受 Key 的 signature_required 影响)
  • 资产在平台目录内且已启用;若该商户配了白名单,还必须逐资产命中且启用
  • 会员未被封禁 / 拉黑 / 冻结(照常过平台准入)
字段类型必填说明
x-on-behalf-of string 必填 给哪个会员记这笔入金
x-idempotency-key string 必填 UUID。格式不对直接 400 idempotency_key_invalid
x-signature string 必填 HMAC 签名。此端点不可关闭签名,与 Key 上的 signature_required 配置无关。
x-timestamp string 必填 Unix 秒。容差 ±300 秒,超窗回 timestamp_out_of_range
x-nonce string 必填 一次性随机串。重放窗口内重复使用回 nonce_reused

请求体

字段类型必填说明
asset string 必填 资产代码。我方会自动转成大写,所以 usdtUSDT 等价。不在目录/白名单内一律 asset_not_allowed
amount string 必填 入账数量,必须 > 0。字符串定点,位数 = 该资产 ledger_scale。小数位多于 scale 且尾数非全 0 时 直接 400 —— 我方不做四舍五入,宁可让你自己决定。USDT(ledger_scale=6)形如 1500.000000
reference string 必填 你那边这笔入金的稳定业务流水号,≤ 120 字符。 它进账本幂等键,是「同一笔钱只入账一次」的唯一依据。 ⚠ 每次调用现生成一个 = 这道闸完全失效。

响应

200幂等命中 —— 这笔我方早就记过了,本次没有再记一遍
{
  "id": "dep_0xa3f1c2...e9:0",
  "external_member_id": "u_10023",
  "asset": "USDT",
  "amount": "1500.000000",
  "ledger_scale": 6,
  "status": "credited",
  "replayed": true
}
201已入账(首次)
{
  "id": "dep_0xa3f1c2...e9:0",
  "external_member_id": "u_10023",
  "asset": "USDT",
  "amount": "1500.000000",
  "ledger_scale": 6,
  "status": "credited",
  "replayed": false
}
400invalid_request 缺字段 / 金额非法 / reference 超 120 字符 · asset_not_allowed 资产不在目录或不在该商户白名单内 · limit_exceeded 超限(看 limit_type = single 或 daily, limit_scope = merchant) · request_rejected 会员被平台准入拦下(不下发原因) · insufficient_balance 过账时余额类 CHECK 被撞 · idempotency_key_required / idempotency_key_invalid 幂等键问题
401signature_required 没带签名 · invalid_signature 签名不匹配 · timestamp_out_of_range 时间戳超窗 · nonce_reused nonce 重放
409idempotency_key_reused 同一把幂等键配了不同的请求体 · idempotency_in_progress 首次请求还在处理中,稍后同键重试
调用样例
curl -X POST 'https://api.zise.com/v1/deposits' \
  -H 'authorization: Bearer $TOKEN' \
  -H 'x-zise-merchant: $MERCHANT_ID' \
  -H 'x-on-behalf-of: $MEMBER_ID' \
  -H 'x-idempotency-key: $(uuidgen)' \
  -H 'content-type: application/json' \
  -d '{
    "asset": "USDT",
    "amount": "1500.000000",
    "reference": "0xa3f1c2...e9:0"
  }'
const res = await fetch(
  "https://api.zise.com/v1/deposits",
  {
    method: "POST",
    headers: {
      "authorization": "Bearer $TOKEN",
      "x-zise-merchant": "MERCHANT_ID",
      "x-on-behalf-of": "MEMBER_ID",
      "x-idempotency-key": "crypto.randomUUID()",
      "content-type": "application/json"
    },
    body: JSON.stringify({
      "asset": "USDT",
      "amount": "1500.000000",
      "reference": "0xa3f1c2...e9:0"
    }),
  },
);
// 金额一律按字符串读,不要 JSON.parse 成 number
const data = await res.json();
import requests

res = requests.post(
    "https://api.zise.com/v1/deposits",
    headers={
        "authorization": "Bearer $TOKEN",
        "x-zise-merchant": "$MERCHANT_ID",
        "x-on-behalf-of": "$MEMBER_ID",
        "x-idempotency-key": "$(uuidgen)",
        "content-type": "application/json"
    },
    json={
        "asset": "USDT",
        "amount": "1500.000000",
        "reference": "0xa3f1c2...e9:0"
    },
)
# 金额用 Decimal(str(...)),不要 float
data = res.json()