API 参考

HTTP 端 API - 按量支付#

基于链上 Escrow 合约的流式支付通道。Buyer 开通支付通道并存入资金,Seller 通过链下 EIP-712 Voucher 累计消费,最终上链结算并退还剩余余额。

  • Base URL:https://web3.okx.com
  • 路径前缀:/api/v6/pay/mpp/session
  • Network:X Layer(chainId 196

认证#

所有接口均需通过 API Key 认证,请求头中携带以下字段:

Header必传描述
OK-ACCESS-KEYAPI Key
OK-ACCESS-SIGN请求签名
OK-ACCESS-PASSPHRASEAPI 密码短语
OK-ACCESS-TIMESTAMPISO 8601 时间戳
Content-TypePOST 请求需设为 application/json

所有响应统一使用业务包络:

json
{
  "code": "0",
  "msg": "success",
  "data": { /* 业务字段 */ }
}

业务错误时 code 为非 "0"datanull,错误码集中见文末 错误码 章节。


1. /api/v6/pay/mpp/session/open#

POST
/api/v6/pay/mpp/session/open

开通支付通道。支持两种模式:

  • transaction 模式:服务端代开,Buyer 提供 EIP-3009 授权,Broker 代为提交链上 openChannel 交易
  • hash 模式:客户端自行开通道,提供已广播的链上交易哈希供 Broker 验证

请求参数#

参数类型必传描述
challengeObject服务端签发的 Challenge 对象(原样回传),详见 Challenge
payloadObject支付凭证
payload.actionString固定 "open"
payload.typeString"transaction"(服务端代开)或 "hash"(客户端已开)
payload.channelIdString通道 ID(bytes32,客户端预计算)
payload.authorizationObject条件必填type="transaction" 时必填,EIP-3009 授权对象
payload.authorization.typeString条件必填固定 "eip-3009"
payload.authorization.fromString条件必填付款方地址
payload.authorization.toString条件必填Escrow 合约地址
payload.authorization.valueString条件必填存款金额(base units)
payload.authorization.validAfterString条件必填授权生效 Unix 时间戳
payload.authorization.validBeforeString条件必填授权过期 Unix 时间戳
payload.authorization.nonceString条件必填随机 bytes32
payload.signatureString条件必填type="transaction" 时必填,EIP-3009 签名(65 字节)
payload.hashString条件必填type="hash" 时必填,链上 open 交易哈希
payload.saltString随机 bytes32,用于计算 channelId
payload.authorizedSignerString委托签名地址,默认为 0x0000...0000
sourceString条件必填type="hash" 时必填,付款方 DID(did:pkh:eip155:196:0x...

响应参数#

参数类型描述
methodString固定值 "evm"
intentString固定值 "session"
statusString固定值 "success"
timestampStringRFC 3339 响应时间
channelIdString通道 ID(bytes32)
chainIdIntegerEVM chain ID,如 196
referenceString链上交易哈希(transaction 模式时返回)
depositString当前已知用户在链上的存款金额(base units)

请求示例 — hash 模式(客户端自行开通道)#

bash
curl --location --request POST 'https://web3.okx.com/api/v6/pay/mpp/session/open' \
--header 'Content-Type: application/json' \
--header 'OK-ACCESS-KEY: 37c541a1-****-****-****-10fe7a038418' \
--header 'OK-ACCESS-SIGN: leaV********3uw=' \
--header 'OK-ACCESS-PASSPHRASE: 1****6' \
--header 'OK-ACCESS-TIMESTAMP: 2023-10-18T12:21:41.274Z' \
--data '{
  "challenge": {
    "id": "kM9xPqWvT2nJrHsY4aDfEb",
    "realm": "api.llm-service.com",
    "method": "evm",
    "intent": "session",
    "request": "eyJ...",
    "expires": "2026-04-01T12:05:00Z"
  },
  "source": "did:pkh:eip155:196:0xaabbccddee11223344556677889900aabbccddee",
  "payload": {
    "action": "open",
    "type": "hash",
    "channelId": "0x6d0f4fdf1f2f6a1f6c1b0fbd6a7d5c2c0a8d3d7b1f6a9c1b3e2d4a5b6c7d8e9f",
    "hash": "0x9f8e7d6c5b4a39281700abcdef1234567890abcdef1234567890abcdef123456",
    "signature": "0xabcdef1234567890...",
    "authorizedSigner": "0x742d35cc6634c0532925a3b844bc9e7595f8fe00",
    "salt": "0xaaaa1234bbbb5678cccc9012dddd3456eeee7890ffff1234aaaa5678bbbb9012"
  }
}'

请求示例 — transaction 模式(服务端代开通道)#

bash
curl --location --request POST 'https://web3.okx.com/api/v6/pay/mpp/session/open' \
--header 'Content-Type: application/json' \
--header 'OK-ACCESS-KEY: 37c541a1-****-****-****-10fe7a038418' \
--header 'OK-ACCESS-SIGN: leaV********3uw=' \
--header 'OK-ACCESS-PASSPHRASE: 1****6' \
--header 'OK-ACCESS-TIMESTAMP: 2023-10-18T12:21:41.274Z' \
--data '{
  "challenge": {
    "id": "kM9xPqWvT2nJrHsY4aDfEb",
    "realm": "api.llm-service.com",
    "method": "evm",
    "intent": "session",
    "request": "eyJ...",
    "expires": "2026-04-01T12:05:00Z"
  },
  "payload": {
    "action": "open",
    "type": "transaction",
    "channelId": "0x6d0f4fdf1f2f6a1f6c1b0fbd6a7d5c2c0a8d3d7b1f6a9c1b3e2d4a5b6c7d8e9f",
    "authorization": {
      "type": "eip-3009",
      "from": "0xaabbccddee11223344556677889900aabbccddee",
      "to": "0x1234567890abcdef1234567890abcdef12345678",
      "value": "10000000",
      "validAfter": "0",
      "validBefore": "1743523500",
      "nonce": "0xaaaa1111bbbb2222cccc3333dddd4444eeee5555ffff6666aaaa7777bbbb8888"
    },
    "signature": "0xabcdef...eip3009sig",
    "authorizedSigner": "0x742d35cc6634c0532925a3b844bc9e7595f8fe00",
    "salt": "0xaaaa1234bbbb5678cccc9012dddd3456eeee7890ffff1234aaaa5678bbbb9012"
  }
}'

响应示例#

json
{
  "code": "0",
  "msg": "",
  "data": {
    "method": "evm",
    "intent": "session",
    "status": "success",
    "timestamp": "2026-04-01T12:04:30Z",
    "channelId": "0x6d0f4fdf1f2f6a1f6c1b0fbd6a7d5c2c0a8d3d7b1f6a9c1b3e2d4a5b6c7d8e9f",
    "chainId": 196,
    "reference": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",
    "deposit": "10000000"
  }
}

2. /api/v6/pay/mpp/session/topUp#

POST
/api/v6/pay/mpp/session/topUp

向已开通的支付通道追加存款。支持 transaction 模式(服务端代充)和 hash 模式(客户端自行充值)。

请求参数#

参数类型必传描述
challengeObject服务端签发的 Challenge 对象,详见 Challenge
payloadObject支付凭证
payload.actionString固定 "topUp"
payload.typeString"transaction"(服务端代充)或 "hash"(客户端已充)
payload.channelIdString通道 ID(bytes32)
payload.authorizationObject条件必填type="transaction" 时必填,EIP-3009 授权对象
payload.authorization.typeString条件必填固定 "eip-3009"
payload.authorization.fromString条件必填付款方地址
payload.authorization.toString条件必填Escrow 合约地址
payload.authorization.valueString条件必填追加金额(base units)
payload.authorization.validAfterString条件必填授权生效 Unix 时间戳
payload.authorization.validBeforeString条件必填授权过期 Unix 时间戳
payload.authorization.nonceString条件必填随机 bytes32
payload.signatureString条件必填type="transaction" 时必填,EIP-3009 签名(65 字节)
payload.hashString条件必填type="hash" 时必填,链上 topUp 交易哈希
payload.additionalDepositString本次追加的金额(base units)
payload.topUpSaltString随机 bytes32,topUp 操作必填
sourceString条件必填type="hash" 时必填,付款方 DID(did:pkh:eip155:196:0x...

响应参数#

参数类型描述
methodString固定值 "evm"
intentString固定值 "session"
statusString固定值 "success"
timestampStringRFC 3339 响应时间
channelIdString通道 ID(bytes32)
chainIdIntegerEVM chain ID,如 196
referenceString链上交易哈希(transaction 模式时返回)
depositString当前已知用户在链上的总存款金额(base units)

请求示例 — transaction 模式(服务端代充)#

bash
curl --location --request POST 'https://web3.okx.com/api/v6/pay/mpp/session/topUp' \
--header 'Content-Type: application/json' \
--header 'OK-ACCESS-KEY: 37c541a1-****-****-****-10fe7a038418' \
--header 'OK-ACCESS-SIGN: leaV********3uw=' \
--header 'OK-ACCESS-PASSPHRASE: 1****6' \
--header 'OK-ACCESS-TIMESTAMP: 2023-10-18T12:21:41.274Z' \
--data '{
  "payload": {
    "action": "topUp",
    "type": "transaction",
    "channelId": "0x6d0f4fdf1f2f6a1f6c1b0fbd6a7d5c2c0a8d3d7b1f6a9c1b3e2d4a5b6c7d8e9f",
    "authorization": {
      "type": "eip-3009",
      "from": "0xaabbccddee11223344556677889900aabbccddee",
      "to": "0x1234567890abcdef1234567890abcdef12345678",
      "value": "5000000",
      "validAfter": "0",
      "validBefore": "1743523500",
      "nonce": "0xcccc1234dddd5678eeee9012ffff3456aaaa7890bbbb1234cccc5678dddd9012"
    },
    "signature": "0xefgh....",
    "additionalDeposit": "5000000",
    "topUpSalt": "0xdddd1234eeee5678ffff9012aaaa3456bbbb7890cccc1234dddd5678eeee9012"
  }
}'

请求示例 — hash 模式(客户端自行充值)#

bash
curl --location --request POST 'https://web3.okx.com/api/v6/pay/mpp/session/topUp' \
--header 'Content-Type: application/json' \
--header 'OK-ACCESS-KEY: 37c541a1-****-****-****-10fe7a038418' \
--header 'OK-ACCESS-SIGN: leaV********3uw=' \
--header 'OK-ACCESS-PASSPHRASE: 1****6' \
--header 'OK-ACCESS-TIMESTAMP: 2023-10-18T12:21:41.274Z' \
--data '{
  "challenge": {
    "id": "qB3wErTyU7iOpAsD9fGhJk",
    "realm": "api.llm-service.com",
    "method": "evm",
    "intent": "session",
    "request": "eyJhbW91bnQiOiIxMDAi...",
    "expires": "2026-04-01T12:05:00Z"
  },
  "source": "did:pkh:eip155:196:0xaabbccddee11223344556677889900aabbccddee",
  "payload": {
    "action": "topUp",
    "type": "hash",
    "channelId": "0x6d0f4fdf1f2f6a1f6c1b0fbd6a7d5c2c0a8d3d7b1f6a9c1b3e2d4a5b6c7d8e9f",
    "hash": "0x9f8e7d6c5b4a3928170fabcdef1234567890abcdef1234567890abcdef123456",
    "additionalDeposit": "5000000",
    "topUpSalt": "0xdddd1234eeee5678ffff9012aaaa3456bbbb7890cccc1234dddd5678eeee9012"
  }
}'

响应示例#

json
{
  "code": "0",
  "msg": "",
  "data": {
    "method": "evm",
    "intent": "session",
    "status": "success",
    "timestamp": "2026-04-01T12:04:30Z",
    "channelId": "0x6d0f4fdf1f2f6a1f6c1b0fbd6a7d5c2c0a8d3d7b1f6a9c1b3e2d4a5b6c7d8e9f",
    "chainId": 196,
    "reference": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",
    "deposit": "15000000"
  }
}

3. /api/v6/pay/mpp/session/settle#

POST
/api/v6/pay/mpp/session/settle

中间结算 — 服务端代商户提交 Voucher 上链。商户(payee)使用自己的密钥签署 EIP-712 SettleAuthorization,Voucher 签名(由 payer 或 authorizedSigner 签署)随请求一起上送。合约端调用 settleWithAuthorization

请求参数#

参数类型必传描述
payloadObjectsettle 载荷
payload.actionString"settle"
payload.channelIdString通道 ID(bytes32 hex,0x 前缀)
payload.cumulativeAmountString本次要结算的累计金额(token 基本单位,uint128 十进制字符串)。若 <= settledOnChain 则服务端短路不上链
payload.voucherSignatureStringEIP-712 Voucher 签名(65 字节 r‖s‖v hex,0x 前缀)。签名者为 channel.authorizedSigner,未设置时为 channel.payer
payload.payeeSignatureStringEIP-712 SettleAuthorization 签名(65 字节)。签名者为 channel.payee
payload.nonceStringuint256 十进制字符串,商户自行随机生成。(payee, channelId, nonce) 三元组在链上唯一,重复使用会被链上以 NonceAlreadyUsed 拒绝
payload.deadlineString签名过期 Unix 秒。服务端当前时间 > deadline 时拒绝

响应参数#

参数类型描述
methodString固定值 "evm"
intentString固定值 "session"
statusString固定值 "success"
timestampStringRFC 3339 响应时间
channelIdString通道 ID(bytes32)
chainIdIntegerEVM chain ID,如 196
referenceString链上交易哈希
depositString当前已知用户在链上的存款金额(base units)

请求示例#

bash
curl --location --request POST 'https://web3.okx.com/api/v6/pay/mpp/session/settle' \
--header 'Content-Type: application/json' \
--header 'OK-ACCESS-KEY: 37c541a1-****-****-****-10fe7a038418' \
--header 'OK-ACCESS-SIGN: leaV********3uw=' \
--header 'OK-ACCESS-PASSPHRASE: 1****6' \
--header 'OK-ACCESS-TIMESTAMP: 2023-10-18T12:21:41.274Z' \
--data '{
  "payload": {
    "action": "settle",
    "channelId": "0x6d0f4fdf1f2f6a1f6c1b0fbd6a7d5c2c0a8d3d7b1f6a9c1b3e2d4a5b6c7d8e9f",
    "cumulativeAmount": "250000",
    "voucherSignature": "0x4a5b6c7d8e9fa0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b501",
    "payeeSignature": "0x11223344556677889900aabbccddeeff00112233445566778899aabbccddeeff1b",
    "nonce": "17890324512398000000000000000000000000000000000000000000000000000001",
    "deadline": "1745500000"
  }
}'

响应示例#

json
{
  "code": "0",
  "msg": "",
  "data": {
    "method": "evm",
    "intent": "session",
    "status": "success",
    "timestamp": "2026-04-01T12:04:30Z",
    "channelId": "0x6d0f4fdf1f2f6a1f6c1b0fbd6a7d5c2c0a8d3d7b1f6a9c1b3e2d4a5b6c7d8e9f",
    "chainId": 196,
    "reference": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",
    "deposit": "10000000"
  }
}

4. /api/v6/pay/mpp/session/close#

POST
/api/v6/pay/mpp/session/close

关闭通道并最终结算。使用 max(客户端金额, 服务端持有最高 Voucher) 保护商户收入。结算完成后,剩余存款由 Escrow 合约退还给付款方。

cumulativeAmount <= settledOnChain 时走 waiver 分支(无需新的 Voucher 签名)。

请求参数#

参数类型必传描述
payloadObjectclose 载荷
payload.actionString"close"
payload.channelIdString通道 ID(bytes32 hex,0x 前缀)
payload.cumulativeAmountString最终累计金额(token 基本单位,uint128 十进制字符串)。<= settledOnChain 时走 waiver 分支
payload.voucherSignatureString条件必填EIP-712 Voucher 签名(65 字节 r‖s‖v hex)。普通分支必填;waiver 分支可传空串 ""
payload.payeeSignatureStringEIP-712 CloseAuthorization 签名(65 字节)。签名者为 channel.payee
payload.nonceStringuint256 十进制字符串,商户自行随机生成。与 SettleAuthorization 共享同一 (payee, channelId, nonce) 已用集合,不可跨类型复用
payload.deadlineString签名过期 Unix 秒。服务端当前时间 > deadline 时拒绝

响应参数#

参数类型描述
methodString固定值 "evm"
intentString固定值 "session"
statusString固定值 "success"
timestampStringRFC 3339 响应时间
channelIdString通道 ID(bytes32)
chainIdIntegerEVM chain ID,如 196
referenceString链上交易哈希
depositString当前已知用户在链上的存款金额(base units)

请求示例#

bash
curl --location --request POST 'https://web3.okx.com/api/v6/pay/mpp/session/close' \
--header 'Content-Type: application/json' \
--header 'OK-ACCESS-KEY: 37c541a1-****-****-****-10fe7a038418' \
--header 'OK-ACCESS-SIGN: leaV********3uw=' \
--header 'OK-ACCESS-PASSPHRASE: 1****6' \
--header 'OK-ACCESS-TIMESTAMP: 2023-10-18T12:21:41.274Z' \
--data '{
  "payload": {
    "action": "close",
    "channelId": "0x6d0f4fdf1f2f6a1f6c1b0fbd6a7d5c2c0a8d3d7b1f6a9c1b3e2d4a5b6c7d8e9f",
    "cumulativeAmount": "500000",
    "voucherSignature": "0x4a5b6c7d8e9fa0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b501",
    "payeeSignature": "0x22334455667788990011aabbccddeeff00112233445566778899aabbccddeeff1c",
    "nonce": "17890324512398000000000000000000000000000000000000000000000000000002",
    "deadline": "1745500600"
  }
}'

响应示例#

json
{
  "code": "0",
  "msg": "",
  "data": {
    "method": "evm",
    "intent": "session",
    "status": "success",
    "timestamp": "2026-04-01T12:04:30Z",
    "channelId": "0x6d0f4fdf1f2f6a1f6c1b0fbd6a7d5c2c0a8d3d7b1f6a9c1b3e2d4a5b6c7d8e9f",
    "chainId": 196,
    "reference": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",
    "deposit": "10000000"
  }
}

5. /api/v6/pay/mpp/session/status#

GET
/api/v6/pay/mpp/session/status

查询支付通道的当前状态(只读)。

请求参数#

参数位置类型必传描述
channelIdqueryString通道 ID(bytes32 hex)

响应参数#

参数类型描述
channelIdString通道 ID(bytes32)
payerString付款方地址
payeeString收款方地址
tokenStringERC-20 代币合约地址
depositString总存款金额(base units)
settledOnChainString已链上结算的金额(仅调用 settle 后更新)
sessionStatusString通道状态:OPEN / CLOSING / CLOSED
remainingBalanceString剩余余额(deposit - cumulativeAmount)

请求示例#

bash
curl --location --request GET 'https://web3.okx.com/api/v6/pay/mpp/session/status?channelId=0x6d0f4fdf1f2f6a1f6c1b0fbd6a7d5c2c0a8d3d7b1f6a9c1b3e2d4a5b6c7d8e9f' \
--header 'OK-ACCESS-KEY: 37c541a1-****-****-****-10fe7a038418' \
--header 'OK-ACCESS-SIGN: leaV********3uw=' \
--header 'OK-ACCESS-PASSPHRASE: 1****6' \
--header 'OK-ACCESS-TIMESTAMP: 2023-10-18T12:21:41.274Z'

响应示例#

json
{
  "code": "0",
  "msg": "",
  "data": {
    "channelId": "0x6d0f4fdf1f2f6a1f6c1b0fbd6a7d5c2c0a8d3d7b1f6a9c1b3e2d4a5b6c7d8e9f",
    "payer": "0xaabbccddee11223344556677889900aabbccddee",
    "payee": "0x742d35Cc6634c0532925a3b844bC9e7595F8fE00",
    "token": "0xA8CE8aee21bC2A48a5EF670afCc9274C7bbbC035",
    "deposit": "10000000",
    "settledOnChain": "100000",
    "sessionStatus": "OPEN",
    "remainingBalance": "9750000"
  }
}

公共数据结构#

Challenge#

由服务端签发的 Challenge 对象,客户端原样回传。

参数类型必传描述
idStringChallenge ID
realmString保护空间标识
methodString固定 "evm"
intentString支付意图:"charge" / "session"
requestStringbase64url 编码的请求参数
expiresString过期时间(ISO 8601)

支持的网络和币种#

网络Chain Index状态
X Layer196已支持

X Layer 支持的稳定币:

币种合约地址
USDG0x4ae46a509f6b1d9056937ba4500cb143933d2dc8
USD₮00x779ded0c9e1022225f8e0630b35a9b54be713736

错误码#

错误响应统一使用包络 {"code": "<code>", "msg": "<message>", "data": null}

1. 认证错误(HTTP 401)#

错误码描述
50103请求头 OK-ACCESS-KEY 不能为空
50104请求头 OK-ACCESS-PASSPHRASE 不能为空
50105请求头 OK-ACCESS-PASSPHRASE 错误
50106请求头 OK-ACCESS-SIGN 不能为空
50107请求头 OK-ACCESS-TIMESTAMP 不能为空
50111无效的 OK-ACCESS-KEY
50112无效的 OK-ACCESS-TIMESTAMP
50113无效的签名

2. 请求错误#

错误码HTTP 状态描述
50011429用户请求频率过快,超过该接口允许的限额
50014400必填参数 {param} 不能为空

3. 业务错误#

错误码错误名称描述
8000SERVICE_ERRORAPI 服务内部错误
70000invalid_params缺少必填字段或格式错误
70001unsupported_chain链不在支持列表
70002payer_blocked付款方在黑名单
70003invalid_credentialsource 缺失、或 txHash 已被使用
70004invalid_signature签名验证失败
70005split_sum_exceeds_total分账总额 >= 总金额
70006split_count_exceeded分账数量 > 10
70007tx_not_confirmed交易未在链上确认
70008channel_close链上合约 channel 状态已关闭
70009challenge_invalidChallenge 不存在或已过期
70010channel_not_foundchannelId 不存在
70011grace_period_too_shortEscrow 合约 grace period < 10 分钟,拒绝开通 channel
70012amount_exceeds_depositcumulativeAmount 超过 channel 存款余额
70013voucher_delta_too_smallVoucher 递增量低于 minVoucherDelta
70014channel_closingchannel 处于 CLOSING 状态,不接受新 Voucher