HTTP 端 API - 单次支付#
本文档是单次支付的 API 参考,涵盖 exact、upto、charge 三种 scheme 的完整接口定义。使用指南与 SDK 接入示例请参阅 单次支付 · 接入文档。
选 scheme#
exact 单收款方,同步 / 异步结算都支持,资产转移方式可选 EIP-3009(仅支持原生实现该接口的代币,如 USDC)或 Permit2(兼容所有 ERC-20)。
upto 按上限授权 + 按实际用量结算,适用于 AI Agent 按次计费 / 流式服务计量 / 试用转付费等场景。底层强制走 Permit2,并同时接受外部 EOA 钱包(secp256k1)与 OKX agentic wallet(Ed25519 session key)两类签名。
charge 除了单收款方,还支持分账(Split),即单次支付多地址收款(≤10),默认且只支持同步结算。
| 维度 | exact (EIP-3009) | exact (Permit2) | upto | charge |
|---|---|---|---|---|
| 收款方 | 单收款方 | 单收款方 | 单收款方 | 单 / 分账 ≤10 |
| 结算时序 | 同步 / 异步均可 | 同步 / 异步均可 | 异步(默认 pending) | 同步 |
| 资产转移 | EIP-3009 transferWithAuthorization | Permit2 canonical → x402ExactPermit2Proxy | Permit2 canonical → x402UptoPermit2Proxy | EIP-3009 |
| 代币兼容性 | 仅 EIP-3009 token | 所有 ERC-20 | 所有 ERC-20 | 仅 EIP-3009 token |
| 金额语义 | 签名 = 实付 | 签名 = 实付 | 签名 = 上限,实付 ≤ 上限 | 签名 = 实付 |
| 接入指南 | exact 路径 | exact 路径 | upto 路径 | charge 路径 |
- Base URL:
https://web3.okx.com exact/upto路径前缀:/api/v6/pay/x402(共用 verify / settle / supported / settle/status 四个 endpoint,由 payload 内容自动路由)charge路径前缀:/api/v6/pay/mpp/charge- Network:X Layer(chainId
196,CAIP-2 标识eip155:196)
认证#
所有接口均需通过 API Key 认证,请求头中携带以下字段:
| Header | 必传 | 描述 |
|---|---|---|
OK-ACCESS-KEY | 是 | API Key |
OK-ACCESS-SIGN | 是 | 请求签名 |
OK-ACCESS-PASSPHRASE | 是 | API 密码短语 |
OK-ACCESS-TIMESTAMP | 是 | ISO 8601 时间戳 |
Content-Type | 是 | POST 请求需设为 application/json |
所有响应统一使用业务包络:
{
"code": "0",
"msg": "success",
"data": { /* 业务字段 */ }
}
业务错误时 code 为非 "0",data 为 null,错误码集中见文末 错误码 章节。
exact Scheme#
exact 同时支持两种资产转移方式,由 accepted.extra.assetTransferMethod 和 payload 字段决定:
- EIP-3009 路径:填
payload.authorization,accepted.extra不带或带assetTransferMethod=eip3009 - Permit2 路径:填
payload.permit2Authorization,accepted.extra.assetTransferMethod="permit2",paymentRequirements.extra同步
两路径互斥,payload.authorization 与 payload.permit2Authorization 必须严格二选一。
1. /api/v6/pay/x402/supported#
/api/v6/pay/x402/supported
查询 Broker 支持的 scheme、network 及签名者列表。Seller SDK 调用此接口构建 402 响应的 accepts 数组。kinds 数组按 Apollo 灰度开关动态输出。
请求参数#
无。
响应参数#
| 参数 | 类型 | 描述 |
|---|---|---|
kinds | Array<SupportedKind> | 支持的支付类型列表 |
kinds[].x402Version | Integer | 协议版本,如 2 |
kinds[].scheme | String | 结算方案:exact / aggr_deferred / upto |
kinds[].network | String | CAIP-2 链标识,如 eip155:196 |
kinds[].extra | Object | scheme 特有扩展配置,见下表 |
extensions | Array<String> | 支持的扩展标识列表 |
signers | Object | CAIP-2 通配符 → 签名者地址数组映射 |
kinds[].extra 子字段:
| 子字段 | 适用 scheme | 描述 |
|---|---|---|
assetTransferMethod | exact / upto | "permit2" 表示走 Permit2 canonical + Proxy 合约结算;exact 在缺省时即原生 EIP-3009 |
facilitatorAddress | upto | facilitator EOA 地址,buyer 必须在 witness.facilitator 填同一地址 |
signatureSchemes | upto | 当前 facilitator 支持的签名算法列表,开关关闭时仅 ["ed25519"],EOA 灰度开启后追加 "secp256k1" |
请求示例#
curl --location --request GET 'https://web3.okx.com/api/v6/pay/x402/supported' \
--header 'OK-ACCESS-KEY: 37c541a1-****-****-****-10fe7a038418' \
--header 'OK-ACCESS-SIGN: leaV********3uw=' \
--header 'OK-ACCESS-PASSPHRASE: 1****6' \
--header 'OK-ACCESS-TIMESTAMP: 2026-04-01T12:21:41.274Z'
响应示例#
{
"code": "0",
"msg": "",
"data": {
"kinds": [
{ "x402Version": 2, "scheme": "exact", "network": "eip155:196" },
{ "x402Version": 2, "scheme": "exact", "network": "eip155:196",
"extra": { "assetTransferMethod": "permit2" } },
{ "x402Version": 2, "scheme": "aggr_deferred", "network": "eip155:196" },
{ "x402Version": 2, "scheme": "upto", "network": "eip155:196",
"extra": {
"assetTransferMethod": "permit2",
"facilitatorAddress": "0xFacilitatorEOA...",
"signatureSchemes": ["ed25519", "secp256k1"]
} }
],
"extensions": [],
"signers": {}
}
}
2. /api/v6/pay/x402/verify#
/api/v6/pay/x402/verify
校验 Buyer 签名的支付授权有效性,不执行链上交易。
请求参数#
| 参数 | 类型 | 必传 | 描述 |
|---|---|---|---|
x402Version | Integer | 是 | 协议版本,如 2 |
paymentPayload | Object | 是 | 客户端随受保护请求携带的支付载荷,详见 PaymentPayload |
paymentRequirements | Object | 是 | Seller 定义的支付要求,详见 PaymentRequirements |
约束:
paymentPayload.accepted.scheme必须与paymentRequirements.scheme一致,取值"exact"或"upto"paymentPayload.payload.authorization与paymentPayload.payload.permit2Authorization必须严格二选一:exact + EIP-3009:填authorizationexact + Permit2:填permit2Authorization,且accepted.scheme="exact"upto:填permit2Authorization,且accepted.scheme="upto",witness.facilitator必填
响应参数#
| 参数 | 类型 | 描述 |
|---|---|---|
isValid | Boolean | true 验证通过,false 验证失败 |
invalidReason | String | 机器可读的无效原因(验证失败时返回) |
invalidMessage | String | 人类可读的无效说明(验证失败时返回) |
payer | String | 付款方钱包地址 |
请求示例 — exact + EIP-3009#
curl --location --request POST 'https://web3.okx.com/api/v6/pay/x402/verify' \
--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: 2026-04-01T12:21:41.274Z' \
--data '{
"x402Version": 2,
"paymentPayload": {
"x402Version": 2,
"resource": {
"url": "https://api.example.com/premium-data",
"description": "Access to premium data",
"mimeType": "application/json"
},
"accepted": {
"scheme": "exact",
"network": "eip155:196",
"amount": "10000",
"asset": "0x4ae46a509f6b1d9056937ba4500cb143933d2dc8",
"payTo": "0xRecipientAddress",
"maxTimeoutSeconds": 60,
"extra": { "name": "USDG", "version": "2" }
},
"payload": {
"signature": "0xf3746613c2d920b5fdabc0856f2aeb2d4f88ee6037b8cc5d04a71a4462f13480...",
"authorization": {
"from": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
"to": "0xRecipientAddress",
"value": "10000",
"validAfter": "0",
"validBefore": "1740672154",
"nonce": "0xf374661..."
}
}
},
"paymentRequirements": {
"scheme": "exact",
"network": "eip155:196",
"amount": "10000",
"asset": "0x4ae46a509f6b1d9056937ba4500cb143933d2dc8",
"payTo": "0xRecipientAddress",
"maxTimeoutSeconds": 60,
"extra": { "name": "USDG", "version": "2" }
}
}'
请求示例 — exact + Permit2#
curl --location --request POST 'https://web3.okx.com/api/v6/pay/x402/verify' \
--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: 2026-04-01T12:21:41.274Z' \
--data '{
"x402Version": 2,
"paymentPayload": {
"x402Version": 2,
"resource": { "url": "https://api.example.com/premium-data" },
"accepted": {
"scheme": "exact",
"network": "eip155:196",
"amount": "10000",
"asset": "0x4ae46a509f6b1d9056937ba4500cb143933d2dc8",
"payTo": "0xMerchantAddr...",
"maxTimeoutSeconds": 60,
"extra": { "assetTransferMethod": "permit2" }
},
"payload": {
"signature": "0xf374...1c",
"permit2Authorization": {
"from": "0xBuyerEOA...",
"permitted": {
"token": "0x4ae46a509f6b1d9056937ba4500cb143933d2dc8",
"amount": "10000"
},
"spender": "0x402085c248EeA27D92E8b30b2C58ed07f9E20001",
"nonce": "1027389471020934876123987612938712398761239",
"deadline": "1714813500",
"witness": {
"to": "0xMerchantAddr...",
"validAfter": "1714812840"
}
}
}
},
"paymentRequirements": {
"scheme": "exact",
"network": "eip155:196",
"amount": "10000",
"asset": "0x4ae46a509f6b1d9056937ba4500cb143933d2dc8",
"payTo": "0xMerchantAddr...",
"extra": { "assetTransferMethod": "permit2" }
}
}'
注意:
permit2Authorization.witness仅含to/validAfter两个字段,不需要facilitator(DTO 上存在但 exact 路径不读不校验)。spender必须等于 Apollox402.exact.permit2.proxy.address,否则返回invalid_permit2_spender。permit2Authorization.permitted.amount必须等于paymentRequirements.amount(signed = paid)。
响应示例 — 验证通过#
{
"code": "0",
"msg": "success",
"data": {
"isValid": true,
"invalidReason": null,
"invalidMessage": null,
"payer": "0xcb30ed083ad246b126a3aa1f414b44346e83e67d"
}
}
响应示例 — 验证失败#
{
"code": "0",
"msg": "success",
"data": {
"isValid": false,
"invalidReason": "insufficient_allowance",
"invalidMessage": "Insufficient allowance to Permit2: allowance=0, required=10000",
"payer": "0xcb30ed083ad246b126a3aa1f414b44346e83e67d"
}
}
3. /api/v6/pay/x402/settle#
/api/v6/pay/x402/settle
验证通过后,提交链上结算。每次调用都会发起一笔独立的链上交易:
exact + EIP-3009:直接调用 token 合约的transferWithAuthorizationexact + Permit2:调用x402ExactPermit2Proxy.settle,Buyer 对 Permit2 canonical 合约的 ERC-20 必须已approve(MAX_UINT256)upto:调用x402UptoPermit2Proxy.settle,由 Facilitator EOA 二次签名(HSM)后上链
请求参数#
| 参数 | 类型 | 必传 | 描述 |
|---|---|---|---|
x402Version | Integer | 是 | 协议版本,如 2 |
paymentPayload | Object | 是 | 同 verify |
paymentRequirements | Object | 是 | 同 verify。upto 路径下 amount 表示实付金额,必须 ≤ permit2Authorization.permitted.amount(上限) |
syncSettle | Boolean | 否 | OKX 扩展。true=同步等待链上确认(轮询至超时);false(默认)=异步广播。upto 路径忽略此字段,永远异步 |
响应参数#
| 参数 | 类型 | 描述 |
|---|---|---|
success | Boolean | 结算是否成功 |
errorReason | String | 机器可读的失败原因(失败时返回) |
errorMessage | String | 人类可读的失败说明(失败时返回) |
payer | String | 付款方钱包地址 |
transaction | String | 链上交易哈希 |
network | String | CAIP-2 链标识 |
status | String | OKX 扩展。结算状态,见下表 |
amount | String | OKX 扩展。upto scheme 返回实际结算金额(原子单位);零结算时为 "0";exact / exact + permit2 不返回此字段 |
status 取值矩阵:
| 路径 | syncSettle | 结果 | status | transaction | amount |
|---|---|---|---|---|---|
exact (EIP-3009 / Permit2) | false(默认) | 已广播 | pending | txHash | — |
exact (EIP-3009 / Permit2) | true | 链上确认成功 | success | txHash | — |
exact (EIP-3009 / Permit2) | true | 等待超时 | timeout | txHash | — |
exact (EIP-3009 / Permit2) | — | 验签 / 模拟 / 链上失败 | failed | "" | — |
upto | —(忽略) | 零结算 | success | null | "0" |
upto | —(忽略) | 已广播 | pending | txHash | 实付金额 |
upto | —(忽略) | 验签 / 模拟 / 链上失败 | failed | "" | — |
请求示例 — exact + EIP-3009 同步结算#
curl --location --request POST 'https://web3.okx.com/api/v6/pay/x402/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: 2026-04-01T12:21:41.274Z' \
--data '{
"x402Version": 2,
"paymentPayload": { "...同 verify..." },
"paymentRequirements": { "...同 verify..." },
"syncSettle": true
}'
请求示例 — exact + Permit2 异步结算#
请求体与 verify 完全一致,paymentPayload.payload 填 permit2Authorization,syncSettle 缺省。
响应示例 — exact 同步结算成功(syncSettle=true)#
{
"code": "0",
"msg": "success",
"data": {
"success": true,
"errorReason": null,
"errorMessage": null,
"payer": "0xcb30ed083ad246b126a3aa1f414b44346e83e67d",
"transaction": "0x4f46ed8eac92ddbccfb56a88ff827db3616c7beb191adabbeeded901340bd7d5",
"network": "eip155:196",
"status": "success"
}
}
响应示例 — exact 异步结算(syncSettle=false)#
{
"code": "0",
"msg": "success",
"data": {
"success": true,
"errorReason": null,
"errorMessage": null,
"payer": "0xcb30ed083ad246b126a3aa1f414b44346e83e67d",
"transaction": "0x4f46ed8eac92ddbccfb56a88ff827db3616c7beb191adabbeeded901340bd7d5",
"network": "eip155:196",
"status": "pending"
}
}
响应示例 — exact 等待超时(syncSettle=true)#
{
"code": "0",
"msg": "success",
"data": {
"success": true,
"payer": "0xcb30ed083ad246b126a3aa1f414b44346e83e67d",
"transaction": "0x4f46ed8eac92ddbccfb56a88ff827db3616c7beb191adabbeeded901340bd7d5",
"network": "eip155:196",
"status": "timeout"
}
}
客户端拿到
timeout时应继续走/settle/status轮询。
响应示例 — 结算失败#
{
"code": "0",
"msg": "success",
"data": {
"success": false,
"errorReason": "insufficient_funds",
"errorMessage": "Transaction reverted",
"payer": "0xcb30ed083ad246b126a3aa1f414b44346e83e67d",
"transaction": "",
"network": "eip155:196",
"status": "failed"
}
}
4. /api/v6/pay/x402/settle/status#
/api/v6/pay/x402/settle/status
根据链上交易哈希查询结算状态,适用于异步结算(syncSettle=false、upto、或 syncSettle=true 超时)的轮询场景。
请求参数#
| 参数 | 位置 | 类型 | 必传 | 描述 |
|---|---|---|---|---|
txHash | query | String | 是 | 链上交易哈希 |
响应参数#
| 参数 | 类型 | 描述 |
|---|---|---|
success | Boolean | 查询是否成功(txHash 不存在时为 false,settleStatus=FAILED 时也为 false) |
errorReason | String | 机器可读的失败原因(DB error_reason 字段) |
errorMessage | String | 人类可读的失败说明 |
payer | String | 付款方钱包地址 |
transaction | String | 链上交易哈希 |
network | String | CAIP-2 链标识 |
status | String | 当前结算状态:pending / success / failed |
amount | String | OKX 扩展。upto scheme 的实际结算金额(原子单位);exact / exact + permit2 为 null |
请求示例#
curl --location --request GET 'https://web3.okx.com/api/v6/pay/x402/settle/status?txHash=0x4f46ed8eac92ddbccfb56a88ff827db3616c7beb191adabbeeded901340bd7d5' \
--header 'OK-ACCESS-KEY: 37c541a1-****-****-****-10fe7a038418' \
--header 'OK-ACCESS-SIGN: leaV********3uw=' \
--header 'OK-ACCESS-PASSPHRASE: 1****6' \
--header 'OK-ACCESS-TIMESTAMP: 2026-04-01T12:21:41.274Z'
响应示例 — 查询成功(exact)#
{
"code": "0",
"msg": "success",
"data": {
"success": true,
"payer": "0xcb30ed083ad246b126a3aa1f414b44346e83e67d",
"transaction": "0x4f46ed8eac92ddbccfb56a88ff827db3616c7beb191adabbeeded901340bd7d5",
"network": "eip155:196",
"status": "success",
"amount": null
}
}
响应示例 — 查询成功(upto)#
{
"code": "0",
"msg": "success",
"data": {
"success": true,
"payer": "0xcb30ed083ad246b126a3aa1f414b44346e83e67d",
"transaction": "0xabc...",
"network": "eip155:196",
"status": "success",
"amount": "1234000"
}
}
响应示例 — 交易未找到#
{
"code": "0",
"msg": "success",
"data": {
"success": false,
"errorReason": "not_found",
"errorMessage": "Transaction not found for txHash: 0xabc123...",
"payer": null,
"transaction": null,
"network": null,
"status": null
}
}
upto Scheme#
upto = "按上限授权 + 按实际用量结算"。底层走 Permit2 canonical → x402UptoPermit2Proxy,强制带 witness.facilitator,由 Facilitator 用注册的 EOA 对 (owner, token, permittedAmount, permitNonce, permitDeadline, witnessHash, userSignatureHash, amount, relayer, deadline) 二次签名(HSM)后上链。
复用 /api/v6/pay/x402/{verify,settle,supported,settle/status} 四个 endpoint,由 paymentPayload.accepted.scheme="upto" + payload.permit2Authorization != null 自动路由。
双签名路径#
upto 同时接受两类签名 buyer,由 accepted.extra.sessionCert + accepted.extra.signatureScheme 决定路由:
| 路径 | 签名钱包 | 签名算法 | sessionCert | signatureScheme |
|---|---|---|---|---|
| EOA | MetaMask / Rabby / Coinbase Wallet 等 | secp256k1 (EIP-712) | 不填 | 缺省 / "secp256k1" |
| SESSION | OKX agentic wallet | Ed25519 (session key) | 必填(base64 sessionCert) | 缺省 / "ed25519" |
互斥校验失败(sessionCert 存在 + signatureScheme="secp256k1",或缺 sessionCert + signatureScheme="ed25519")→ 返回 upto_signature_route_conflict。
EOA 路径受 Apollo x402.upto.eoa.signature.enabled 灰度控制,关闭时返回 unsupported_scheme。
5. /api/v6/pay/x402/verify — scheme=upto#
/api/v6/pay/x402/verify
请求体结构与 exact + Permit2 完全一致,差异点:
| 字段 | upto 要求 |
|---|---|
paymentPayload.accepted.scheme | 必须 "upto" |
paymentRequirements.scheme | 必须 "upto" |
paymentPayload.payload.permit2Authorization.witness.facilitator | 必填,且必须在 facilitator 白名单(Apollo x402.upto.facilitator.address) |
paymentPayload.accepted.extra.facilitatorAddress | 与 witness.facilitator 字符串相等(忽略大小写) |
paymentPayload.accepted.extra.sessionCert | SESSION 路径必填,EOA 路径不填 |
paymentPayload.accepted.extra.signatureScheme | 可选,"secp256k1" / "ed25519";缺省时按 sessionCert 自动判定 |
paymentPayload.payload.permit2Authorization.spender | 必须等于 Apollo x402.upto.permit2.proxy.address(与 exact + permit2 的 proxy 不同),否则 invalid_spender |
paymentPayload.payload.permit2Authorization.permitted.amount | 授权上限,必须 > 0。verify 阶段强制 permitted.amount == paymentRequirements.amount(buyer 把 ceiling 同时签进 requirements,settle 时 seller 才把 paymentRequirements.amount 改写为实付金额) |
请求示例 — upto + EOA#
curl --location --request POST 'https://web3.okx.com/api/v6/pay/x402/verify' \
--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: 2026-04-01T12:21:41.274Z' \
--data '{
"x402Version": 2,
"paymentPayload": {
"x402Version": 2,
"resource": { "url": "https://api.example.com/agent-call" },
"accepted": {
"scheme": "upto",
"network": "eip155:196",
"amount": "5000000",
"asset": "0x4ae46a509f6b1d9056937ba4500cb143933d2dc8",
"payTo": "0xMerchant...",
"maxTimeoutSeconds": 60,
"extra": {
"assetTransferMethod": "permit2",
"facilitatorAddress": "0xFacilitatorEOA..."
}
},
"payload": {
"signature": "0x...65byte_secp256k1_sig",
"permit2Authorization": {
"from": "0xBuyerEOA...",
"permitted": {
"token": "0x4ae46a509f6b1d9056937ba4500cb143933d2dc8",
"amount": "5000000"
},
"spender": "0x4020e7...0002",
"nonce": "1027389471020934876",
"deadline": "1714813500",
"witness": {
"to": "0xMerchant...",
"facilitator": "0xFacilitatorEOA...",
"validAfter": "1714812840"
}
}
}
},
"paymentRequirements": {
"scheme": "upto",
"network": "eip155:196",
"amount": "5000000",
"asset": "0x4ae46a509f6b1d9056937ba4500cb143933d2dc8",
"payTo": "0xMerchant...",
"extra": {
"assetTransferMethod": "permit2",
"facilitatorAddress": "0xFacilitatorEOA..."
}
}
}'
请求示例 — upto + SESSION(OKX agentic wallet)#
accepted.extra 多两个字段,payload.signature 为 base64 Ed25519:
{
"accepted": {
"scheme": "upto",
"network": "eip155:196",
"amount": "5000000",
"asset": "0x4ae46a509f6b1d9056937ba4500cb143933d2dc8",
"payTo": "0xMerchant...",
"extra": {
"assetTransferMethod": "permit2",
"facilitatorAddress": "0xFacilitatorEOA...",
"sessionCert": "eyJhbGciOi...base64",
"signatureScheme": "ed25519"
}
},
"payload": {
"signature": "MEUCIQ...base64_ed25519_sig",
"permit2Authorization": {
"from": "0xAaAddress...",
"permitted": { "token": "0x4ae46a...", "amount": "5000000" },
"spender": "0x4020e7...0002",
"nonce": "1027389471020934876",
"deadline": "1714813500",
"witness": {
"to": "0xMerchant...",
"facilitator": "0xFacilitatorEOA...",
"validAfter": "1714812840"
}
}
}
}
响应#
结构与 exact verify 一致:{isValid, invalidReason, invalidMessage, payer}。
6. /api/v6/pay/x402/settle — scheme=upto#
/api/v6/pay/x402/settle
请求体结构同 verify,关键差异:
paymentRequirements.amount是实付金额,必须满足0 ≤ amount ≤ permit2Authorization.permitted.amountpaymentRequirements.amount = "0"进入零结算快速路径:不调 TEE、不上链、DB 写 SUCCESS、响应transaction=null/status=success/amount="0"syncSettle字段被忽略,upto 永远异步返回pending
settle 响应矩阵#
| 场景 | success | status | transaction | amount | errorReason |
|---|---|---|---|---|---|
| 零结算 | true | success | null | "0" | — |
| 正常广播(异步) | true | pending | txHash | 实付金额 | — |
| settle 实付 > 上限 | false | failed | "" | — | upto_settlement_exceeds_amount |
| facilitator 字段错 | false | failed | "" | — | upto_facilitator_mismatch |
| EOA 签名格式错 | false | failed | "" | — | invalid_eoa_signature |
| TEE 转签失败(SESSION) | false | failed | "" | — | tee_sign_failed |
| Intent 提交失败 | false | failed | "" | — | intent_submit_failed |
| 同 (payer, nonce) 重复 settle | true | 上次状态 | 上次 txHash 或 "" | DB settle_amount 或 "0" | — |
请求示例#
curl --location --request POST 'https://web3.okx.com/api/v6/pay/x402/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: 2026-04-01T12:21:41.274Z' \
--data '{
"x402Version": 2,
"paymentPayload": {
"x402Version": 2,
"accepted": {
"scheme": "upto",
"network": "eip155:196",
"amount": "5000000",
"asset": "0x4ae46a509f6b1d9056937ba4500cb143933d2dc8",
"payTo": "0xMerchant...",
"extra": {
"assetTransferMethod": "permit2",
"facilitatorAddress": "0xFacilitatorEOA..."
}
},
"payload": {
"signature": "0x...secp256k1_sig",
"permit2Authorization": { "...同 verify..." }
}
},
"paymentRequirements": {
"scheme": "upto",
"network": "eip155:196",
"amount": "1234000",
"asset": "0x4ae46a509f6b1d9056937ba4500cb143933d2dc8",
"payTo": "0xMerchant...",
"extra": {
"assetTransferMethod": "permit2",
"facilitatorAddress": "0xFacilitatorEOA..."
}
}
}'
响应示例 — 正常广播#
{
"code": "0",
"msg": "success",
"data": {
"success": true,
"payer": "0xbuyer...",
"transaction": "0xabc...",
"network": "eip155:196",
"status": "pending",
"amount": "1234000"
}
}
响应示例 — 零结算#
{
"code": "0",
"msg": "success",
"data": {
"success": true,
"payer": "0xbuyer...",
"transaction": null,
"network": "eip155:196",
"status": "success",
"amount": "0"
}
}
响应示例 — 失败#
{
"code": "0",
"msg": "success",
"data": {
"success": false,
"errorReason": "upto_settlement_exceeds_amount",
"errorMessage": "Settlement amount exceeds authorized ceiling",
"payer": "0xbuyer...",
"transaction": "",
"network": "eip155:196",
"status": "failed"
}
}
charge Scheme#
charge 基于 HTTP 402 Challenge-Credential 流程提供一次性代币转账能力。
- 服务端代付(transaction 模式):Buyer 签署 EIP-3009 授权,Broker 代为提交链上交易
- 客户端自付(hash 模式):Buyer 自行广播链上交易,Broker 验证交易有效性
7. /api/v6/pay/mpp/charge/settle#
/api/v6/pay/mpp/charge/settle
服务端代付 — 代替用户提交链上 ERC-20 转账。支持 EIP-3009 授权方式,支持分账(最多 10 笔)。
请求参数#
| 参数 | 类型 | 必传 | 描述 |
|---|---|---|---|
challenge | Object | 是 | 服务端签发的 Challenge 对象(原样回传),详见 Challenge |
payload | Object | 是 | EVM 支付凭证 |
payload.type | String | 是 | 固定 "transaction" |
payload.authorization | Object | 是 | EIP-3009 授权对象 |
payload.authorization.type | String | 是 | 固定 "eip-3009" |
payload.authorization.from | String | 是 | 付款方钱包地址 |
payload.authorization.to | String | 是 | 收款方钱包地址 |
payload.authorization.value | String | 是 | 支付金额(base units) |
payload.authorization.validAfter | String | 是 | 授权生效 Unix 时间戳 |
payload.authorization.validBefore | String | 是 | 授权过期 Unix 时间戳 |
payload.authorization.nonce | String | 是 | 随机 bytes32,每笔授权唯一 |
payload.authorization.signature | String | 是 | 65 字节 EIP-712 签名(r‖s‖v) |
payload.authorization.splits | Array | 否 | 分账列表,最多 10 条,详见 Split |
source | String | 否 | 付款方 DID(did:pkh:eip155:196:0x...) |
响应参数#
| 参数 | 类型 | 描述 |
|---|---|---|
method | String | 固定值 "evm" |
reference | String | 链上交易哈希(0x 前缀) |
status | String | 固定值 "success" |
timestamp | String | RFC 3339 结算时间 |
chainId | Integer | 结算所在链 ID,如 196 |
challengeId | String | Challenge ID,用于客户端关联 |
externalId | String | 原样回传自 Challenge request 的商户订单号 |
请求示例#
curl --location --request POST 'https://web3.okx.com/api/v6/pay/mpp/charge/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: 2026-04-01T12:21:41.274Z' \
--data '{
"challenge": {
"id": "qB3wErTyU7iOpAsD9fGhJk",
"realm": "api.example.com",
"method": "evm",
"intent": "charge",
"request": "eyJhbW91bnQiOiIxMDAwMCIsImN1cnJlbmN5Ijoi...",
"expires": "2026-04-01T12:05:00Z"
},
"payload": {
"type": "transaction",
"authorization": {
"type": "eip-3009",
"from": "0x1234567890abcdef1234567890abcdef12345678",
"to": "0x742d35Cc6634c0532925a3b844bC9e7595F8fE00",
"value": "10000",
"validAfter": "0",
"validBefore": "9999999999",
"nonce": "0x9337d07c707c703b86f05e66b9097e38e7587e7ecfe740551ac608693864abdd",
"signature": "0x5a9827232b5c640d7239462dbb3f0eede1aa2522eb53e552369db8db66720293..."
}
}
}'
响应示例#
{
"code": "0",
"msg": "",
"data": {
"method": "evm",
"reference": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",
"status": "success",
"timestamp": "2026-04-01T12:04:30Z",
"chainId": 196,
"challengeId": "qB3wErTyU7iOpAsD9fGhJk",
"externalId": "order-12345"
}
}
请求示例 — 含分账#
curl --location --request POST 'https://web3.okx.com/api/v6/pay/mpp/charge/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: 2026-04-01T12:21:41.274Z' \
--data '{
"challenge": {
"id": "sP1itPaym3ntEx4mple",
"realm": "marketplace.example.com",
"method": "evm",
"intent": "charge",
"request": "eyJ...",
"expires": "2026-04-01T12:05:00Z"
},
"payload": {
"type": "transaction",
"authorization": {
"type": "eip-3009",
"from": "0x1234567890abcdef1234567890abcdef12345678",
"to": "0x742d35Cc6634c0532925a3b844bC9e7595F8fE00",
"value": "940000",
"validAfter": "0",
"validBefore": "1775059500",
"nonce": "0x1111111111111111111111111111111111111111111111111111111111111111",
"signature": "0xabc...primary",
"splits": [
{
"from": "0x1234567890abcdef1234567890abcdef12345678",
"to": "0xA1B2C3d4e5F6a1B2c3d4e5F6a1b2c3d4e5F6a1b2",
"value": "50000",
"validAfter": "0",
"validBefore": "1775059500",
"nonce": "0x2222222222222222222222222222222222222222222222222222222222222222",
"signature": "0xdef...split1"
},
{
"from": "0x1234567890abcdef1234567890abcdef12345678",
"to": "0xC4D5e6F7A8B9c4D5E6f7a8B9c4d5e6F7a8b9C4D5",
"value": "10000",
"validAfter": "0",
"validBefore": "1775059500",
"nonce": "0x3333333333333333333333333333333333333333333333333333333333333333",
"signature": "0xghi...split2"
}
]
}
},
"source": "did:pkh:eip155:196:0x1234567890abcdef1234567890abcdef12345678"
}'
8. /api/v6/pay/mpp/charge/verifyHash#
/api/v6/pay/mpp/charge/verifyHash
客户端自付 — 验证客户端已广播的链上交易,确认交易符合 Challenge 中的支付要求。
请求参数#
| 参数 | 类型 | 必传 | 描述 |
|---|---|---|---|
challenge | Object | 是 | 服务端签发的 Challenge 对象(原样回传),详见 Challenge |
payload | Object | 是 | 支付凭证 |
payload.type | String | 是 | 固定 "hash" |
payload.hash | String | 是 | 客户端已广播的链上交易哈希 |
source | String | 是 | 付款方 DID(did:pkh:eip155:196:0x...) |
响应参数#
| 参数 | 类型 | 描述 |
|---|---|---|
method | String | 固定值 "evm" |
reference | String | 链上交易哈希(0x 前缀) |
status | String | 固定值 "success" |
timestamp | String | RFC 3339 确认时间 |
chainId | Integer | 链 ID,如 196 |
challengeId | String | Challenge ID,用于客户端关联 |
externalId | String | 原样回传自 Challenge request 的商户订单号 |
请求示例#
curl --location --request POST 'https://web3.okx.com/api/v6/pay/mpp/charge/verifyHash' \
--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: 2026-04-01T12:21:41.274Z' \
--data '{
"challenge": {
"id": "qB3wErTyU7iOpAsD9fGhJk",
"realm": "api.example.com",
"method": "evm",
"intent": "charge",
"request": "eyJhbW91bnQiOiIxMDAwMCIsImN1cnJlbmN5Ijoi...",
"expires": "2026-04-01T12:05:00Z"
},
"payload": {
"type": "hash",
"hash": "0xd9a703784f0cb489ea90c52f5626a22516f39c5063558733bb742972fdf6f722"
},
"source": "did:pkh:eip155:196:0x1234567890abcdef1234567890abcdef12345678"
}'
响应示例#
{
"code": "0",
"msg": "",
"data": {
"method": "evm",
"reference": "0x9f8e7d6c5b4a3928170fabcdef1234567890abcdef1234567890abcdef123456",
"status": "success",
"timestamp": "2026-04-01T12:04:30Z",
"chainId": 196,
"challengeId": "qB3wErTyU7iOpAsD9fGhJk",
"externalId": "order-12345"
}
}
公共数据结构#
PaymentPayload#
Buyer 签名后通过 X-PAYMENT Header(base64 编码)传递给 Seller,Seller 原样透传给 Broker。
| 参数 | 类型 | 必传 | 描述 |
|---|---|---|---|
x402Version | Integer | 是 | 协议版本,如 2 |
resource | Object | 否 | 受保护资源描述 |
resource.url | String | 是 | 受保护资源的 URL |
resource.description | String | 否 | 资源描述 |
resource.mimeType | String | 否 | 预期响应的 MIME 类型 |
accepted | Object | 是 | Buyer 选中的支付方式(从 accepts 数组中选取),结构同 PaymentRequirements |
payload | Object | 是 | 签名数据 |
payload.signature | String | 是 | 签名(编码与路径相关,见下文 Permit2Authorization) |
payload.authorization | Object | 条件 | EIP-3009 授权对象,exact + EIP-3009 时必填 |
payload.permit2Authorization | Object | 条件 | Permit2 授权对象,exact + Permit2 / upto 时必填 |
约束:payload.authorization 与 payload.permit2Authorization 严格二选一,否则返回 param_mismatch。
PaymentRequirements#
同时用作 402 响应 accepts 数组元素和 paymentPayload.accepted。
| 参数 | 类型 | 必传 | 描述 |
|---|---|---|---|
scheme | String | 是 | "exact" / "upto" / "aggr_deferred" |
network | String | 是 | CAIP-2 链标识,如 eip155:196 |
amount | String | 是 | 金额(原子单位字符串)。exact = 实付;upto verify 阶段 = 上限,settle 阶段 = 实付 |
asset | String | 是 | 代币合约地址 |
payTo | String | 是 | 收款钱包地址 |
maxTimeoutSeconds | Integer | 否 | 支付完成的最大超时时间(秒) |
extra | Object | 否 | scheme 特有扩展,见下表 |
extra 子字段:
| 子字段 | 适用 scheme | 说明 |
|---|---|---|
name / version | exact (EIP-3009) | EIP-712 domain 字段,部分 token 需要 |
assetTransferMethod | exact / upto | "permit2" 走 Permit2 路径;缺省 / "eip3009" 走 EIP-3009 |
facilitatorAddress | upto | facilitator EOA 地址 |
sessionCert | upto (SESSION) | base64 session cert |
signatureScheme | upto | "secp256k1" / "ed25519" |
Authorization#
exact + EIP-3009 路径专用。
| 参数 | 类型 | 必传 | 描述 |
|---|---|---|---|
from | String | 是 | 付款方钱包地址(EOA) |
to | String | 是 | 收款方钱包地址(应等于 payTo) |
value | String | 是 | 支付金额(原子单位,应等于 amount) |
validAfter | String | 是 | 授权生效的 Unix 时间戳 |
validBefore | String | 是 | 授权过期的 Unix 时间戳 |
nonce | String | 是 | 32 字节随机 nonce(0x hex,防重放) |
Permit2Authorization#
exact + Permit2 / upto 路径专用。
| 子字段 | 类型 | 必传 (exact + Permit2) | 必传 (upto) | 说明 |
|---|---|---|---|---|
from | String | ✅ | ✅ | Buyer 钱包地址(EOA 路径:EOA;SESSION 路径:AA) |
permitted.token | String | ✅ | ✅ | 代币合约地址 |
permitted.amount | String | ✅ | ✅ | exact = 实付;upto = 授权上限 |
spender | String | ✅ | ✅ | exact: x402ExactPermit2Proxy;upto: x402UptoPermit2Proxy |
nonce | String | ✅ | ✅ | Permit2 nonce 十进制字符串(uint256) |
deadline | String | ✅ | ✅ | Permit2 deadline Unix 时间戳 |
witness.to | String | ✅ | ✅ | 收款方地址,必须等于 accepted.payTo |
witness.facilitator | String | — | ✅ | upto 必填;exact 路径忽略此字段 |
witness.validAfter | String | ✅ | ✅ | 授权生效 Unix 时间戳 |
payload.signature 编码规则:
| 路径 | 编码 |
|---|---|
exact + Permit2(EOA) | 0x 前缀 65 byte hex,secp256k1 r‖s‖v(EIP-2 低 s) |
upto + EOA | 同上 |
upto + SESSION | base64 编码的 Ed25519 签名 |
Permit2 链上前置条件:buyer 必须对 Permit2 canonical 合约 0x000000000022D473030F116dDEE9F6B43aC78BA3 执行 approve(MAX_UINT256),否则 verify 返回 insufficient_allowance。
Challenge#
由服务端签发的 Challenge 对象,客户端原样回传(仅 charge 使用)。
| 参数 | 类型 | 必传 | 描述 |
|---|---|---|---|
id | String | 是 | Challenge ID |
realm | String | 是 | 保护空间标识 |
method | String | 是 | 固定 "evm" |
intent | String | 是 | 支付意图:"charge" / "session" |
request | String | 是 | base64url 编码的请求参数 |
expires | String | 是 | 过期时间(ISO 8601) |
Split#
charge 分账列表中的单条分账项,每笔需独立签名。
| 参数 | 类型 | 必传 | 描述 |
|---|---|---|---|
from | String | 是 | 付款方地址(与主签名相同) |
to | String | 是 | 分账收款方地址 |
value | String | 是 | 分账金额(base units) |
validAfter | String | 是 | 授权生效 Unix 时间戳 |
validBefore | String | 是 | 授权过期 Unix 时间戳 |
nonce | String | 是 | 独立 nonce(bytes32) |
signature | String | 是 | 65 字节 EIP-712 签名 |
支持的网络和币种#
| 网络 | Chain Index | 状态 |
|---|---|---|
| X Layer | 196 | 已支持 |
X Layer 支持的稳定币:
| 币种 | 合约地址 |
|---|---|
| USDG | 0x4ae46a509f6b1d9056937ba4500cb143933d2dc8 |
| USD₮0 | 0x779ded0c9e1022225f8e0630b35a9b54be713736 |
错误码#
错误响应统一使用包络 {"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 状态 | 描述 |
|---|---|---|
| 50011 | 429 | 用户请求频率过快,超过该接口允许的限额 |
| 50014 | 400 | 必填参数 {param} 不能为空 |
3. 业务错误#
| 错误码 | HTTP 状态 | 描述 |
|---|---|---|
| 50026 | 500 | 系统错误,请稍后重试 |
| 81001 | 200 | {param} 参数错误 |
| 81004 | 200 | 不支持的链 |
| 80007 | 200 | 风险地址 |
4. exact / upto verify / settle 业务字段#
exact / upto 接口的失败原因通过响应 data 中的 invalidReason(verify)或 errorReason(settle / settle/status)返回,常见取值:
| 字段值 | 适用接口 | 描述 |
|---|---|---|
insufficient_funds | verify, settle | 付款方余额不足(兼容旧版) |
insufficient_balance | verify, settle | 余额扣除 pending 后不足实付 |
insufficient_allowance | verify, settle | buyer 对 Permit2 canonical 合约的 ERC-20 allowance 不足 |
nonce_already_used | verify, settle | nonce 已被使用 |
expired_authorization | verify, settle | 授权已过期(兼容旧版) |
expired | verify, settle | deadline 已过 |
not_yet_valid | verify, settle | validAfter > now |
signature_invalid | verify, settle | 签名校验失败(兼容旧版) |
invalid_signature | verify, settle | secp256k1 / Ed25519 验签失败 / 格式错 / 低 s 违反 |
requirements_mismatch | verify, settle | accepted 与 paymentRequirements 不一致(兼容旧版) |
param_mismatch | verify, settle | 字段缺失 / 互斥违反 / 一致性校验失败 |
unsupported_scheme | verify, settle | scheme 未启用(Apollo 灰度开关关闭) |
unsupported_chain | verify, settle | chainIndex 不在配置 |
payer_blocked | verify, settle | buyer 命中黑名单 |
risk_address | verify, settle | KYS 合规拦截(payer 或 payTo) |
transaction_reverted | settle | 链上交易回滚 |
chain_unavailable | settle | 链上 RPC 不可用 |
onchain_error | verify | verify 阶段 multicall 调用异常 |
onchain_recheck_error | settle | settle 阶段链上 TOCTOU 二次校验失败 |
settle_busy | settle | 同一 (payer, token) 并发结算锁冲突 |
settle_interrupted | settle | 等锁期间线程被中断 |
not_found | settle/status | txHash 不在 Broker 记录中 |
invalid_permit2_spender | verify (exact + permit2) | spender ≠ x402ExactPermit2Proxy |
permit2_token_mismatch | verify (exact + permit2) | permitted.token ≠ accepted.asset |
permit2_amount_mismatch | verify (exact + permit2) | permitted.amount ≠ paymentRequirements.amount |
invalid_permit2_recipient_mismatch | verify (exact + permit2) | witness.to ≠ accepted.payTo |
permit2_not_yet_valid | verify (exact + permit2) | witness.validAfter > now |
permit2_deadline_expired | verify, settle (permit2) | deadline ≤ now + buffer |
invalid_permit2_signature | verify (exact + permit2) | Permit2 EIP-712 签名验证失败 |
invalid_spender | verify (upto) | spender ≠ x402UptoPermit2Proxy |
invalid_amount | verify (upto) | upto ceiling ≤ 0 |
upto_signature_route_conflict | verify (upto) | sessionCert 与 signatureScheme 互斥校验失败 |
upto_facilitator_mismatch | verify, settle (upto) | witness.facilitator 缺失 / 非法 / 不在白名单 / 与 accepted.extra.facilitatorAddress 不一致 |
upto_invalid_settlement_amount | settle (upto) | paymentRequirements.amount 为负或格式错 |
upto_settlement_exceeds_amount | settle (upto) | settle 实付 > permit ceiling |
invalid_eoa_signature | settle (upto + EOA) | EOA sig 非 0x 前缀或长度 ≠ 65 byte |
tee_sign_failed | settle (upto + SESSION) | TEE signMsg(eip712Hash) 转签失败 |
account_resolve_error | settle (upto + SESSION) | AA 账户解析失败 |
intent_submit_failed | settle (upto) | Intent Framework 提交失败 |
5. charge 业务错误#
| 错误码 | 错误名称 | 描述 |
|---|---|---|
| 8000 | SERVICE_ERROR | API 服务内部错误 |
| 70000 | invalid_params | 缺少必填字段或格式错误 |
| 70001 | unsupported_chain | 链不在支持列表 |
| 70002 | payer_blocked | 付款方在黑名单 |
| 70003 | invalid_credential | source 缺失、或 txHash 已被使用 |
| 70004 | invalid_signature | 签名验证失败 |
| 70005 | split_sum_exceeds_total | 分账总额 >= 总金额 |
| 70006 | split_count_exceeded | 分账数量 > 10 |
| 70007 | tx_not_confirmed | 交易未在链上确认 |
| 70009 | challenge_invalid | Challenge 不存在或已过期 |
- 选 scheme认证exact Scheme1. /api/v6/pay/x402/supported请求参数响应参数请求示例响应示例2. /api/v6/pay/x402/verify请求参数响应参数请求示例 — exact + EIP-3009请求示例 — exact + Permit2响应示例 — 验证通过响应示例 — 验证失败3. /api/v6/pay/x402/settle请求参数响应参数请求示例 — exact + EIP-3009 同步结算请求示例 — exact + Permit2 异步结算响应示例 — exact 同步结算成功(syncSettle=true)响应示例 — exact 异步结算(syncSettle=false)响应示例 — exact 等待超时(syncSettle=true)响应示例 — 结算失败4. /api/v6/pay/x402/settle/status请求参数响应参数请求示例响应示例 — 查询成功(exact)响应示例 — 查询成功(upto)响应示例 — 交易未找到upto Scheme双签名路径5. /api/v6/pay/x402/verify — scheme=upto请求示例 — upto + EOA请求示例 — upto + SESSION(OKX agentic wallet)响应6. /api/v6/pay/x402/settle — scheme=uptosettle 响应矩阵请求示例响应示例 — 正常广播响应示例 — 零结算响应示例 — 失败charge Scheme7. /api/v6/pay/mpp/charge/settle请求参数响应参数请求示例响应示例请求示例 — 含分账8. /api/v6/pay/mpp/charge/verifyHash请求参数响应参数请求示例响应示例公共数据结构PaymentPayloadPaymentRequirementsAuthorizationPermit2AuthorizationChallengeSplit支持的网络和币种错误码1. 认证错误(HTTP 401)2. 请求错误3. 业务错误4. exact / upto verify / settle 业务字段5. charge 业务错误
