下单(付款重试沿用同一把幂等键)
代会员调用 · 必带
x-on-behalf-of
需 x-idempotency-key
动钱 · 冻结会员该资产的可用余额(locked_amount,含滑点预留)+ 同步冻结你的预付备付金
这个端点会动钱
失败处置见下方响应表。超时(504)用同一把幂等键重试——我方可能已经处理完;业务失败要换新键,同键会原样返回那次失败。
这是这条线上钱开始动的那一刻。 成功返回意味着:会员的可用余额
已经按 locked_amount 冻进 locked 桶(含滑点预留),你的预付
备付金已经按批发价同步冻结,限额已经预留。
走廊不从请求里读
以收款人自带的那一份为准。少一条可被构造的入参 ——
你传什么走廊我方都不看。
只有「收款人收多少」这一个方向
下单没有 source_amount。理由是上游那一侧 payout_amount
是定死边,必须逐字等于报价的买入额。要按「我出多少」下单,
先用 POST /v1/remit/quotes 反算出 payout_amount,再拿它下单。
幂等键 = 一次「确认」一把
付款重试沿用同一把键(拿回首次那笔,duplicated: true)。
换新键 == 第二笔真实付款。收到 504/网络错误时必须同键重试,
别新生成 —— 我方可能已经建单并冻了钱。
三种成功状态,处置完全不同
dispatching已放行,分发执行器在跑;reviewing/platform_reviewing等我方人工审核
(商户单一律先过一遍总后台,这是制度性关卡,不是出了问题);
pending= 内部的pending_merchant_funds:你的预付余额不足。
此时会员的钱一分未动、限额未预留、上游没有订单,
只有一张排队的订单行。去充预付,我方会自动推进它。
队列深度看 GET /v1/merchant/pending。
⚠ 会员侧永远看不到 pending 的原因。 你的界面上对终端用户
只能说「处理中」,不能说「商户余额不足」。
⚠ duplicated: true 时没有 quote(这一次没有真的报价),
status 是那张既有订单此刻的状态 —— 可能已经是 completed 了。
别把它当成「刚刚下单成功」。
前置条件
- 收款人在这个会员名下且状态可用
- 会员该资产可用余额 ≥ locked_amount(= 客户实付 × (1 + 滑点))
- 会员已过这条线要求的 KYC 层级,且未被封禁/拉黑
- 金额在最低起汇额、单笔上限、日限额之内
- purpose_code 在这条产品线允许的用途码清单内
- 个人线(pobo)还要求这个会员已有一个 active 的上游子账户
请求头
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
x-on-behalf-of |
string | 必填 | 代哪个会员调用。钱从他的余额里扣。 |
x-idempotency-key |
string | 必填 | UUID v4。这把键就是「一笔付款」的身份 —— 重试用同一把,新的一笔换新的一把。24 小时后同键视为新请求。 |
请求体
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
payee_id |
string | 必填 | 收款人号。pye_ 前缀可带可不带;剥掉后必须是纯数字。 |
payout_amount |
string | 必填 | 收款人收多少(目标币)。位数必须与该币种一致 ——
多给一位在下单这一刻就被拒(这道校验刻意前移到冻结之前:
晚一步的话,钱已经冻上、订单卡在 dispatching,
而那个状态不解冻也不可取消)。最长 32 字符。GBP 为 2 位:"380.00";JPY 为 0 位:"50000" |
slippage_bps |
integer | 必填 | 滑点上限,基点。必填整数,50 ~ 1000(0.5% ~ 10%)。
成交价相对下单快照上浮超过它时,订单停在 needs_reconfirm
等用户决定,而不是默默多扣。它同时决定冻多少:
locked_amount = customer_total × (1 + slippage_bps/10000)。 |
purpose_code |
string | 必填 | 汇款用途。必填,取值来自我方给你的用途码清单
(上游固定枚举 23 个,如 FAMILY_SUPPORT /
GOODS_PURCHASED / EDUCATION_TRAINING)。
留空或写错在下单这一刻被拒 —— 上游那个字段是 required,
漏到分发那一步就是钱冻完了才被打回来。 |
reference |
string | 可选 | 附言,会带给收款方。超过 200 字符截断。 |
line |
"express" | "pobo" | 可选 | 缺省 express;认不出的值静默按 express 处理。 |
asset |
string | 可选 | 从哪个资产扣款。缺省 USDT。 |
响应
201已受理。幂等命中也是 201(带
duplicated: true、quote: null)——
这个端点不用 200 区分首次与重放,判据是 duplicated
和响应头 X-Idempotent-Replay。{
"id": "rmt_9c1f0a7e-3b2d-4f81-9a55-1d2e3f4a5b6c",
"status": "reviewing",
"quote": {
"source_asset": "USDT",
"customer_total": "499.980000",
"fee": "2.480000",
"locked_amount": "504.979800",
"indicative_rate": "1.2899",
"applied_rate": "1.2743"
}
}400
invalid_request 请求体不是合法 JSON,或 payee_id 不是数字。
resource_not_found 收款人不在这个会员名下。
corridor_not_supported 收款人所在走廊已不可用(下架 / 受限辖区)。
product_not_available 业务线未开通,或源资产不可用。
invalid_fields payout_amount 位数与币种不符 / 超长 / 算不出来。
request_rejected 风控拒绝。不带原因、不带规则名、不带评分
(判据永不出境)。别重试,走商户后台联系我方。
service_unavailable 你的预付余额不足且这条线不排队时的对外形态。
汇款线正常情况下走排队(201 + status: pending)。409
idempotency_key_reused 同键换了请求体 —— 我方拒绝,
因为那意味着你有两笔不同的付款用了同一个身份。
idempotency_in_progress 首次请求还在处理中,稍后同键重试。422业务拒绝,逐条有明确的
code(不再是 500,2026-08-12 修复):
insufficient_balance 会员可用余额不足 ·
amount_out_of_range 低于最低起汇额(改金额就能过)·
limit_exceeded 超单笔或日累计上限(当天不用再试)·
kyc_required KYC 层级不足 ·
invalid_fields 用途码非法 / slippage_bps 缺失或越界 / 走廊与收款人不符 ·
request_rejected 账户被封禁或拉黑 ·
product_not_available 个人线缺 active 子账户、该资产未开通 ·
corridor_not_supported 走廊不可用。
实际 HTTP 码按对外码所属的类别走(多数是 400),
逐条见错误码目录。会触发的事件
remittance.order.action_requiredremittance.order.completedremittance.order.failedremittance.order.refunded
绿 = 终局且是好消息 · 红 = 终局且要处置 · 紫 = 中间态。点进去看事件体与验签。
请求
curl -X POST 'https://api.zise.com/v1/remittances' \
-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 '{
"payee_id": "pye_1042",
"payout_amount": "380.00",
"slippage_bps": 100,
"purpose_code": "FAMILY_SUPPORT",
"reference": "Rent Aug",
"line": "express",
"asset": "USDT"
}'const res = await fetch("https://api.zise.com/v1/remittances", {
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({
"payee_id": "pye_1042",
"payout_amount": "380.00",
"slippage_bps": 100,
"purpose_code": "FAMILY_SUPPORT",
"reference": "Rent Aug",
"line": "express",
"asset": "USDT"
}),
});
// 金额按字符串读,别让它变成 number
const data = await res.json();import requests
res = requests.post(
"https://api.zise.com/v1/remittances",
headers={
"x-auth-token": "Bearer $TOKEN",
"x-on-behalf-of": "$MEMBER_ID",
"x-idempotency-key": "$IDEMPOTENCY_KEY",
"content-type": "application/json",
},
json={
"payee_id": "pye_1042",
"payout_amount": "380.00",
"slippage_bps": 100,
"purpose_code": "FAMILY_SUPPORT",
"reference": "Rent Aug",
"line": "express",
"asset": "USDT"
},
)
# 金额用 Decimal(str(...)),不要 float
data = res.json()req, _ := http.NewRequest("POST", "https://api.zise.com/v1/remittances",
strings.NewReader(`{
"payee_id": "pye_1042",
"payout_amount": "380.00",
"slippage_bps": 100,
"purpose_code": "FAMILY_SUPPORT",
"reference": "Rent Aug",
"line": "express",
"asset": "USDT"
}`))
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/remittances"))
.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("""
{
"payee_id": "pye_1042",
"payout_amount": "380.00",
"slippage_bps": 100,
"purpose_code": "FAMILY_SUPPORT",
"reference": "Rent Aug",
"line": "express",
"asset": "USDT"
}
"""))
.build();
// 金额字段用 String / BigDecimal,不要 double$ch = curl_init('https://api.zise.com/v1/remittances');
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'
{
"payee_id": "pye_1042",
"payout_amount": "380.00",
"slippage_bps": 100,
"purpose_code": "FAMILY_SUPPORT",
"reference": "Rent Aug",
"line": "express",
"asset": "USDT"
}
JSON,
]);
$res = curl_exec($ch);
// 金额用 bcmath / 字符串,不要 floatval
201
{
"id": "rmt_9c1f0a7e-3b2d-4f81-9a55-1d2e3f4a5b6c",
"status": "reviewing",
"quote": {
"source_asset": "USDT",
"customer_total": "499.980000",
"fee": "2.480000",
"locked_amount": "504.979800",
"indicative_rate": "1.2899",
"applied_rate": "1.2743"
}
}