建会员
商户自身
需
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"
}400
invalid_request —— 三种情况同一个响应:body 非 JSON ·
external_member_id 为空或超 120 字符 / email 为空或不含 @ ·
该邮箱已属于另一个商户的会员(见上)403
insufficient_scope 缺 members:write409
idempotency_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 接,不要 float64HttpRequest 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 的响应示例