提交开卡申请(虚拟/实体经 form_factor 区分)
代会员调用 · 必带
x-on-behalf-of
需 x-idempotency-key
动钱 · 扣开卡费与邮费 + 锁定首充金额(会员可用余额)
这个端点会动钱
失败处置见下方响应表。超时(504)用同一把幂等键重试——我方可能已经处理完;业务失败要换新键,同键会原样返回那次失败。
建单 + 扣开卡费(实体卡另收邮费),同步返回,不外呼上游。
真正的开卡是异步的,终局靠 webhook。
⚠ 回给你的 status 只有三档,是裁剪过的,不是我方的内部状态机。
其中 pending 的真实含义可能是「你的预付余额不够了,这张单在排队」——
我方刻意不在这里说破(会员侧连原因都看不到)。你要看队列深度走
GET /v1/merchant/pending,那是你自己的经营面。
⚠ 有两把幂等键,别混:请求头 x-idempotency-key 是开放 API 那一层
(24 小时窗口,同键回放首次结论);请求体 client_key 是发卡业务自己
那一层(落库、永久)。不传 client_key 我方会随机生成一把 ——
于是超过 24 小时之后同一份 body 重发会真的开出第二张卡。要幂等就自己传。
前置条件
- 会员 KYC 已通过 L1(产品可单独抬到 L2)
- 该会员在该供应商/介质下的持卡数未达上限(在途申请也算一个名额)
- 该会员没有未结清的罚金欠款
- 实体卡:必须已有默认邮寄地址,且收货国家在发卡与配送清单内
- 会员可用余额 ≥ 开卡费 + 邮费 + 首充额
- 你的预付余额够付这一单的批发成本(不够则这张单排队,不报原因)
请求头
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
x-on-behalf-of |
string | 必填 | 代哪个会员调用 |
请求体
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
form_factor |
string | 可选 | physical = 实体卡,其余一切取值(含缺省)都按虚拟卡处理。
没有拼写校验 —— 打成 Physical 会静默开出一张虚拟卡。 |
product_id |
string | 可选 | 产品标识,取自 GET /v1/card/products 的 id(cpd_…)。
推荐用它下单 —— 介质、BIN、发行安排全部由它唯一确定。
认不出(或不属于你)一律回 product_not_available。 |
bin |
string | 可选 | 卡 BIN,取自 GET /v1/card/products 的 bin。
只在不传 product_id 时使用;该 BIN 必须支持你要的介质与资金模式。 |
source_asset |
string | 必填 | 扣款资产代码(如 USDT)。必须在该产品的允许清单内 —— 不在清单里回 product_not_available。 |
first_topup |
string | 可选 | 首充金额,源资产口径的十进制串。省略 = 不首充。 产品配了首充下限时低于它会被拒。开卡费与首充是两笔独立的钱: 开卡失败退开卡费,而首充那笔在开卡成功后才真的充进卡。USDT 为 6 位以内:"50.00" |
address_id |
string | 可选 | 实体卡的收货地址 id。省略则用该会员的默认地址。地址会快照进单里 —— 会员日后改地址不影响已下的单。 |
client_key |
string | 可选 | 业务级幂等键(见上文两把键的区别)。强烈建议传。 |
响应
201已受理
{
"id": "cap_1b7d90c4-5e2a-4f18-83b6-0c7a4d1e9f22",
"status": "submitted",
"form_factor": "virtual"
}400
product_not_available 供应商/产品/BIN 不可用,或 source_asset 不在清单内 ·
service_unavailable 发卡这条线对你没开通,或你的资金账户被处置 ·
member_context_required 少了 x-on-behalf-of ·
idempotency_key_required / idempotency_key_invalid 幂等键缺失或不是 UUID v4
⚠ 另有一批业务拒绝目前会以 500 api_error 的形态返回(会员余额不足、
KYC 未过、持卡数已达上限、首充低于下限、有未结清罚金、收货国家不支持)——
它们在内部有明确的码,但还没登记进对外码目录。不要照着 500 无限重试:
重试同一把幂等键只会拿回同一个 500。这是我方的缺陷,已在修,
修好后这些会变成 400 且带各自的 code。409
idempotency_key_reused 同一把键换了 body 或换了端点 · idempotency_in_progress 首次请求还在处理会触发的事件
绿 = 终局且是好消息 · 红 = 终局且要处置 · 紫 = 中间态。点进去看事件体与验签。
请求
curl -X POST 'https://api.zise.com/v1/cards/applications' \
-H 'x-auth-token: Bearer $TOKEN' \
-H 'x-on-behalf-of: $MEMBER_ID' \
-H 'x-idempotency-key: $IDEMPOTENCY_KEY' \
-H 'content-type: application/json' \
-d '{
"form_factor": "virtual",
"product_id": "cpd_1042",
"source_asset": "USDT",
"first_topup": "50.00",
"client_key": "6d0f3a2e-8b41-4c77-9a10-2f5c7e91b3d4"
}'const res = await fetch("https://api.zise.com/v1/cards/applications", {
method: "POST",
headers: {
"x-auth-token": "Bearer $TOKEN",
"x-on-behalf-of": "$MEMBER_ID",
"x-idempotency-key": "$IDEMPOTENCY_KEY",
"content-type": "application/json",
},
body: JSON.stringify({
"form_factor": "virtual",
"product_id": "cpd_1042",
"source_asset": "USDT",
"first_topup": "50.00",
"client_key": "6d0f3a2e-8b41-4c77-9a10-2f5c7e91b3d4"
}),
});
// 金额按字符串读,别让它变成 number
const data = await res.json();import requests
res = requests.post(
"https://api.zise.com/v1/cards/applications",
headers={
"x-auth-token": "Bearer $TOKEN",
"x-on-behalf-of": "$MEMBER_ID",
"x-idempotency-key": "$IDEMPOTENCY_KEY",
"content-type": "application/json",
},
json={
"form_factor": "virtual",
"product_id": "cpd_1042",
"source_asset": "USDT",
"first_topup": "50.00",
"client_key": "6d0f3a2e-8b41-4c77-9a10-2f5c7e91b3d4"
},
)
# 金额用 Decimal(str(...)),不要 float
data = res.json()req, _ := http.NewRequest("POST", "https://api.zise.com/v1/cards/applications",
strings.NewReader(`{
"form_factor": "virtual",
"product_id": "cpd_1042",
"source_asset": "USDT",
"first_topup": "50.00",
"client_key": "6d0f3a2e-8b41-4c77-9a10-2f5c7e91b3d4"
}`))
req.Header.Set("x-auth-token", "Bearer $TOKEN")
req.Header.Set("x-on-behalf-of", "$MEMBER_ID")
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/cards/applications"))
.header("x-auth-token", "Bearer $TOKEN")
.header("x-on-behalf-of", "$MEMBER_ID")
.header("x-idempotency-key", "$IDEMPOTENCY_KEY")
.header("content-type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString("""
{
"form_factor": "virtual",
"product_id": "cpd_1042",
"source_asset": "USDT",
"first_topup": "50.00",
"client_key": "6d0f3a2e-8b41-4c77-9a10-2f5c7e91b3d4"
}
"""))
.build();
// 金额字段用 String / BigDecimal,不要 double$ch = curl_init('https://api.zise.com/v1/cards/applications');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'x-auth-token: Bearer $TOKEN',
'x-on-behalf-of: $MEMBER_ID',
'x-idempotency-key: $IDEMPOTENCY_KEY',
'content-type: application/json',
],
CURLOPT_POSTFIELDS => <<<'JSON'
{
"form_factor": "virtual",
"product_id": "cpd_1042",
"source_asset": "USDT",
"first_topup": "50.00",
"client_key": "6d0f3a2e-8b41-4c77-9a10-2f5c7e91b3d4"
}
JSON,
]);
$res = curl_exec($ch);
// 金额用 bcmath / 字符串,不要 floatval
201
{
"id": "cap_1b7d90c4-5e2a-4f18-83b6-0c7a4d1e9f22",
"status": "submitted",
"form_factor": "virtual"
}