Z Zise Developers

建会员

POST /v1/members scope: members:write
商户自身 x-idempotency-key

两层幂等:external_member_id 天然去重(同一个外部号重复提交拿回

既有那一行,200 而不是 201),另加 x-idempotency-key 一层。

所以「已存在」不是错误,按状态码分支即可。

⚠ **该邮箱若已属于平台上另一个商户的会员,这里返回 400

invalid_request,建不出来。** 身份分层(把邮箱唯一索引从 users

上移到 identities)尚未落地,全局唯一索引还在,所以同一个自然人

暂时不能在两个商户下各建一个账号。

不是「已注册」的提示:返回的是与「参数不合法」逐字相同的

通用响应,不带任何字样能区分出「这个邮箱在别处存在」——

区分开就等于送出一个跨商户会员探测接口。代价是你拿到 400 时无法

自行判断是格式错还是撞了这条限制,请按「换一个邮箱或联系我方」处理。

(同一个邮箱若本来就在你自己名下,我方会把那一行认作你的会员

并补上你传的 external_member_id,返回 200。)

建出来的账号带一个随机占位密码,不走我方的密码登录;你的会员

经你自己的 App 或我方托管屏进入。

会触发 member.created

前置条件

  • 该邮箱不属于平台上其他商户的会员
字段类型必填说明
x-idempotency-key string 必填 UUID v4

请求体

字段类型必填说明
external_member_id string 必填 你自己的会员标识,最长 120 字符。它是这条线上的天然 幂等键,也是后续所有 x-on-behalf-of 的取值之一。
email string 必填 会员邮箱。服务端转小写后存,只校验「含 @」。 它同时是我方身份层的归并键(见上)。

响应

200这个 external_member_id 已存在,回读既有那一行(本次未新建)
201新建成功
{
  "id": "mem_9f1c0c8e-6f2a-4c1d-9d0b-2a7e5b3f8c41",
  "external_member_id": "u-10086",
  "uid": "80031427",
  "email": "alice@example.com",
  "nickname": "",
  "status": "normal",
  "kyc_level": 0,
  "created_at": "2026-08-12T09:30:00.000Z"
}
400invalid_request —— 三种情况同一个响应:body 非 JSON · external_member_id 为空或超 120 字符 / email 为空或不含 @ · 该邮箱已属于另一个商户的会员(见上)
403insufficient_scopemembers:write
409idempotency_key_reused · idempotency_in_progress

会触发的事件

绿 = 终局且是好消息 · 红 = 终局且要处置 · 紫 = 中间态。点进去看事件体与验签。

请求
curl -X POST 'https://api.zise.com/v1/members' \
  -H 'x-auth-token: Bearer $TOKEN' \
  -H 'x-idempotency-key: $IDEMPOTENCY_KEY' \
  -H 'content-type: application/json' \
  -d '{
    "external_member_id": "u-10086",
    "email": "alice@example.com"
  }'
const res = await fetch("https://api.zise.com/v1/members", {
  method: "POST",
  headers: {
    "x-auth-token": "Bearer $TOKEN",
    "x-idempotency-key": "$IDEMPOTENCY_KEY",
    "content-type": "application/json",
  },
  body: JSON.stringify({
    "external_member_id": "u-10086",
    "email": "alice@example.com"
  }),
});
// 金额按字符串读,别让它变成 number
const data = await res.json();
import requests

res = requests.post(
    "https://api.zise.com/v1/members",
    headers={
        "x-auth-token": "Bearer $TOKEN",
        "x-idempotency-key": "$IDEMPOTENCY_KEY",
        "content-type": "application/json",
    },
    json={
      "external_member_id": "u-10086",
      "email": "alice@example.com"
    },
)
# 金额用 Decimal(str(...)),不要 float
data = res.json()
req, _ := http.NewRequest("POST", "https://api.zise.com/v1/members",
    strings.NewReader(`{
  "external_member_id": "u-10086",
  "email": "alice@example.com"
}`))
req.Header.Set("x-auth-token", "Bearer $TOKEN")
req.Header.Set("x-idempotency-key", "$IDEMPOTENCY_KEY")
req.Header.Set("content-type", "application/json")
res, err := http.DefaultClient.Do(req)
// 金额字段用 string 接,不要 float64
HttpRequest req = HttpRequest.newBuilder()
    .uri(URI.create("https://api.zise.com/v1/members"))
    .header("x-auth-token", "Bearer $TOKEN")
    .header("x-idempotency-key", "$IDEMPOTENCY_KEY")
    .header("content-type", "application/json")
    .method("POST", HttpRequest.BodyPublishers.ofString("""
{
  "external_member_id": "u-10086",
  "email": "alice@example.com"
}
"""))
    .build();
// 金额字段用 String / BigDecimal,不要 double
$ch = curl_init('https://api.zise.com/v1/members');
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => [
    'x-auth-token: Bearer $TOKEN',
    'x-idempotency-key: $IDEMPOTENCY_KEY',
    'content-type: application/json',
  ],
  CURLOPT_POSTFIELDS => <<<'JSON'
{
  "external_member_id": "u-10086",
  "email": "alice@example.com"
}
JSON,
]);
$res = curl_exec($ch);
// 金额用 bcmath / 字符串,不要 floatval
200
// spec 里还没有这个 operation 的响应示例