Allinks 商户开放 API 对接文档

版本: W8.2 增补 3 更新日期: 2026-09-13 Base URL: https://<api-host>/open/api/v1


目录


1. 概述

Allinks Open API 为商户提供标准化的 RESTful 接口,覆盖卡片查询与状态管理、申请开卡、资金划转、交易与账单查询、通道头寸查询、KYC 案件查询等核心能力。佣金提现、结算对账、开卡代填、密钥与 Webhook 配置等控制台操作不在本通道范围(2026-09-12 产品裁决),请在商户控制台办理。

核心特性

  • 基于 API Key + HMAC-SHA256 签名认证,附防重放(nonce)、IP 白名单与权限范围(scopes)多重防护
  • 全量数据 JSON 格式、UTF-8 编码;金额一律为字符串,杜绝浮点误差
  • 写操作强制 Idempotency-Key 幂等保护,同 Key 重放返回首次结果
  • 19 个 Webhook 异步通知事件,1/5/15 分钟三级重试,投递状态可查

卡片响应仅含卡号后四位 last4,不含完整卡号与 CVV。下文示例中的主机名、密钥与编号均为占位符,请替换为控制台下发的真实值。


2. 接入准备

2.1 获取 API 凭证

在商户控制台的 设置 → API 密钥 模块完成以下步骤:

  1. 创建 API 密钥,按需配置权限范围(scopes)、IP 白名单与过期时间
  2. 复制 apiKey 与一次性展示的 apiSecret
  3. 妥善保存凭证(Secret 仅在创建或轮换时展示一次)

2.2 凭证示例

text
API Key:    ak_0123456789abcdef0123456789abcdef
API Secret: sk_0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef

重要提示: apiSecret 是签名密钥,请勿泄露。如怀疑泄露,请立即在控制台轮换,旧密钥即刻失效。

2.3 环境要求

  1. 服务器时钟与 UTC 偏差小于 300 秒
  2. 出口服务器 IP 已加入密钥的 IP 白名单(如配置)
  3. 完成后先调用无需签名的 GET /status 探活,再调用需签名的 GET /cards 验证凭证

3. 认证

GET /status 外,每个请求必须带齐四个头。

Header必填说明
X-Api-Key控制台下发的 apiKey
X-TimestampUnix (不是毫秒),与服务器相差超过 300 秒会被拒绝
X-Nonce每个请求唯一;重复使用会被视为重放
X-Signature见下方算法,小写 hex
Idempotency-Key卡片写操作、划转必填UUID;卡片冻结 / 解冻 / 销卡 / status 与划转必须携带
Content-TypePOST JSON 时application/json
Accept建议application/json

签名串

text
METHOD\nPATH\nTIMESTAMP\nNONCE\nBODY
规则
METHOD大写,如 GETPOST
PATH不含查询串/open/api/v1/cards?page=1 的 PATH 仍是 /open/api/v1/cards
TIMESTAMP / NONCE与请求头同一字符串
BODY原始请求体。GET 必须是空字符串,不要传 {}

HMAC 密钥不是 apiSecret 原文,而是:

text
hmacKey = SHA-256 的小写 hex(对 apiSecret 的 UTF-8 字节)
signature = HMAC-SHA256(key = hmacKey 的 UTF-8 字节, msg = 签名串) 的小写 hex

hmacKey64 位 hex 字符串的字节,不是 SHA-256 的原始 32 字节。

POST 时:用于签名的 BODY 必须与实际发出的字节完全一致(含空格)。同一份字符串既签名又发送。

错签不消耗 nonce,可用同一 nonce 更正后重试。限流 429、scope 不足 403 OPEN_403 同样不消耗 nonce。

权限范围 scopes

创建密钥时可传可选数组 scopes。合法值仅:readcardsfundsissue(trim 后大小写不敏感,落库小写,去重保序)。省略、null 或空数组 = 全部权限(存量密钥行为不变)。非法值创建失败(VAL_400)。

HMAC 验签且过期/IP 通过后、限流与 nonce 之前按路径闸口:

请求所需 scope
GET / HEADread
POST /cards/{id}/freeze · /unfreeze · /close · /statuscards
POST /merchant-credits(恰好该路径)funds
POST /card-applications(恰好该路径)issue
其它写方法(未知 POST / PUT / PATCH / DELETE)仅空 scopes(全部权限)可通过;显式列表 fail-closed
GET /statusFilter 跳过,不查 scope

缺所需 scope 返回 HTTP 403,errorCode=OPEN_403不消耗 nonceissue 为申请开卡(POST /card-applications,见 §5.11)所需 scope。显式四值与空数组不等价:未来新增 scope 时,显式列表不会自动获得。

示例(占位符)

python
import hashlib, hmac, os, time, uuid

api_key = os.environ["ALLINKS_API_KEY"]
api_secret = os.environ["ALLINKS_API_SECRET"]

def sign(method, path, timestamp, nonce, body=""):
    canonical = f"{method.upper()}\n{path}\n{timestamp}\n{nonce}\n{body}"
    key = hashlib.sha256(api_secret.encode("utf-8")).hexdigest()
    return hmac.new(key.encode("utf-8"), canonical.encode("utf-8"), hashlib.sha256).hexdigest()

ts = str(int(time.time()))
nonce = str(uuid.uuid4())
headers = {
    "X-Api-Key": api_key,
    "X-Timestamp": ts,
    "X-Nonce": nonce,
    "X-Signature": sign("GET", "/open/api/v1/cards", ts, nonce, ""),
    "Accept": "application/json",
}
bash
curl -sS "https://<api-host>/open/api/v1/cards?page=1&size=20" \
  -H "Accept: application/json" \
  -H "X-Api-Key: <YOUR_API_KEY>" \
  -H "X-Timestamp: <UNIX_SECONDS>" \
  -H "X-Nonce: <UNIQUE_NONCE>" \
  -H "X-Signature: <HEX_SIGNATURE>"

仓库内另有签名小工具 examples/open_api_hmac.py(从环境变量读密钥,无内置密钥)。


4. 请求与响应

成功

HTTP 多为 200code 为 JSON 数字 0

json
{
  "code": 0,
  "message": "success",
  "sceneCode": null,
  "data": {},
  "timestamp": 1710000000000
}
字段说明
codeJSON 数字。成功为 0;失败为 PRD 业务 int。请用 code === 0 判断成功
errorCode仅失败出现:原机读串(如 OPEN_401VAL_400
message成功为 "success"
data业务体
sceneCode可忽略
timestamp响应时刻,epoch 毫秒(与请求头的秒不同)

金额一律为 string(如 "10.00"),按十进制解析,不要用浮点。卡片 balance 可能多于 2 位小数。

失败

鉴权失败使用 HTTP 401 / 403 / 429;多数业务失败仍是 HTTP 200,看信封 code

json
{
  "code": 4001,
  "errorCode": "CARD_404",
  "message": "卡片不存在",
  "sceneCode": null,
  "data": null,
  "timestamp": 1710000000000
}
HTTPcodeerrorCode含义
4011002OPEN_401缺头、密钥无效或已停用
4011002OPEN_401_T时间戳非法或超出 ±300 秒
4011002OPEN_401_Rnonce 已使用
4031003OPEN_403密钥缺少该路径所需 scope(不消耗 nonce)
4031003OPEN_403_S签名不一致
4031003OPEN_403_IP来源 IP 不在白名单
4031003OPEN_403_EX凭证已过期
4294290142901该密钥超过窗口限额(默认 100 次 / 60 秒)
4042001NOT_FOUND路径不存在
2001001VAL_400参数错误(含路径 ID 非数字、非法 action、缺 Idempotency-Key
2004001CARD_404卡不存在或不属于本商户
2002001DEP_404充值单不存在
2002001MCC_404划转单不存在或不属于本商户
20010091009Idempotency-Key 但请求参数不同(幂等键冲突)
20010081008并发冲突(写操作处理中或头寸版本冲突)
2002004CARD_409卡片状态不允许该操作
2001003AUTH_403无权访问该资源(如跨商户查询持卡人/KYC)
2003406 / 34073406 / 3407划转额度不足 / 目标持卡人不满足条件
2009000CH_404 / KYC_404 / TRF_404 / WH_404 / PROD_404 / ACC_404 / POS_404 / CHN_502 / SYSTEM_ERROR资源不存在(持卡人 / KYC 案件 / 交易 / Webhook 端点 / 卡产品 / 账户 / 头寸)或通道异常、未分类错误

数据隔离:访问其他商户资源时原则上返回「不存在」,不暴露资源是否真实存在。例外:GET /cardholders/{id}GET /kyc/{id} 跨商户访问返回 AUTH_403(code 1003)。

分页与命名

查询与 JSON 均为 camelCase。划转请求同时接受 cardholderIdcardholder_id(W8.0 起值为 string,兼容历史 number 入参)。

分页总表(W8.0 起列表信封统一为 data = {total, page, size, items};W8.1 起补齐 /card-statements/finance/positions):

接口查询参数默认data
GET /cardspage size statuspage=1,size=50(1–100)total page size items
GET /cards/{id}/transactionstype page sizepage=1,size=50total page size items
GET /transactionstype page sizepage=1,size=50total page size items
GET /card-statementspage sizepage=1,size=50total page size items(W8.1 起为对象,原为裸数组)
GET /orders/depositspage size status from topage=1,size=50total page size items
GET /merchant-creditsstatus cardholderId page sizepage=1,size=50total page size items
GET /cardholderscurrency page sizepage=1,size=50total page size items
GET /kycstatus page sizepage=1,size=50total page size items
GET /webhookspage sizepage=1,size=50total page size items
GET /webhooks/{id}/deliveriespage sizepage=1,size=50total page size items
GET /finance/positionspage sizepage=1,size=50total page size items(W8.1 起增 page size 字段)

夹紧语义:page 小于 1 按 1 处理;size 小于 1 按 1、大于 100 按 100 处理;page 超出总页数时 items 为空数组但 total 仍为全集条数。

ID 类型总表(W8.0 起所有资源 ID 在 JSON 中一律为 string):

ID出现位置JSON 类型说明
cardId卡片列表/详情/冻结string路径 {id} 为数字串
cardholderId卡片、持卡人、划转、KYCstring划转请求体契约 string(兼容历史 number 入参)
userId持卡人列表行string即持卡人 ID
merchantId划转详情string主体取自凭证,不在 body 传
creditId划转单string路径 {id} 为数字串
depositId / depositNo充值单string/orders/{id} 两者皆可
endpointId / subscriberIdWebhook endpointstring路径 {id} 为数字串
deliveryIdWebhook 投递string
caseId / caseNoKYC 案件string路径 {id} 为数字串
id(交易 ID)卡交易stringGET /transactions/{id} 路径使用该数字串

路径 {id} 通常为数字串(如 /cards/123);非数字返回 VAL_400(code 1001)。例外:GET /deposits/{id}/orders/{id})另接受充值单编号 depositNoGET /transactions/{id} 另接受业务参考号与渠道流水号。历史版本中 cardholderId(卡片/划转上下文)、endpointIddeliveryIdsubscriberId 曾为 JSON number,W8.0 起统一 string。


5. 接口

以下 curl 均省略四个签名头,实际请求必须带上。

5.1 探活

接口

接口方法与路径说明
探活GET /status服务状态与能力目录(免签名)

接口说明:服务探活与能力目录接口说明:服务探活与能力目录。无需签名,可用于连通性检测与凭证配置前的环境确认。

请求

bash
curl -sS https://<api-host>/open/api/v1/status

请求参数:无。

响应参数data

字段类型说明
modulestring服务模块名
statusstring服务状态,UP 为可用
gastring当前可用版本号(对接文档版本以此为准)
authstring认证方式(HMAC-SHA256
capabilitiesarray当前全部可用端点清单(以实时返回为准,请勿硬编码)
scopesarray权限范围合法值(read / cards / funds / issue
scopesSemanticsstringscopes 语义说明

响应示例

json
{
  "code": 0,
  "message": "success",
  "data": {
    "module": "allinks-merchant-api",
    "status": "UP",
    "ga": "W8.2",
    "auth": "HMAC-SHA256",
    "capabilities": [
      "GET /open/api/v1/status",
      "GET /open/api/v1/cards",
      "GET /open/api/v1/cards/{id}",
      "GET /open/api/v1/cards/{id}/balance",
      "GET /open/api/v1/cards/{id}/transactions",
      "POST /open/api/v1/cards/{id}/freeze",
      "POST /open/api/v1/cards/{id}/unfreeze",
      "POST /open/api/v1/cards/{id}/close",
      "POST /open/api/v1/card-applications",
      "GET /open/api/v1/card-applications/{applicationId}",
      "GET /open/api/v1/cardholders",
      "GET /open/api/v1/cardholders/{id}",
      "GET /open/api/v1/transactions",
      "GET /open/api/v1/transactions/{id}",
      "GET /open/api/v1/card-statements",
      "GET /open/api/v1/orders",
      "GET /open/api/v1/orders/{id}",
      "GET /open/api/v1/deposits",
      "GET /open/api/v1/deposits/{id}",
      "GET /open/api/v1/finance/positions",
      "POST /open/api/v1/merchant-credits",
      "GET /open/api/v1/merchant-credits",
      "GET /open/api/v1/merchant-credits/{id}",
      "GET /open/api/v1/kyc",
      "GET /open/api/v1/kyc/{id}",
      "GET /open/api/v1/webhooks",
      "GET /open/api/v1/webhooks/{id}",
      "GET /open/api/v1/webhooks/{id}/deliveries"
    ],
    "scopes": ["read", "cards", "funds", "issue"],
    "scopesSemantics": "空或省略 scopes 表示全部权限;显式列表按最小权限闸口"
  }
}

业务规则

规则说明
免签名本接口不校验签名与 scope,可用于连通性检测
能力目录capabilities 以实时返回为准(上例为当前时点快照,共 28 条);后续版本可能增删,请勿硬编码

5.2 卡片列表

接口

接口方法与路径说明
列表GET /cards分页查询本商户卡片
详情GET /cards/{id}按卡片 ID 查询单张卡的详情

接口说明:分页查询本商户名下卡片接口说明:分页查询本商户名下卡片;详情接口按卡片 ID 返回单张卡(字段与列表项一致)。

请求

bash
curl -sS "https://<api-host>/open/api/v1/cards?page=1&size=20&status=ACTIVE"

请求参数

参数类型必填说明
statusquery按卡片状态筛选(值域见附录 A.1)
page / sizequery分页,默认 1 / 50(size 上限 100)
{id}path详情必填卡片 ID(数字串)

响应参数data

字段类型说明
total / page / size / items分页信封(见 §4)
items[].cardIdstring卡片 ID
items[].statusstring卡片状态(值域见附录 A.1)
items[].cardTypestring卡类型:VIRTUAL / PHYSICAL
items[].cardholderIdstring持卡人 ID
items[].last4string卡号后四位
items[].balancestring卡余额
items[].currencystring币种

响应示例

json
{
  "code": 0,
  "message": "success",
  "data": {
    "total": 1,
    "page": 1,
    "size": 20,
    "items": [
      {
        "cardId": "1234567890123456789",
        "status": "ACTIVE",
        "cardType": "VIRTUAL",
        "cardholderId": "10001",
        "last4": "1234",
        "balance": "0.00",
        "currency": "USD"
      }
    ]
  }
}

业务规则

规则说明
租户隔离仅返回本商户名下卡片;访问他商户卡片按不存在处理(CARD_404
脱敏仅返回卡号后四位 last4,不含完整卡号与 CVV
分页夹紧语义见 §4;total 为筛选后真实总数

5.3 卡片操作

卡片状态操作的接口总览:

操作方法与路径说明
冻结POST /cards/{id}/freeze暂停卡片交易,可解冻恢复
解冻POST /cards/{id}/unfreeze恢复已冻结卡片
销卡POST /cards/{id}/close注销卡片,不可逆
余额GET /cards/{id}/balance查询卡余额(响应与卡片详情相同)
单卡交易GET /cards/{id}/transactions查询单卡交易流水(分页)
状态变更(兼容)POST /cards/{id}/status?action=兼容端点,建议使用上述专用路径

以下三个写操作均需 scope cards、须携带 Idempotency-Key,请求体与响应结构一致。

5.3.1 冻结 / 解冻 / 销卡

接口说明:变更卡片状态。冻结后卡片不可交易,解冻立即恢复;销卡为终态操作,不可逆。

请求

bash
curl -sS -X POST "https://<api-host>/open/api/v1/cards/1234567890/freeze" \
  -H "Idempotency-Key: <uuid>" \
  -H "Content-Type: application/json" \
  -d '{"reason": "merchant-request"}'

请求参数

字段类型必填说明
reasonstring操作原因(便于对账与审计,如 merchant-request

响应参数data

字段类型说明
cardIdstring卡片 ID
previousStatusstring变更前状态
newStatusstring变更后状态(值域见附录 A.1)
effectiveAtstring生效时间,ISO-8601 UTC

响应示例

json
{
  "code": 0,
  "message": "success",
  "data": {
    "cardId": "1234567890123456789",
    "previousStatus": "ACTIVE",
    "newStatus": "FROZEN",
    "effectiveAt": "2026-01-15T08:00:00Z"
  }
}

业务规则

规则说明
幂等Idempotency-Key 返回 VAL_400;同 Key 同参重放返回首次结果,不重复执行;同 Key 异参返回 1009;失败请求不占用 Key;同一 Key 的请求处理中返回 1008
冻结ACTIVE 状态可冻结;其他状态(含重复冻结)返回 CARD_409
解冻FROZEN 状态可解冻;存在欠缴时返回 CARD_409
销卡需卡余额与冻结额均为 0 方可销卡,否则返回 CARD_409;已销卡重放按成功无副作用返回;销卡为终态操作,不可逆
通道失败上游通道处理失败返回 errorCode=CHN_502

5.3.2 余额查询

GET /cards/{id}/balance,响应 data 与卡片详情相同(字段见 §5.2)。

5.3.3 单卡交易

接口说明:查询单卡的交易流水(授权与清算合并为一条生命周期记录),分页返回。

请求参数

参数类型必填说明
{id}path卡片 ID(数字串)
typequery筛选 AUTH(授权)/ CLEARING(清算)
pagequery页码,默认 1
sizequery每页条数,默认 50(1–100)

响应参数data):分页信封 {total, page, size, items},行项字段与 GET /transactions 一致(见 §5.5)。

业务规则total 为该卡真实交易条数(单卡直达数据源,不受商户交易量上限影响)。

5.3.4 状态变更(兼容端点)

POST /cards/{id}/status?action= 为兼容端点,不在 capabilities 目录中。仅允许 action=FREEZE / UNFREEZE,其他值返回 VAL_400;同样须携带 Idempotency-Key。新开发请使用 /freeze/unfreeze/close

5.4 持卡人

接口

接口方法与路径说明
列表GET /cardholders分页查询本商户持卡人(脱敏)
详情GET /cardholders/{id}按持卡人 ID 查询详情(含持卡与余额摘要)

接口说明:分页查询本商户名下持卡人接口说明:分页查询本商户名下持卡人(脱敏输出,不含完整证件号码与卡号);详情接口按持卡人 ID 返回单个对象。

请求

bash
curl -sS "https://<api-host>/open/api/v1/cardholders?currency=USD&page=1&size=50"

请求参数

参数类型必填说明
currencyquery按币种筛选
page / sizequery分页,默认 1 / 50
{id}path详情必填持卡人 ID(数字串)

响应参数data

字段类型说明
total / page / size / items分页信封(见 §4)
items[].userIdstring持卡人 ID
items[].displayNamestring姓名(脱敏)
items[].mobileMaskstring手机号(脱敏)
items[].kycStatusstring持卡人 KYC 等级(L0 / L1 / L2 / L3;未认证为 NONE
items[].registeredAtstring注册时间
items[].balancestring可用余额
items[].currencystring币种
items[].statusstring持卡人状态(如 ACTIVE

响应示例

json
{
  "code": 0,
  "message": "success",
  "data": {
    "total": 1,
    "page": 1,
    "size": 50,
    "items": [
      {
        "userId": "10001",
        "displayName": "张*三",
        "mobileMask": "138****0000",
        "kycStatus": "L2",
        "registeredAt": "2026-01-15T08:00:00",
        "balance": "10.00",
        "currency": "USD",
        "status": "ACTIVE"
      }
    ]
  }
}

详情响应参数GET /cardholders/{id}data

字段类型说明
cardholderId / cardholderNostring持卡人 ID / 业务编号
merchantIdstring归属商户 ID
displayName / phoneMasked / emailMaskedstring姓名 / 手机 / 邮箱(均脱敏)
statusstring持卡人状态(如 ACTIVE
kycLevelstringKYC 等级(L0L3
kycStatusstring最新 KYC 案件状态(无案件时为 NONE
cardCountnumber名下卡片数量
panMaskedFirst6 / panMaskedLast4string \null
balance / currencystring可用余额 / 币种
jurisdictionstring归属司法辖区
statusReason / lastStatusAtstring \null
cardsarray名下卡片掩码摘要列表

业务规则

规则说明
租户隔离仅可查询本商户名下持卡人;跨商户访问返回 errorCode=AUTH_403
不存在持卡人不存在返回 errorCode=CH_404
脱敏姓名、手机、邮箱与卡号一律掩码输出,不含证件原文

5.5 卡交易与账单

接口

接口方法与路径说明
交易列表GET /transactions分页查询卡交易流水(授权、清算等)
交易详情GET /transactions/{id}按交易 ID / 流水号查询单笔交易
账单摘要GET /card-statements月度账单摘要(按账期聚合)

接口说明:分页查询本商户名下的卡交易流水接口说明:分页查询本商户名下的卡交易流水(授权、清算等)与月度账单摘要;交易详情按交易 ID 返回单笔记录。

请求

bash
curl -sS "https://<api-host>/open/api/v1/transactions?type=AUTH&page=1&size=20"

请求参数

参数类型必填说明
typequery筛选 AUTH(授权)/ CLEARING(清算)
page / sizequery分页,默认 1 / 50
{id}path详情必填交易 ID(数字串)

响应参数data.items[] 交易行项)

字段类型说明
idstring交易 ID
typestring类型:AUTH(授权)/ CLEARING(清算)
statusstring交易状态
amountstring金额
currencystring币种
createdAtstring交易时间
refNostring业务参考号
remarkstring \null
creditIdstring \null
cardIdstring卡片 ID
panLast4string卡号后四位
merchantIdstring商户 ID
mccstring \null
channelIdstring \null
authCodestring \null
declineCodestring \null
channelTxId / channelClearIdstring \null
authAmountstring \null
clearAmountstring \null
clearAppliedboolean \null
shortfallAmountstring \null
authResultstring \null
authAt / clearAtstring \null

业务规则

规则说明
行项口径授权与清算合并为一条生命周期记录,状态随清算推进更新
脱敏仅含卡号后四位 panLast4
详情查询GET /transactions/{id}{id} 支持交易 ID 或业务参考号(refNo / 渠道流水号);不存在返回 errorCode=TRF_404
月度账单GET /card-statements 返回账期摘要;账单行明细请经商户控制台下载

月度账单摘要 GET /card-statements?page=1&size=50 —— 响应参数(data.items[]

字段类型说明
statementIdstring账单 ID(即账期 period,如 2026-08
periodstring账期
txCountnumber当期交易笔数
amountstring当期交易金额合计
currencystring币种
json
{
  "code": 0,
  "message": "success",
  "data": {
    "total": 1,
    "page": 1,
    "size": 50,
    "items": [
      { "statementId": "2026-08", "period": "2026-08", "txCount": 2, "amount": "20.00", "currency": "USD" }
    ]
  }
}

5.6 用户充值单

接口

接口方法与路径说明
列表GET /deposits分页查询持卡人充值单(GET /orders 为同义路径)
详情GET /deposits/{id}按充值单 ID 或编号(depositNo)查询

接口说明:分页查询持卡人充值单接口说明:分页查询持卡人充值单(用户入金记录,非卡消费流水);详情按充值单 ID 或编号返回单条记录。

请求

bash
curl -sS "https://<api-host>/open/api/v1/deposits?status=CREDITED&page=1&size=50"

请求参数

参数类型必填说明
statusquery按充值状态筛选
from / toquery时间范围,YYYY-MM-DD 或本地日期时间;日期型 to 按次日 0 点不含
page / sizequery分页,默认 1 / 50
{id}path详情必填充值单 ID 或 depositNo

响应参数data

字段类型说明
items[].depositIdstring充值单 ID
items[].depositNostring充值单编号
items[].userMaskstring持卡人标识(脱敏)
items[].amountstring充值金额
items[].currencystring币种
items[].statusstring充值状态(值域见附录 A.8)
items[].txidstring \null
items[].methodstring充值方式(如 CRYPTO
items[].createdAtstring创建时间
items[].exceptionCodestring \null

响应示例

json
{
  "code": 0,
  "message": "success",
  "data": {
    "total": 1,
    "page": 1,
    "size": 50,
    "items": [
      {
        "depositId": "10001",
        "depositNo": "DEP10001",
        "userMask": "u1***9",
        "amount": "10.00",
        "currency": "USD",
        "status": "CREDITED",
        "txid": "onchain-or-channel-ref",
        "method": "CRYPTO",
        "createdAt": "2026-01-15T08:00:00",
        "exceptionCode": null
      }
    ]
  }
}

业务规则

规则说明
路径别名/orders/deposits 为同一业务(兼容保留),新开发请使用 /deposits
存在性详情不存在时返回 errorCode=DEP_404
租户隔离仅返回本商户名下持卡人的充值单

5.7 通道头寸

接口

接口方法与路径说明
头寸查询GET /finance/positions分页查询通道头寸的会计分科余额

接口说明:分页查询商户通道头寸接口说明:分页查询商户通道头寸的会计分科余额。

请求

bash
curl -sS "https://<api-host>/open/api/v1/finance/positions?page=1&size=50"

请求参数page / size,分页,默认 1 / 50。

响应参数data.items[]

字段类型说明
currencystring币种
balancestring头寸总额
heldstring冻结中金额
reservedstring预留金额
safetyBufferstring安全垫金额
availableForReturnstring可调回金额
transferHoldstring划转冻结金额(待复核的划转占用)
availableForCreditstring可划转金额(划转接口的额度依据)
warningStatusstring水位预警状态:OK / WARN / CRITICAL
updatedAtstring更新时间

响应示例

json
{
  "code": 0,
  "message": "success",
  "data": {
    "total": 1,
    "page": 1,
    "size": 50,
    "items": [
      {
        "currency": "USD",
        "balance": "10000.00",
        "held": "0.00",
        "reserved": "0.00",
        "safetyBuffer": "0.00",
        "availableForReturn": "10000.00",
        "transferHold": "0.00",
        "availableForCredit": "10000.00",
        "warningStatus": "OK",
        "updatedAt": "2026-01-15T08:00:00"
      }
    ]
  }
}

业务规则

规则说明
分科管理通道头寸与持卡人资金、佣金分科核算,互不混同;本接口仅反映头寸科目
额度依据availableForCredit 为划转接口(§5.10)的可划转额度单一真源

5.8 KYC 案件

接口

接口方法与路径说明
列表GET /kyc分页查询本商户持卡人的 KYC 案件(脱敏)
详情GET /kyc/{id}按案件 ID 查询单个案件

接口说明:分页查询本商户持卡人的 KYC 案件接口说明:分页查询本商户持卡人的 KYC 案件(脱敏输出);详情按案件 ID 返回单个案件。

请求

bash
curl -sS "https://<api-host>/open/api/v1/kyc?status=PENDING_MERCHANT&page=1&size=50"

请求参数

参数类型必填说明
statusquery按案件状态筛选(值域见附录 A.7);空或 ALL 为全量
page / sizequery分页,默认 1 / 50
{id}path详情必填案件 ID(数字串)

响应参数data.items[]

字段类型说明
caseIdstring案件 ID
caseNostring案件编号
cardholderIdstring持卡人 ID
merchantIdstring商户 ID
targetLevelstring目标认证等级(见附录 A.4)
statusstring案件状态
fullNamestring姓名(脱敏)
resubmitCountnumber补件次数
resubmitFieldsarray需补件字段清单
publicRejectReasonstring \null
idFrontFileId / idBackFileIdstring \null
submittedAt / reviewedAtstring \null

响应示例

json
{
  "code": 0,
  "message": "success",
  "data": {
    "total": 1,
    "page": 1,
    "size": 50,
    "items": [
      {
        "caseId": "5001",
        "caseNo": "KYC5001",
        "cardholderId": "10001",
        "merchantId": "1001",
        "targetLevel": "L2",
        "status": "PENDING_MERCHANT",
        "fullName": "张*三",
        "resubmitCount": 0,
        "resubmitFields": [],
        "publicRejectReason": null,
        "idFrontFileId": "f-001",
        "idBackFileId": "f-002",
        "submittedAt": "2026-01-15T08:00:00",
        "reviewedAt": null
      }
    ]
  }
}

业务规则

规则说明
只读KYC 档案的创建与提交经商户门户办理(代填入口),本通道仅提供查询
脱敏姓名脱敏输出(如 张*三);不返回证件影像内容与审核内部字段
存在性跨商户或不存在按 errorCode=AUTH_403 / KYC_404 处理,均不返回案件内容
结果通知审核结果同步推送 kyc.approved / kyc.rejected / kyc.resubmit_required(见 §6.7)

5.9 Webhook 查询

接口

接口方法与路径说明
端点列表GET /webhooks分页查询 Webhook 端点配置(只读,不含密钥)
端点详情GET /webhooks/{id}查询单个端点配置
投递记录GET /webhooks/{id}/deliveries分页查询投递记录(含重试信息)

接口说明:查询 Webhook 端点配置接口说明:查询 Webhook 端点配置(只读,响应不含签名密钥)与投递记录;用于自助排查回调送达情况。

请求

bash
curl -sS "https://<api-host>/open/api/v1/webhooks?page=1&size=50"
curl -sS "https://<api-host>/open/api/v1/webhooks/971322588/deliveries?page=1&size=50"

请求参数page / size,分页,默认 1 / 50;{id} 为端点 ID(数字串)。

响应参数 —— 端点GET /webhooksGET /webhooks/{id}

字段类型说明
endpointIdstring端点 ID
subscriberTypestring订阅主体类型(如 MERCHANT
subscriberIdstring订阅主体 ID
urlstring回调地址
eventsarray已订阅事件名列表(见 §6.7)
statusstring端点状态:ACTIVE / PAUSED / DISABLED(见附录 A.6)
consecutiveFailuresnumber连续失败次数
createdAt / updatedAtstring创建 / 更新时间
json
{
  "code": 0,
  "message": "success",
  "data": {
    "total": 1,
    "page": 1,
    "size": 50,
    "items": [
      {
        "endpointId": "971322588",
        "subscriberType": "MERCHANT",
        "subscriberId": "1001",
        "url": "https://example.com/hook",
        "events": ["rate.merchant_changed"],
        "status": "ACTIVE",
        "consecutiveFailures": 0,
        "createdAt": "2026-01-15T08:00:00",
        "updatedAt": "2026-01-15T08:00:00"
      }
    ]
  }
}

响应参数 —— 投递记录GET /webhooks/{id}/deliveries

字段类型说明
deliveryIdstring投递 ID
eventIdstring事件 ID
eventTypestring事件名
endpointIdstring端点 ID
statusstring投递状态(见附录 A.6)
attemptCountnumber已尝试次数
retryCountnumber已重试次数
nextAttemptAtstring \null
lastHttpStatusnumber \null
lastErrorstring \null
retryDelayMinutesUsedarray已使用的重试间隔(分钟)
createdAt / succeededAtstring \null
json
{
  "code": 0,
  "message": "success",
  "data": {
    "total": 1,
    "page": 1,
    "size": 50,
    "items": [
      {
        "deliveryId": "9001",
        "eventId": "evt-001",
        "eventType": "rate.merchant_changed",
        "endpointId": "971322588",
        "status": "SUCCEEDED",
        "attemptCount": 1,
        "retryCount": 0,
        "nextAttemptAt": null,
        "lastHttpStatus": 200,
        "lastError": null,
        "retryDelayMinutesUsed": [],
        "createdAt": "2026-01-15T08:05:00",
        "succeededAt": "2026-01-15T08:05:01"
      }
    ]
  }
}

业务规则

规则说明
只读本通道仅提供查询;端点的创建、修改、删除、测试与失败重发请在商户控制台完成(见 §6.1)
不含密钥响应永不返回端点签名密钥
排查路径投递失败原因与重试计划请结合投递记录与 §6.6 重试机制排查

5.10 划转

接口

接口方法与路径说明
发起划转POST /merchant-credits商户通道头寸划入持卡人账户
划转列表GET /merchant-credits分页查询划转单
划转详情GET /merchant-credits/{id}按划转单号查询(提交后轮询用)

接口说明:将商户通道头寸划入本商户持卡人账户接口说明:将商户通道头寸划入本商户持卡人账户(仅此方向,无逆向接口)。签名认证即二次验证,无需门户动态口令。大额划转进入人工复核(详见业务规则)。

请求

bash
curl -sS -X POST "https://<api-host>/open/api/v1/merchant-credits" \
  -H "Idempotency-Key: <uuid>" \
  -H "Content-Type: application/json" \
  -d '{"cardholderId":"10001","amount":"100.00","currency":"USD"}'
  • 须携带 Idempotency-Key;主体取自凭证,请勿在请求体传入商户标识

请求参数

字段类型必填说明
cardholderIdstring目标持卡人 ID(须为本商户名下)。亦接受 cardholder_id,值为 string
amountstring划转金额,大于 0,最多 2 位小数
currencystring币种,缺省 USD;其他币种不支持

响应参数data

字段类型说明
creditIdstring划转单号(幂等重试返回同一单号)
statusstring划转状态:PENDING_REVIEW 复核中 / CREDITED 已入账 / FAILED_ROLLED_BACK 失败已冲回 / REJECTED 已驳回
amountstring划转金额
currencystring币种
transferHoldstring当前冻结头寸金额(复核中大于 0,终态为 0
accountVersionnumber头寸版本号(并发冲突重试时使用)
idempotentboolean是否为幂等重试命中(true 表示返回首次结果,未执行新划转)
availableForCreditstring当前可划转额度

业务规则

规则说明
幂等同 Key 同参重放返回首次结果;同 Key 异参返回 1009;缺 Key 返回 VAL_400Idempotency-Key 最长 64 字符
额度划转金额不得超过可划转额度(见 §5.7 availableForCredit),不足返回 3406
大额复核单笔超过 $50,000 或「商户×持卡人」24 小时滚动累计超过 $50,000 时进入 PENDING_REVIEW 并冻结对应头寸;复核期间不可撤销,审核完成后更新为 CREDITEDREJECTED
目标校验持卡人须为本商户名下、KYC 达标且账户状态正常,否则返回 3407
到账通知入账后平台向持卡人发送站内信;本操作不产生 Webhook 通知transfer.completed 事件对应账户↔卡拨付,与划转无关)

查询

划转列表 GET /merchant-credits —— 请求参数:statuscardholderIdpage / size(默认 1 / 50);响应参数(data.items[]

字段类型说明
creditIdstring划转单号
cardholderMaskstring持卡人标识(脱敏)
amountstring划转金额
currencystring币种
statusstring划转状态
transferHoldstring冻结头寸金额
reviewReasonstring \null
createdAtstring创建时间
completedAtstring \null

划转详情 GET /merchant-credits/{id} —— 用于提交后轮询;他商户或不存在均为 errorCode=MCC_404;响应参数(data

字段类型说明
creditId / status / amount / currency / transferHoldstring同提交响应
accountVersionnumber头寸版本号
cardholderIdstring持卡人 ID
reviewReasonstring \null
reviewedBy / reviewedAtstring \null
reviewDeadline / escalationAtstring \null
createdAt / updatedAtstring创建 / 更新时间
availableForCreditstring当前可划转额度
timelinearray划转状态时间线(状态与时间)

错误码

HTTPcodeerrorCode说明
2001001VAL_400参数错误(缺 Idempotency-Key、金额格式非法等)
20010091009Idempotency-Key 但参数不一致
20010081008并发冲突(头寸版本冲突,请按 accountVersion 重试)
20034063406可划转额度不足
20034073407目标持卡人不满足划转条件
2002001MCC_404划转单不存在或不属于本商户

5.11 申请开卡

接口

接口方法与路径说明
提交申请POST /card-applications为持卡人申请开卡,返回申请单号
查询状态GET /card-applications/{applicationId}按申请单号轮询状态

接口说明接口说明

为商户名下持卡人申请开卡。提交后平台异步受理并返回申请单号;商户可凭申请单号轮询状态,开卡成功后平台推送 card.issued 通知(见 §6.8)。

支持范围:虚拟卡产品(产品目录中 cardType=VIRTUAL 的产品)。实体卡请在商户门户办理。

请求

bash
curl -sS -X POST "https://<api-host>/open/api/v1/card-applications"   -H "Idempotency-Key: <uuid>"   -d '{"cardholder_id":"10001","product_id":"880100"}'
  • 所需 scope:issue;须携带 Idempotency-Key
  • 主体取自凭证,请勿在请求体传入商户标识

请求参数

字段类型必填说明
cardholder_idstring持卡人 ID。须为本商户名下、且 KYC 等级满足开卡要求的持卡人
product_idstring卡产品 ID(虚拟卡产品)。产品目录请经商户门户「卡片产品」获取

响应参数data

字段类型说明
applicationIdstring申请单号(数字串),轮询凭据
applicationNostring申请单业务编号(OCA- 前缀)
statusstring申请状态:PENDING 已受理 / PROCESSING 处理中 / APPROVED 开卡成功 / FAILED 开卡失败
cardIdstring \null
failReasonstring \null
createdAtstring申请受理时间,ISO-8601 UTC

响应示例

json
{
  "code": 0,
  "message": "success",
  "data": {
    "applicationId": "9900001",
    "applicationNo": "OCA-9900001",
    "status": "APPROVED",
    "cardId": "123456",
    "failReason": null,
    "createdAt": "2026-09-12T08:00:00Z"
  }
}

查询申请状态

GET /open/api/v1/card-applications/{applicationId}data 结构与提交响应一致。他商户或不存在的申请单按不存在处理(errorCode=CARD_404)。

业务规则

规则说明
幂等Idempotency-Key 同参数重放返回首次受理结果,不重复受理;同 Key 参数不同返回 1009;缺 Key 返回 VAL_400
受理与终态提交后平台同步执行开卡;提交响应通常即为终态(APPROVED / FAILED),也可经查询接口轮询
校验失败参数、持卡人资格或产品不符合要求时,不产生申请单、不发生费用
执行失败申请单进入 FAILED 终态并附 failReason,可换用新的 Idempotency-Key 重新提交;若提交时出现系统级异常,请按错误响应指引稍后查询,勿直接以原 Key 重试
开卡费用按产品资费自商户通道资金中扣收
资金入卡开卡后如需注资,请经划转接口(§5.10)或商户门户办理

错误码

HTTPcodeerrorCode说明
2001001VAL_400参数错误(缺 Idempotency-Key、产品已下架、非虚拟卡产品等)
20010091009Idempotency-Key 但参数不一致
20010081008同一 Idempotency-Key 的申请正在处理中,请稍后查询
2009000PROD_404卡产品不存在
20033013301持卡人档案不存在或 KYC 等级不足
2001003AUTH_403持卡人不属于本商户

6. Webhook 异步通知

平台在业务事件发生后,通过 HTTP POST(JSON) 主动通知商户服务端。通知为单向推送:商户无需(也不能)通过本通道向平台发起请求;查询类需求请使用 §5.9 的 Webhook 查询接口。

项目约定
方向平台 → 商户(商户服务端接收)
方法与编码POSTContent-Type: application/json; charset=UTF-8
触发时机业务事务提交后异步发出(AFTER_COMMIT);通知失败不影响业务主流程
触发延迟通常秒级;受重试计划影响见 §6.6
接收地址商户在控制台为每个 endpoint 配置的 HTTPS URL(≤2048 字符)
签名密钥商户创建 endpoint 时自行填写的 secret(≥16 字符),请妥善保管
超时连接与读取均 5 秒
成功判定商户返回 HTTP 2xx 即视为投递成功;其余状态码或超时均判失败并进入重试

6.1 订阅管理

Webhook endpoint 的创建、修改、删除、测试与一键重发在商户控制台完成(设置中心 → Webhook;对应门户接口 /merchant/api/v1/webhooks),开放 API 侧仅提供只读查询(§5.9)。规则:

规则说明
URL必须 HTTPS,长度 ≤2048 字符
secret必填,≥16 字符;仅创建时展示一次,遗忘须更换
事件订阅按 §6.8 事件目录勾选;同一事件最多配置 3 个不同 URL
试投递控制台「测试」按钮:向该 endpoint 推送一条 data={"ping":true,"test":true,"endpoint_id":…} 的连通性通知,id 形如 evt_test_<雪花ID>
一键重发仅对终态为 FAILED / ABORTED 的投递生效;重发不重置已尝试次数

6.2 通知请求头

Header说明
Content-Typeapplication/json; charset=UTF-8
X-Signature通知签名,HMAC-SHA256 小写 hex(64 位),见 §6.3
X-Timestamp通知发起时刻的 Unix 级时间戳
X-Event事件名,与报文 event 字段一致(如 deposit.credited
X-Event-Id事件 ID,与报文 id 字段一致
注意

注意:请求头 X-Timestamp;报文内 created_at 为 ISO-8601 UTC(带 Z 后缀)。两者口径不同,请勿混用。

6.3 通知报文与签名验证

通知报文信封(固定字段顺序):

json
{
  "id": "evt_17_3f9c2a1b8d4e",
  "event": "deposit.credited",
  "created_at": "2026-09-13T01:23:45.123Z",
  "merchant_id": "MCH_100",
  "data": { }
}
字段类型说明
idstring事件 ID,全局唯一,格式 evt_<序列>_<12位随机串>幂等去重键
eventstring事件名,见 §6.8 目录
created_atstring事件创建时刻,ISO-8601 UTC(yyyy-MM-dd'T'HH:mm:ss.SSS'Z'
merchant_idstring商户标识,MCH_ 前缀 + 商户数字 ID
dataobject事件业务数据,逐事件定义见 §6.9

签名算法

text
X-Signature = HMAC-SHA256(key = endpoint secret 的 UTF-8 字节,
                          msg = 完整原始请求 Body)
  • 签名串是原始 Body 字节——请勿将 Body 反序列化后再重新序列化参与验签(字段顺序或空白变化会导致验签失败);
  • 签名不包含任何 Header(含 X-Timestamp);
  • 输出为 64 位小写 hex。

验签步骤(建议顺序):

  1. 读取 X-Timestamp(秒),校验与当前时间偏差 ≤ 5 分钟,超出直接拒绝(防重放);
  2. 读取原始请求 Body(字节级,不做任何重新序列化);
  3. 以 endpoint secret 为密钥计算 HMAC-SHA256(secret, body)
  4. X-Signature 比对(建议常量时间比较,防时序攻击);
  5. 验签通过后按 id 幂等去重(同一 id 可能因重试收到多次,见 §6.6),再处理业务。

验签示例(Python)

python
import hmac, hashlib, time

def verify(body: bytes, signature: str, secret: str, ts_header: str) -> bool:
    if abs(time.time() - int(ts_header)) > 300:        # 1. 时间窗(秒)
        return False
    expected = hmac.new(secret.encode("utf-8"), body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature)    # 2+3+4. 原始 Body + 常量时间比较

验签示例(Java)

java
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.time.Instant;

static boolean verify(byte[] rawBody, String signature, String secret, String tsHeader) throws Exception {
    if (Math.abs(Instant.now().getEpochSecond() - Long.parseLong(tsHeader)) > 300) return false;
    Mac mac = Mac.getInstance("HmacSHA256");
    mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
    byte[] digest = mac.doFinal(rawBody);
    StringBuilder hex = new StringBuilder();
    for (byte b : digest) hex.append(String.format("%02x", b));
    return java.security.MessageDigest.isEqual(
            hex.toString().getBytes(StandardCharsets.UTF_8),
            signature.getBytes(StandardCharsets.UTF_8));
}

6.4 响应要求与幂等处理

  • 商户处理完成后应返回任意 2xx(如 200);非 2xx 或 5 秒内未响应视为失败,触发重试;
  • 平台不解析商户响应体;
  • 同一事件可能因重试送达多次:请以报文 id(或 X-Event-Id)做幂等键,先查重再落库;
  • 建议先快速落库/入队再异步处理业务,避免复杂逻辑超出 5 秒超时。

6.5 数据安全与脱敏

平台通知报文永不包含完整卡号(PAN)、CVV、密码等敏感要素;卡相关事件仅返回卡号后四位 last4。商户也不应在接收日志中记录多余敏感字段。若报文因故包含键名含 pan / cvv / card_number / password 的字段,平台侧会在组装时自动剔除。

6.6 重试机制与 endpoint 状态

尝试时机
首次事件发生后即时
第 1 次重试失败后 1 分钟
第 2 次重试再失败后 5 分钟
第 3 次重试再失败后 15 分钟
  • 共计最多 4 次尝试(首次 + 3 次重试);全部失败后该投递标记为 FAILED,不再自动重试;
  • 某条投递重试耗尽仍失败,所属 endpoint 会被置为 PAUSED(暂停自动投递,避免持续打挂商户端);商户可在控制台修复后对该投递一键重发
  • 同一 endpoint 连续失败累计达 10 次会被自动置为 DISABLED(禁用);任一次成功即清零连续失败计数;
  • 投递状态值:PENDING(待首投)/ SUCCESS / RETRYING(等待重试)/ FAILED(重试耗尽)/ ABORTED(endpoint 已暂停或禁用,不再投递);
  • 排查入口:控制台投递记录(含每次尝试的 HTTP 状态码与错误摘要),或开放 API GET /webhooks/{id}/deliveries

6.7 事件目录

19 个事件。持卡人交易、KYC、提现类事件仅向商户主体订阅开放;settlement.postedposition.*rate.merchant_changed 另对代理主体开放。

事件事件名触发时机data 关键字段
充值入账成功deposit.credited持卡人充值入账成功amount currency deposit_id cardholder_id from_in_transit
充值入账异常deposit.exception充值入账异常amount currency deposit_id cardholder_id exception_code reverse_in_transit
账户划拨完成transfer.completed账户→卡划拨成功amount currency transfer_id account_id card_id last4
开卡成功card.issued开卡成功card_id cardholder_id product_id last4 status
卡片状态变更card.status_changed卡片状态变更card_id action previous_status new_status reason_type reason_detail last4
交易授权成功transaction.authorized交易授权成功amount currency auth_id card_id channel_tx_id last4
交易授权被拒transaction.declined交易授权被拒amount currency auth_id card_id channel_tx_id decline_code last4
交易清算完成transaction.cleared交易清算完成amount currency clearing_id card_id channel_clear_id channel_tx_id applied_amount shortfall last4
交易退款过账transaction.refunded强制退款/赔付过账refund_id fund_subject amount currency card_id cardholder_id
KYC 审核通过kyc.approvedKYC 审核通过case_id cardholder_id kyc_level
KYC 审核驳回kyc.rejectedKYC 审核驳回case_id cardholder_id reason
KYC 补件重提kyc.resubmit_requiredKYC 要求补件重提case_id cardholder_id resubmit_fields
提现申请受理withdrawal.submitted提现申请已受理amount currency withdrawal_id withdrawal_no subject_type subject_id
提现打款成功withdrawal.completed提现打款成功amount currency withdrawal_id withdrawal_no result bank_reference subject_type subject_id
提现打款失败withdrawal.rejected提现打款失败/退票withdrawal.completed
佣金结算过账settlement.posted商户佣金 T+1 结算过账amount currency entry_id batch_id settlement_kind
头寸充值入账position.topup_credited通道头寸充值入账amount currency topup_id
头寸调回完成position.return_completed通道头寸调回完成amount currency return_id bank_reference
商户费率变更rate.merchant_changed商户费率变更merchant_id product_id rate_version

6.8 逐事件通知报文

以下 data 字段与平台实际推送一致。未标注「条件返回」的字段每次通知必返;金额一律为 string;资源 ID 在通知报文中为 JSON number(与开放 API 响应的 string 口径不同,请分别处理)。

充值入账成功 deposit.credited

持卡人充值(链上或通道)入账成功后推送。

json
{
  "id": "evt_17_3f9c2a1b8d4e",
  "event": "deposit.credited",
  "created_at": "2026-09-13T01:23:45.123Z",
  "merchant_id": "MCH_100",
  "data": {
    "amount": "10.50000000",
    "currency": "USD",
    "deposit_id": 10001,
    "cardholder_id": 1001,
    "from_in_transit": false
  }
}
字段类型必返说明
amountstring入账金额(十进制字符串)
currencystring币种,ISO 3 位
deposit_idnumber充值单 ID
cardholder_idnumber持卡人 ID
from_in_transitbooleantrue=由在途转可用(此前已发过检测通知);false=直接入可用

充值入账异常 deposit.exception

充值入账异常(如链上金额与订单不符、低于起充金额等)后推送。异常处理后商户可在控制台按指引处置。

json
{
  "id": "evt_18_a1b2c3d4e5f6",
  "event": "deposit.exception",
  "created_at": "2026-09-13T01:24:10.456Z",
  "merchant_id": "MCH_100",
  "data": {
    "amount": "5.00000000",
    "currency": "USD",
    "deposit_id": 10002,
    "cardholder_id": 1001,
    "exception_code": "BELOW_MIN",
    "reverse_in_transit": false
  }
}
字段类型必返说明
amount / currencystring金额 / 币种
deposit_idnumber充值单 ID
cardholder_idnumber持卡人 ID
exception_codestring异常码,值域见附录 A.5
reverse_in_transitboolean在途金额是否已冲回

账户划拨完成 transfer.completed

账户→卡拨付(ACCOUNT_TO_CARD)成功后推送。

json
{
  "id": "evt_21_b2c3d4e5f6a1",
  "event": "transfer.completed",
  "created_at": "2026-09-13T01:30:00.000Z",
  "merchant_id": "MCH_100",
  "data": {
    "amount": "50.00000000",
    "currency": "USD",
    "transfer_id": 3001,
    "account_id": 2001,
    "card_id": 123456,
    "last4": "1234"
  }
}
字段类型必返说明
amount / currencystring拨付金额 / 币种
transfer_idnumber拨付单 ID
account_idnumber资金账户 ID
card_idnumber卡 ID
last4string条件卡号后四位

开卡成功 card.issued

开卡成功(门户开卡或开放 API 申请开卡通过)后推送。

json
{
  "id": "evt_22_c3d4e5f6a1b2",
  "event": "card.issued",
  "created_at": "2026-09-13T01:32:00.000Z",
  "merchant_id": "MCH_100",
  "data": {
    "card_id": 123456,
    "cardholder_id": 1001,
    "product_id": 880100,
    "last4": "1234",
    "status": "ACTIVE"
  }
}
字段类型必返说明
card_idnumber卡 ID
cardholder_idnumber持卡人 ID
product_idnumber卡产品 ID
last4string条件卡号后四位
statusstring条件发卡后状态,值域见附录 A.1(虚拟卡通常 ACTIVE

卡片状态变更 card.status_changed

卡片状态变更(冻结、解冻、销卡、激活、挂失等)后推送。

json
{
  "id": "evt_23_d4e5f6a1b2c3",
  "event": "card.status_changed",
  "created_at": "2026-09-13T01:35:00.000Z",
  "merchant_id": "MCH_100",
  "data": {
    "card_id": 123456,
    "action": "FREEZE",
    "previous_status": "ACTIVE",
    "new_status": "FROZEN",
    "reason_type": "USER_REQUEST",
    "reason_detail": "merchant-request",
    "last4": "1234"
  }
}
字段类型必返说明
card_idnumber卡 ID
actionstring条件变更动作,值域见附录 A.2
previous_status / new_statusstring条件变更前 / 后状态,值域见附录 A.1
reason_typestring条件原因分类,值域见附录 A.3
reason_detailstring条件原因补充说明
last4string条件卡号后四位

交易授权成功 transaction.authorized

交易授权成功后推送。

json
{
  "id": "evt_24_e5f6a1b2c3d4",
  "event": "transaction.authorized",
  "created_at": "2026-09-13T02:00:00.000Z",
  "merchant_id": "MCH_100",
  "data": {
    "amount": "12.34000000",
    "currency": "USD",
    "auth_id": 4001,
    "card_id": 123456,
    "channel_tx_id": "CHN-AUTH-889",
    "last4": "1234"
  }
}
字段类型必返说明
amount / currencystring授权金额 / 币种
auth_idnumber授权记录 ID
card_idnumber卡 ID
channel_tx_idstring渠道交易流水号
last4string条件卡号后四位

交易授权被拒 transaction.declined

交易授权被拒后推送。

json
{
  "id": "evt_25_f6a1b2c3d4e5",
  "event": "transaction.declined",
  "created_at": "2026-09-13T02:01:00.000Z",
  "merchant_id": "MCH_100",
  "data": {
    "amount": "99.00000000",
    "currency": "USD",
    "auth_id": 4002,
    "card_id": 123456,
    "channel_tx_id": "CHN-AUTH-890",
    "decline_code": "INSUFFICIENT_FUNDS",
    "last4": "1234"
  }
}
字段类型必返说明
transaction.authorized
decline_codestring条件拒绝原因码(稳定字符串,可供商户分类处理)

交易清算完成 transaction.cleared

交易清算完成后推送。amount 为清算金额,applied_amount 为实际入账金额;二者不等(shortfall=true)即为短账场景。

json
{
  "id": "evt_26_a1b2c3d4e5f7",
  "event": "transaction.cleared",
  "created_at": "2026-09-13T03:00:00.000Z",
  "merchant_id": "MCH_100",
  "data": {
    "amount": "12.34000000",
    "currency": "USD",
    "clearing_id": 5001,
    "card_id": 123456,
    "channel_clear_id": "CHN-CLR-77",
    "channel_tx_id": "CHN-AUTH-889",
    "applied_amount": "12.34000000",
    "shortfall": false,
    "last4": "1234"
  }
}
字段类型必返说明
amount / currencystring清算金额 / 币种
clearing_idnumber清算记录 ID
card_idnumber卡 ID
channel_clear_idstring渠道清算流水号
channel_tx_idstring关联的渠道授权流水号
applied_amountstring条件实际入账金额(短账等场景返回)
shortfallboolean条件是否短账
last4string条件卡号后四位

交易退款过账 transaction.refunded

强制退款 / 赔付过账后推送(平台侧资金调整,非消费冲正)。

json
{
  "id": "evt_27_b2c3d4e5f6a8",
  "event": "transaction.refunded",
  "created_at": "2026-09-13T03:10:00.000Z",
  "merchant_id": "MCH_100",
  "data": {
    "refund_id": 6001,
    "fund_subject": "PLATFORM_OPEX",
    "amount": "12.00",
    "currency": "USD",
    "card_id": null,
    "cardholder_id": 1001
  }
}
字段类型必返说明
refund_idnumber退款过账记录 ID
fund_subjectstring资金科目(平台内部分账标识)
amount / currencystring退款金额 / 币种
card_idnumber条件关联卡 ID(可能为 null
cardholder_idnumber持卡人 ID

KYC 审核结果通知 kyc.approved / kyc.rejected / kyc.resubmit_required

持卡人 KYC 审核结果通知,三个事件同构:

json
{
  "id": "evt_28_c3d4e5f6a1b9",
  "event": "kyc.approved",
  "created_at": "2026-09-13T04:00:00.000Z",
  "merchant_id": "MCH_100",
  "data": {
    "case_id": 5001,
    "cardholder_id": 1001,
    "kyc_level": "L2"
  }
}
字段类型必返说明
case_idnumberKYC 案件 ID
cardholder_idnumber持卡人 ID
kyc_levelstringapproved 条件通过的等级,L0 / L1 / L2 / L3
reasonstringrejected 条件驳回原因(面向商户的可读摘要)
resubmit_fieldsstringresubmit_required 条件需补件的字段清单(序列化为字符串形式)

提现申请受理 withdrawal.submitted

提现申请受理后推送(商户 / 持卡人主体)。

json
{
  "id": "evt_29_d4e5f6a1b2c0",
  "event": "withdrawal.submitted",
  "created_at": "2026-09-13T05:00:00.000Z",
  "merchant_id": "MCH_100",
  "data": {
    "amount": "500.00000000",
    "currency": "USD",
    "withdrawal_id": 7001,
    "withdrawal_no": "WDR-M-7001",
    "subject_type": "MERCHANT",
    "subject_id": 100
  }
}
字段类型必返说明
amount / currencystring提现金额 / 币种
withdrawal_idnumber提现单 ID
withdrawal_nostring提现单号(WDR-M-/WDR-A-/USDT-RETURN- 前缀 + ID)
subject_typestring主体类型,CARDHOLDER / MERCHANT / AGENT
subject_idnumber主体 ID

提现打款结果通知 withdrawal.completed / withdrawal.rejected

提现打款结果通知,两个事件 data 同构,result 与事件名对应(SUCCESS/COMPLETEDcompletedFAILED/RETURNEDrejected):

json
{
  "id": "evt_30_e5f6a1b2c3d1",
  "event": "withdrawal.completed",
  "created_at": "2026-09-13T06:00:00.000Z",
  "merchant_id": "MCH_100",
  "data": {
    "amount": "500.00000000",
    "currency": "USD",
    "withdrawal_id": 7001,
    "withdrawal_no": "WDR-M-7001",
    "result": "SUCCESS",
    "bank_reference": "BK-20260913-001",
    "subject_type": "MERCHANT",
    "subject_id": 100
  }
}
字段类型必返说明
withdrawal.submitted 公共字段
resultstring打款结果:SUCCESS / RETURNED / FAILED
bank_referencestring条件银行/渠道参考号

佣金结算过账 settlement.posted

商户佣金 T+1 结算过账后推送。

json
{
  "id": "evt_31_f6a1b2c3d4e2",
  "event": "settlement.posted",
  "created_at": "2026-09-14T01:00:00.000Z",
  "merchant_id": "MCH_100",
  "data": {
    "amount": "88.00000000",
    "currency": "USD",
    "entry_id": 8001,
    "batch_id": "STL-20260913",
    "settlement_kind": "COMMISSION_ENTRY"
  }
}
字段类型必返说明
amount / currencystring结算金额 / 币种
entry_idnumber结算分录 ID
batch_idstring结算批次号
settlement_kindstring结算类型,当前恒为 COMMISSION_ENTRY

头寸资金通知 position.topup_credited / position.return_completed

通道头寸充值入账 / 调回完成后推送,两个事件 data 同构:

json
{
  "id": "evt_32_a1b2c3d4e5f3",
  "event": "position.topup_credited",
  "created_at": "2026-09-13T07:00:00.000Z",
  "merchant_id": "MCH_100",
  "data": {
    "amount": "10000.00000000",
    "currency": "USD",
    "topup_id": 9001
  }
}
字段类型必返说明
amount / currencystring金额 / 币种
topup_id / return_idnumber充值单 / 调回单 ID(字段名随事件不同)
bank_referencestringreturn_completed 条件银行/渠道参考号

商户费率变更 rate.merchant_changed

商户费率变更后推送。

json
{
  "id": "evt_33_b2c3d4e5f6a4",
  "event": "rate.merchant_changed",
  "created_at": "2026-09-13T08:00:00.000Z",
  "merchant_id": "MCH_100",
  "data": {
    "merchant_id": 100,
    "product_id": 880100,
    "rate_version": 3
  }
}
字段类型必返说明
merchant_idnumber商户 ID
product_idnumber卡产品 ID
rate_versionnumber变更后的费率版本号(递增)

7. 常见问题

签名一直 403? GET 的 BODY 不要写成 {};PATH 不要带 ?;时间戳用秒;HMAC 的 key 用 hex 字符串的字节。

timestampX-Timestamp 差三个数量级? 请求头是秒,响应当中是毫秒。

/orders 是刷卡流水吗? 不是。这是用户充值单。卡交易明细不在 Open API。

可以取完整卡号吗? 不可以。只有 last4

冻卡要不要 Idempotency-Key? 要。卡片冻结 / 解冻 / 销卡 / status、划转与申请开卡都必须带;同 Key 同参返回首次结果,同 Key 异参报 1009

开卡申请 POST /card-applications 返回 status=FAILED 是出错了吗? 不是。code=0 表示本次调用成功;data.status=FAILED 是申请单终态(failReason 为失败原因码)。可修复原因(如头寸不足)后换用新的 Idempotency-Key 重新提交。若遇到系统级错误响应(非 200 业务体),请勿直接以原 Key 重试——先以 GET /card-applications/{applicationId} 查询确认状态。

W8.0 升级后旧客户端要改什么? 若旧客户端把 ID 按 number 解析,需改为按 string 处理(见 §4 ID 类型总表);调用 cardholders / kyc / webhooks 列表的客户端需适配新的 {total, page, size, items} 信封。请求体中账户/持卡人 ID 传历史 number 仍可被接受,但建议尽快改为 string。

W8.1 升级后旧客户端要改什么? GET /card-statements 由裸数组改为分页对象(破坏性):原 data[0].period 需改为 data.items[0].period,并适配 total / page / sizeGET /finance/positionsGET /reconciliations增字段:原读 total / items 的代码无需改动即可继续工作,建议逐步补上 page / size 回显与翻页参数。GET /cardsGET /cards/{id}/transactions 的响应契约不变(/cards 数据来源下沉数据库分页,透明)。

W8.2 升级后旧客户端要改什么? 无破坏性变更,无需改动。GET /cards/{id}/transactions 修复了数据完整性缺陷(历史版本在商户交易量超过 1 万条时会静默截断单卡交易列表;W8.2 起返回完整真实条数,响应契约与行项字段不变)。/orders/deposits 的同义别名,新开发请使用 /deposits/orders 保留为兼容别名,不设下线日期。

W8.2 增补(2026-09-12)升级后旧客户端要改什么? 若有提现 / 对账集成:相关端点已移除(HTTP 404),请迁移至商户控制台(门户)操作。若集成卡片写操作:freeze / unfreeze / close / status 从本增补起必须携带 Idempotency-Key(缺头 VAL_400),并为每次业务操作生成唯一 Key。其余接口契约不变。

收不到 Webhook 通知,如何排查? 按顺序检查:① 控制台确认 endpoint 状态为 ACTIVEPAUSED/DISABLED 时自动投递已停止,见 §6.6);② 投递记录中查看最近投递的 HTTP 状态码与错误摘要(控制台或 GET /webhooks/{id}/deliveries);③ 确认接收地址为公网可达的 HTTPS 且未拦截平台出口 IP;④ 确认商户端在 5 秒内返回了 2xx(复杂业务建议先落库后处理);⑤ 修复后用控制台「测试」发一条连通性通知,再对失败投递一键重发。

Webhook 验签一直失败? 高频原因:① 把 Body 反序列化后重新序列化再验签——必须用原始字节(字段顺序会变);② 时间窗单位搞错——X-Timestamp,窗口 ±300 秒;③ 密钥用错——是 endpoint 的 secret 原文(UTF-8 字节),不是 API Secret,也不是任何哈希;④ 忽略大小写——签名为小写 hex,比较时请勿改变大小写。

同一事件收到了多次通知,怎么办? 属正常重试行为(非 2xx 或超时会触发,见 §6.6)。请以报文 id(或 X-Event-Id)为幂等键先查重再处理;重复通知重复处理业务属商户侧缺陷。

通知报文里的 ID 是 number,开放 API 响应里却是 string? 两端口径不同:Webhook data 内资源 ID 为 JSON number(如 "card_id": 123456);开放 API 响应 ID 一律 string(§4 ID 类型总表)。分别按各自口径解析,勿混用。

沙箱 / 测试环境怎么联调 Webhook? 当前开放通道无独立沙箱环境。可在控制台对 endpoint 使用「测试」按钮发送连通性通知;事件级联调建议在低风险真实环境小金额进行。


8. 附录

A.1 卡片状态(status

含义
DRAFT草稿(未提交)
ISSUING开卡中
ACTIVE已激活可用
FROZEN已冻结
SUSPENDED已暂停
LOST已挂失
EXPIRING临期
CLOSED已销户
IN_STOCK在库(实体卡库存)
PENDING_ACTIVATION待激活(实体卡发卡后)

A.2 卡片状态变更动作(action

含义
FREEZE / UNFREEZE冻结 / 解冻
CLOSE销卡
SUSPEND / RESUME暂停 / 恢复
LOST挂失
MARK_EXPIRING标记临期
RENEW换卡续期
ACTIVATE激活
ALLOCATE发放(出库至持卡人)
RETURN_STOCK退回库存

A.3 状态变更原因分类(reason_type

含义
FRAUD_SUSPICION欺诈嫌疑
USER_REQUEST用户请求
EXPIRED到期
COMPLIANCE合规要求
OTHER其他

A.4 KYC 等级(kyc_level

含义
L0基础(未认证)
L1一级认证
L2二级认证
L3三级认证

A.5 充值异常码(exception_code

含义
USER_UNMATCHED付款人与订单不匹配
ADDRESS_MISMATCH充值地址与订单不匹配
BELOW_MIN低于最低充值金额
ASSET_NOT_SUPPORTED币种(资产)不支持
NETWORK_NOT_SUPPORTED链(网络)不支持
CHANNEL_APPLY_FAIL_<state>通道申请失败(<state> 为渠道状态码)
OTHER其他异常

A.7 KYC 案件状态(status

含义
DRAFT草稿(未提交)
SUBMITTED已提交
AUTO_REVIEW自动审核中
PENDING_MERCHANT待商户审核
PENDING_PLATFORM待平台审核
PENDING_RESUBMIT待补充材料
PENDING_LIVENESS / LIVENESS_PASSED活体检测中 / 已通过
APPROVED / REJECTED审核通过 / 驳回
EXPIRED / CANCELLED已过期 / 已取消

A.8 充值单状态(status

含义
DETECTED已检测到入金(在途)
PENDING_REVIEW待人工审核
CREDITED已入账
EXCEPTION异常(附异常码,见 A.5)
IGNORED已忽略(重复/迟到入金等)
REJECTED已驳回

A.6 Webhook 投递与 endpoint 状态

投递状态含义
PENDING待首次投递
SUCCESS投递成功(收到 2xx)
RETRYING投递失败,按 1m/5m/15m 计划等待重试
FAILED重试耗尽(共 4 次尝试)仍失败
ABORTEDendpoint 已暂停 / 禁用,放弃投递
endpoint 状态含义
ACTIVE正常投递
PAUSED有投递重试耗尽后被暂停(自动投递停止)
DISABLED连续失败达 10 次被禁用(或人工删除)

9. 变更记录

W8.2 增补 4(2026-09-13,文档审查修正)

仅文档修正,无接口契约变更(按逐端点审查结果修正文档与实现不一致处):

修正说明
§5.11 错误码表更正机读码更正为 PROD_404 / 3301 / AUTH_403(1003)/ 1008;受理与终态表述与实际执行模型对齐
§5.8 KYC状态示例与筛选值更正(值域见新增附录 A.7);证件影像字段注明仅详情返回
§5.10 划转补列表与详情响应字段表;更正通知说明(本操作不产生 Webhook);披露大额复核阈值 $50,000;补幂等键长度约束
§5.4 持卡人kycStatus 字段语义更正为 KYC 等级(L0L3/NONE);补详情响应字段表
§5.3 卡片操作补冻结 / 解冻 / 销卡前置条件与 CARD_409CHN_5021008 语义
§5.5 卡交易补交易行项完整字段表;详情支持参考号查询
§4 通用约定路径 ID 规则补充例外;租户隔离例外修正;错误码总表补全
附录新增 A.7 KYC 状态、A.8 充值单状态值域

W8.2 增补 3(2026-09-13,文档专业化与 Webhook 章节补全)

仅文档增强,无代码契约变更(端点、参数、错误码、capabilities 均不变):

变化说明
新增 §6 Webhook 异步通知通知机制总览、报文信封、签名验证(含 Python/Java 示例)、响应要求、重试与 endpoint 状态机、脱敏说明;19 个事件逐事件 payload 示例与字段表(与平台实际推送对齐)。
新增 §8 附录卡片状态 / 变更动作 / 原因分类 / KYC 等级 / 充值异常码 / 投递与 endpoint 状态等枚举值域表。
全文专业化重构对齐支付行业对接文档规范:补充文档信息表、目录、「必返」字段标注、枚举值域引用、FAQ 扩充(收不到通知 / 验签失败 / 重复通知等 5 条)。

W8.2 增补 2(2026-09-12,API-FUND-019 申请开卡)

新增能力(非破坏)

变化说明
新增 POST /card-applications(scope issue商户开放通道申请开卡:提交后异步受理,可经申请单号轮询状态;Idempotency-Key 必填;当前支持虚拟卡产品。见 §5.11。
新增 GET /card-applications/{applicationId}(scope read开卡申请单轮询;他商户按不存在处理(CARD_404)。
issue scope 落地POST /card-applicationsissue 的消费点;无 issue 的显式 scopes 密钥调用返回 403 OPEN_403
/status capabilities +2快照增至 28 条(示例已同步)。

W8.2 增补(2026-09-12,产品裁决)

能力收敛(破坏性)

变化说明
移除 GET/POST /withdrawalsGET /withdrawals/{id}GET /reconciliationsGET /reconciliations/{statementId}/download开放 API 不再提供提现与对账能力(含 /status capabilities 同步裁剪),调用返回 HTTP 404 NOT_FOUND。提现 / 对账请使用商户控制台(门户)。
卡片写操作强制 Idempotency-KeyPOST /cards/{id}/freeze · /unfreeze · /close · /status 缺头返回 VAL_400;同 Key 同参返回首次结果;同 Key 异参返回 1009

非破坏变更

  • POST /merchant-creditsIdempotency-Key 注解口径改为必填(与既有服务端强制校验对齐,缺头 VAL_400,行为语义不变)。
  • GET /orders/deposits)数据源下沉数据库分页,total 为筛选后真实总数;响应契约与分页夹紧语义不变。

W8.2(2026-09-10)

无对外契约破坏性变更。

数据完整性修复

接口变化
GET /cards/{id}/transactions改为单卡直达数据源:授权按卡 ID、清算按商户 ID 索引查询后合并,分页在应用层完成。修复历史缺陷:旧实现按商户交易全集(上限 10,000 条)拉取后内存按卡过滤,商户交易量超过 1 万时单卡交易会静默缺失。W8.2 起 total 为该卡真实交易条数,响应契约({total, page, size, items})与行项字段不变。

内部改进(契约不变)

  • GET /transactions(及导出 / 月度账单等商户侧卡交易聚合)数据源收窄:授权按卡集合(idx_card_ctime)、清算按商户(idx_merchant_time)索引查询,消除全表扫描;排序与合并口径不变。
  • GET /reconciliationsissues 商户过滤由表现层下沉至应用层(total 口径不变)。
  • /statusga 字段 W8.1 → W8.2;capabilities 快照不变(31 条,以实时返回为准)。

别名指引

  • /orders/deposits 的同义别名,新开发请使用 /deposits(语义更明确);/orders 保留为兼容别名,不设 sunset。

W8.1(2026-09-10)

破坏性变更(列表信封)

接口W8.0 及以前W8.1 起
GET /card-statements裸数组 data: [...]{total, page, size, items},query 增 page / size

非破坏变更(增字段 / 增参数)

接口变化
GET /finance/positionsdata{total, items} 增补为 {total, page, size, items};query 增 page / size
GET /reconciliationsstatementsissues 两块各自由 {total, items} 增补为 {total, page, size, items};query 增 page / size(同时作用于两块)

无契约变化的内部改进

  • GET /cards 分页下沉数据库:生产仓储按 merchantId + status 等 SQL 层过滤、计数与取页(原为拉取上限 10,000 条全集内存切片,超限时静默截断);响应契约({total, page, size, items})与行项字段不变。
  • /statusga 字段 W8.0 → W8.1;capabilities 快照不变(31 条,以实时返回为准)。

W8.0(2026-09-09)

破坏性变更(出参 ID number → string)

资源字段变化
GET /cards · GET /cards/{id}cardholderIdnumber → string
GET /merchant-credits/{id}cardholderIdnumber → string
GET /webhooks · GET /webhooks/{id}endpointId subscriberIdnumber → string
GET /webhooks/{id}/deliveriesdeliveryId endpointIdnumber → string
GET /reconciliations/{statementId}/downloadmerchantIdnumber → string
GET /reconciliationsissues.items[*]merchantIdnumber → string

破坏性变更(列表信封)

接口W7.1 及以前W8.0 起
GET /cardholders{merchantId, total, items}(无 page 参数){total, page, size, items},query 增 page / sizemerchantId 字段移除)
GET /kyc裸数组 data: [...]{total, page, size, items},query 增 page / size
GET /webhooks裸数组 data: [...]{total, page, size, items},query 增 page / size
GET /webhooks/{id}/deliveries裸数组 data: [...]{total, page, size, items},query 增 page / size

请求体契约变化(非破坏,双向兼容)

接口字段契约兼容性
POST /merchant-creditscardholderId(含 cardholder_id 别名)string历史 number 入参仍可解析
POST /withdrawalscommissionAccountId payoutAccountIdstring历史 number 入参仍可解析

非破坏改进

  • GET /cards 响应体类型化(JSON 形态不变,仍为 {total, page, size, items})。
  • 路径 {id} 非数字统一返回 VAL_400(code 1001),错误消息不回显原始输入。
  • POST /merchant-credits 请求体校验(@Valid)与提现申请对齐;缺字段返回 VAL_400 而非延迟到业务层报错。
  • /statusga 字段 W7.1 → W8.0;capabilities 快照更新为 31 条(以实时返回为准)。