The Buyer issues a Session Key certificate (sessionCert) inside their AA wallet; every call is signed with that Session Key, and the Facilitator aggregates many authorizations and settles them in a single on-chain transaction. Suitable for high-frequency low-value scenarios — continuous Agent consumption, etc.
- Base URL:
https://web3.okx.com
- Path prefix:
/api/v6/pay/x402
- Scheme:
aggr_deferred
- Network: X Layer (CAIP-2 identifier
eip155:196)
Authentication
All endpoints require API Key authentication. Include the following headers:
| Header | Required | Description |
|---|
OK-ACCESS-KEY | Yes | API Key |
OK-ACCESS-SIGN | Yes | Request signature |
OK-ACCESS-PASSPHRASE | Yes | API passphrase |
OK-ACCESS-TIMESTAMP | Yes | ISO 8601 timestamp |
Content-Type | Yes | Set to application/json for POST requests |
All responses use a uniform business envelope:
On business errors, code is non-"0" and data is null. See the Error codes section at the bottom for the full list.
Differences from exact mode
The endpoint paths are identical to exact. Key field differences:
| Field | exact | aggr_deferred |
|---|
accepted.scheme | "exact" | "aggr_deferred" |
accepted.extra.sessionCert | absent | Required: Session Key certificate (base64) |
payload.signature | EOA signature | Session Key signature |
authorization.from | EOA address | Buyer's AA wallet address |
settle.syncSettle | Optional, default false | Not applicable, ignored |
settle response transaction | On-chain txHash | Empty string at intake; obtain via /settle/status after the batch lands on-chain |
settle response status | pending / success / timeout / "" | Returns "success" immediately on intake |
sessionCert lifecycle: The Buyer carries it in paymentPayload.accepted.extra.sessionCert → the Seller forwards it verbatim → the Facilitator extracts and verifies it inside the TEE. The Seller does not parse this field. sessionCert must not appear in paymentRequirements.extra.
1. /api/v6/pay/x402/supported
GET
/api/v6/pay/x402/supported
Returns the schemes, networks, and signers supported by the Facilitator. In batch mode, kinds includes the aggr_deferred entry.
Request parameters
None.
Response parameters
| Parameter | Type | Description |
|---|
kinds | Array<SupportedKind> | List of supported payment kinds |
kinds[].x402Version | Integer | x402 protocol version, e.g. 2 |
kinds[].scheme | String | Settlement scheme: exact / aggr_deferred |
kinds[].network | String | CAIP-2 chain identifier, e.g. eip155:196 |
kinds[].extra | Object | Scheme-specific extra config |
extensions | Array<String> | List of supported extension identifiers |
signers | Object | Map from CAIP-2 wildcard to an array of signer addresses |
Response example
2. /api/v6/pay/x402/verify
POST
/api/v6/pay/x402/verify
Verifies the Buyer's PaymentPayload:
- Parses and validates
accepted.extra.sessionCert (verifies the AA-wallet issuance chain inside the TEE).
- Verifies that
payload.signature was produced by the Session Key authorized in the sessionCert.
- Verifies that the authorization amount, validity window,
payTo, and asset all fall within the sessionCert's allowed scope.
- Verifies that
nonce has not been used.
Request parameters
| Parameter | Type | Required | Description |
|---|
x402Version | Integer | Yes | x402 protocol version, e.g. 2 |
paymentPayload | Object | Yes | The x402 payment payload the client carries with the protected request. See PaymentPayload |
paymentRequirements | Object | Yes | Payment requirements declared by the Seller. See PaymentRequirements |
Constraints:
paymentPayload.accepted.scheme and paymentRequirements.scheme must both be "aggr_deferred".
paymentPayload.accepted.extra.sessionCert is required (base64-encoded string).
Response parameters
| Parameter | Type | Description |
|---|
isValid | Boolean | true if verification passed, false otherwise |
invalidReason | String | Machine-readable reason (returned on failure) |
invalidMessage | String | Human-readable explanation (returned on failure) |
payer | String | Payer AA address |
Request example
Response example — verification passed
Response example — sessionCert expired
3. /api/v6/pay/x402/settle
POST
/api/v6/pay/x402/settle
Persists a verified authorization, queued for the Facilitator's background batch settlement. A response only means "accepted" — it does not mean the payment has landed on-chain.
Request parameters
| Parameter | Type | Required | Description |
|---|
x402Version | Integer | Yes | x402 protocol version, e.g. 2 |
paymentPayload | Object | Yes | Same as verify |
paymentRequirements | Object | Yes | Same as verify |
In aggr_deferred mode, the syncSettle field is ignored.
Response parameters
| Parameter | Type | Description |
|---|
success | Boolean | Whether intake succeeded |
errorReason | String | Reason for intake failure (machine-readable) |
errorMessage | String | Failure explanation (human-readable) |
payer | String | Payer AA address |
transaction | String | Empty string at intake; obtain via /settle/status after the batch lands on-chain |
network | String | CAIP-2 chain identifier |
status | String | On successful intake, fixed "success" |
Request example
Response example — intake success
Response example — intake failure
Once the Seller receives success: true, the resource can be released to the Buyer. The final on-chain outcome is tracked asynchronously via /settle/status.
4. /api/v6/pay/x402/settle/status
GET
/api/v6/pay/x402/settle/status
After the batch lands on-chain, the Facilitator associates the batch's on-chain txHash with each original payment in the batch. The Seller queries it through this endpoint.
Request parameters
| Parameter | Location | Type | Required | Description |
|---|
txHash | query | String | Yes | On-chain transaction hash of the batch (delivered to the Seller via backend events or async notifications) |
Response parameters
| Parameter | Type | Description |
|---|
success | Boolean | Whether the query succeeded |
errorReason | String | Failure reason |
errorMessage | String | Failure explanation |
payer | String | Payer AA address |
transaction | String | The batch's on-chain txHash |
network | String | CAIP-2 chain identifier |
status | String | pending / success / failed |
Request example
Response example — batch settled on-chain
Response example — still aggregating
Response example — on-chain failure
Shared data structures
PaymentPayload
After signing, the Buyer passes the payload to the Seller through the X-PAYMENT header (base64-encoded), and the Seller forwards it verbatim to the Facilitator.
| Parameter | Type | Required | Description |
|---|
x402Version | Integer | Yes | Protocol version, e.g. 2 |
resource | Object | No | Description of the protected resource |
resource.url | String | Yes | URL of the protected resource |
resource.description | String | No | Resource description |
resource.mimeType | String | No | Expected MIME type of the response |
accepted | Object | Yes | The payment option chosen by the Buyer (same shape as PaymentRequirements, but extra.sessionCert is required) |
payload | Object | Yes | Signature data |
payload.signature | String | Yes | EIP-712 signature by the Session Key over the EIP-3009 message |
payload.authorization | Object | Yes | EIP-3009 authorization parameters. See Authorization |
PaymentRequirements
| Parameter | Type | Required | Description |
|---|
scheme | String | Yes | Fixed "aggr_deferred" |
network | String | Yes | CAIP-2 chain identifier, e.g. eip155:196 |
amount | String | Yes | Payment amount (atomic-unit string) |
asset | String | Yes | Token contract address |
payTo | String | Yes | Recipient wallet address |
maxTimeoutSeconds | Integer | No | Maximum timeout for completing payment (seconds) |
extra | Object | No | Extension fields, see table below |
extra fields (paymentPayload.accepted.extra and paymentRequirements.extra differ slightly):
| Field | Type | Required | Description |
|---|
name | String | No | Token name (e.g. "USDG") |
version | String | No | Token EIP-712 domain version |
sessionCert | String | Yes (only in paymentPayload.accepted.extra) | base64-encoded Session Key certificate; must not appear in paymentRequirements.extra |
Authorization
| Parameter | Type | Required | Description |
|---|
from | String | Yes | Payer AA wallet address |
to | String | Yes | Recipient wallet address (must equal payTo) |
value | String | Yes | Payment amount (atomic units) |
validAfter | String | Yes | Unix timestamp when the authorization becomes valid |
validBefore | String | Yes | Unix timestamp when the authorization expires |
nonce | String | Yes | 32-byte random nonce (0x hex, replay protection) |
Supported networks and tokens
| Network | Chain Index | Status |
|---|
| X Layer | 196 | Supported |
Stablecoins supported on X Layer:
| Token | Contract address |
|---|
| USDG | 0x4ae46a509f6b1d9056937ba4500cb143933d2dc8 |
| USD₮0 | 0x779ded0c9e1022225f8e0630b35a9b54be713736 |
| USDC | 0x74b7f16337b8972027f6196a17a631ac6de26d22 |
Error codes
Error responses use the uniform envelope {"code": "<code>", "msg": "<message>", "data": null}.
1. Authentication errors (HTTP 401)
| Code | Description |
|---|
| 50103 | Header OK-ACCESS-KEY cannot be empty |
| 50104 | Header OK-ACCESS-PASSPHRASE cannot be empty |
| 50105 | Header OK-ACCESS-PASSPHRASE is incorrect |
| 50106 | Header OK-ACCESS-SIGN cannot be empty |
| 50107 | Header OK-ACCESS-TIMESTAMP cannot be empty |
| 50111 | Invalid OK-ACCESS-KEY |
| 50112 | Invalid OK-ACCESS-TIMESTAMP |
| 50113 | Invalid signature |
2. Request errors
| Code | HTTP status | Description |
|---|
| 50011 | 429 | Request rate exceeds the limit allowed for this endpoint |
| 50014 | 400 | Required parameter {param} cannot be empty |
3. Business errors
| Code | HTTP status | Description |
|---|
| 50026 | 500 | System error, please retry later |
| 81001 | 200 | Invalid {param} parameter |
| 81004 | 200 | Unsupported chain |
| 80007 | 200 | Risky address |
4. verify / settle business fields
x402 endpoints return failure reasons in data via invalidReason (verify) or errorReason (settle / settle/status). Common values:
| Field value | Endpoints | Description |
|---|
session_cert_invalid | verify, settle | sessionCert parsing or chain validation failed |
session_cert_expired | verify, settle | sessionCert has expired |
session_key_signature_invalid | verify | Session Key signature is invalid |
out_of_session_scope | verify | Authorization amount / recipient / asset out of sessionCert scope |
nonce_already_used | verify, settle | Nonce has already been used |
insufficient_funds | verify, settle | AA wallet balance insufficient |
expired_authorization | verify, settle | EIP-3009 authorization expired |
requirements_mismatch | verify, settle | accepted does not match paymentRequirements |
aggregator_unavailable | settle | Aggregator service unavailable |
not_found | settle/status | txHash not found in Facilitator records |