API reference

HTTP API - One-time Payment#

The Buyer signs a fresh EIP-3009 authorization on every protected-resource request, and the Facilitator settles each one on-chain individually. Aligned with the Coinbase x402 V2 protocol, with OKX extensions.

  • Base URL: https://web3.okx.com
  • Path prefix: /api/v6/pay/x402
  • Scheme: exact
  • Network: X Layer (CAIP-2 identifier eip155:196)

Authentication#

All endpoints require API Key authentication. Include the following headers:

HeaderRequiredDescription
OK-ACCESS-KEYYesAPI Key
OK-ACCESS-SIGNYesRequest signature
OK-ACCESS-PASSPHRASEYesAPI passphrase
OK-ACCESS-TIMESTAMPYesISO 8601 timestamp
Content-TypeYesSet to application/json for POST requests

All responses use a uniform business envelope:

json
{
  "code": "0",
  "msg": "success",
  "data": { /* business fields */ }
}

On business errors, code is non-"0" and data is null. See the Error codes section at the bottom for the full list.


1. /api/v6/pay/x402/supported#

GET
/api/v6/pay/x402/supported

Returns the schemes, networks, and signers supported by the Facilitator. Seller SDKs use this to build the accepts array of a 402 response.

Request parameters#

None.

Response parameters#

ParameterTypeDescription
kindsArray<SupportedKind>List of supported payment kinds
kinds[].x402VersionIntegerx402 protocol version, e.g. 2
kinds[].schemeStringSettlement scheme: exact / aggr_deferred
kinds[].networkStringCAIP-2 chain identifier, e.g. eip155:196
kinds[].extraObjectScheme-specific extra config
extensionsArray<String>List of supported extension identifiers
signersObjectMap from CAIP-2 wildcard to an array of signer addresses

Request example#

bash
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: 2023-10-18T12:21:41.274Z'

Response example#

json
{
  "code": "0",
  "msg": "",
  "data": {
    "kinds": [
      { "x402Version": 2, "scheme": "exact",         "network": "eip155:196", "extra": null },
      { "x402Version": 2, "scheme": "aggr_deferred", "network": "eip155:196", "extra": null }
    ],
    "extensions": [],
    "signers": {
      "eip155:*": ["0x...facilitatorSignerAddress"]
    }
  }
}

2. /api/v6/pay/x402/verify#

POST
/api/v6/pay/x402/verify

Verifies the validity of the Buyer's signed payment authorization. Does not execute any on-chain transaction.

Request parameters#

ParameterTypeRequiredDescription
x402VersionIntegerYesx402 protocol version, e.g. 2
paymentPayloadObjectYesThe x402 payment payload the client carries with the protected request. See PaymentPayload
paymentRequirementsObjectYesPayment requirements declared by the Seller. See PaymentRequirements

Constraint: paymentPayload.accepted.scheme and paymentRequirements.scheme must both be "exact".

Response parameters#

ParameterTypeDescription
isValidBooleantrue if verification passed, false otherwise
invalidReasonStringMachine-readable reason (returned on failure)
invalidMessageStringHuman-readable explanation (returned on failure)
payerStringPayer wallet address

Request example#

bash
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: 2023-10-18T12: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" }
  }
}'

Response example — verification passed#

json
{
  "code": "0",
  "msg": "success",
  "data": {
    "isValid": true,
    "invalidReason": null,
    "invalidMessage": null,
    "payer": "0xcb30ed083ad246b126a3aa1f414b44346e83e67d"
  }
}

Response example — verification failed#

json
{
  "code": "0",
  "msg": "success",
  "data": {
    "isValid": false,
    "invalidReason": "insufficient_funds",
    "invalidMessage": "Payer balance is below required amount",
    "payer": "0xcb30ed083ad246b126a3aa1f414b44346e83e67d"
  }
}

3. /api/v6/pay/x402/settle#

POST
/api/v6/pay/x402/settle

After verification passes, submit the payment for on-chain settlement. In exact mode, every call kicks off an independent transferWithAuthorization on-chain transaction.

Request parameters#

ParameterTypeRequiredDescription
x402VersionIntegerYesx402 protocol version, e.g. 2
paymentPayloadObjectYesSame as verify
paymentRequirementsObjectYesSame as verify
syncSettleBooleanNoOKX extension. true = wait synchronously for on-chain confirmation; false (default) = async broadcast

Response parameters#

ParameterTypeDescription
successBooleanWhether settlement succeeded
errorReasonStringMachine-readable failure reason (returned on failure)
errorMessageStringHuman-readable failure explanation (returned on failure)
payerStringPayer wallet address
transactionStringOn-chain transaction hash
networkStringCAIP-2 chain identifier
statusStringOKX extension. Settlement status, see table below

status values:

syncSettleOutcomestatustransaction
false (default)BroadcastpendingtxHash
trueOn-chain confirmedsuccesstxHash
trueWait timed outtimeouttxHash
Signature / simulation / on-chain failure""""

Request example#

bash
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: 2023-10-18T12:21:41.274Z' \
--data '{
  "x402Version": 2,
  "paymentPayload": { "...same as verify..." },
  "paymentRequirements": { "...same as verify..." },
  "syncSettle": true
}'

Response example — sync settle success (syncSettle=true)#

json
{
  "code": "0",
  "msg": "success",
  "data": {
    "success": true,
    "errorReason": null,
    "errorMessage": null,
    "payer": "0xcb30ed083ad246b126a3aa1f414b44346e83e67d",
    "transaction": "0x4f46ed8eac92ddbccfb56a88ff827db3616c7beb191adabbeeded901340bd7d5",
    "network": "eip155:196",
    "status": "success"
  }
}

Response example — async settle (syncSettle=false)#

json
{
  "code": "0",
  "msg": "success",
  "data": {
    "success": true,
    "errorReason": null,
    "errorMessage": null,
    "payer": "0xcb30ed083ad246b126a3aa1f414b44346e83e67d",
    "transaction": "0x4f46ed8eac92ddbccfb56a88ff827db3616c7beb191adabbeeded901340bd7d5",
    "network": "eip155:196",
    "status": "pending"
  }
}

Response example — settle failure#

json
{
  "code": "0",
  "msg": "success",
  "data": {
    "success": false,
    "errorReason": "insufficient_funds",
    "errorMessage": "Transaction reverted",
    "payer": "0xcb30ed083ad246b126a3aa1f414b44346e83e67d",
    "transaction": "",
    "network": "eip155:196",
    "status": ""
  }
}

4. /api/v6/pay/x402/settle/status#

GET
/api/v6/pay/x402/settle/status

Query settlement status by on-chain transaction hash. Suitable for polling under syncSettle=false async settlement.

Request parameters#

ParameterLocationTypeRequiredDescription
txHashqueryStringYesOn-chain transaction hash

Response parameters#

ParameterTypeDescription
successBooleanWhether the query succeeded (false if txHash not found)
errorReasonStringMachine-readable failure reason
errorMessageStringHuman-readable failure explanation
payerStringPayer wallet address
transactionStringOn-chain transaction hash
networkStringCAIP-2 chain identifier
statusStringCurrent settlement status: pending / success / failed

Request example#

bash
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: 2023-10-18T12:21:41.274Z'

Response example — query success#

json
{
  "code": "0",
  "msg": "success",
  "data": {
    "success": true,
    "errorReason": null,
    "errorMessage": null,
    "payer": "0xcb30ed083ad246b126a3aa1f414b44346e83e67d",
    "transaction": "0x4f46ed8eac92ddbccfb56a88ff827db3616c7beb191adabbeeded901340bd7d5",
    "network": "eip155:196",
    "status": "success"
  }
}

Response example — transaction not found#

json
{
  "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
  }
}

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.

ParameterTypeRequiredDescription
x402VersionIntegerYesProtocol version, e.g. 2
resourceObjectNoDescription of the protected resource
resource.urlStringYesURL of the protected resource
resource.descriptionStringNoResource description
resource.mimeTypeStringNoExpected MIME type of the response
acceptedObjectYesThe payment option the Buyer chose (selected from the accepts array); same shape as PaymentRequirements
payloadObjectYesSignature data
payload.signatureStringYesEIP-712 signature (EOA signature)
payload.authorizationObjectYesEIP-3009 authorization parameters. See Authorization

PaymentRequirements#

Used both as elements of the accepts array in the 402 response and as paymentPayload.accepted.

ParameterTypeRequiredDescription
schemeStringYesFixed "exact"
networkStringYesCAIP-2 chain identifier, e.g. eip155:196
amountStringYesPayment amount (atomic-unit string)
assetStringYesToken contract address
payToStringYesRecipient wallet address
maxTimeoutSecondsIntegerNoMaximum timeout for completing payment (seconds)
extraObjectNoScheme-specific extras (e.g. name / version)

Authorization#

ParameterTypeRequiredDescription
fromStringYesPayer wallet address (EOA)
toStringYesRecipient wallet address (must equal payTo)
valueStringYesPayment amount (atomic units, must equal amount)
validAfterStringYesUnix timestamp when the authorization becomes valid
validBeforeStringYesUnix timestamp when the authorization expires
nonceStringYes32-byte random nonce (0x hex, replay protection)

Supported networks and tokens#

NetworkChain IndexStatus
X Layer196Supported

Stablecoins supported on X Layer:

TokenContract address
USDG0x4ae46a509f6b1d9056937ba4500cb143933d2dc8
USD₮00x779ded0c9e1022225f8e0630b35a9b54be713736
USDC0x74b7f16337b8972027f6196a17a631ac6de26d22

Error codes#

Error responses use the uniform envelope {"code": "<code>", "msg": "<message>", "data": null}.

1. Authentication errors (HTTP 401)#

CodeDescription
50103Header OK-ACCESS-KEY cannot be empty
50104Header OK-ACCESS-PASSPHRASE cannot be empty
50105Header OK-ACCESS-PASSPHRASE is incorrect
50106Header OK-ACCESS-SIGN cannot be empty
50107Header OK-ACCESS-TIMESTAMP cannot be empty
50111Invalid OK-ACCESS-KEY
50112Invalid OK-ACCESS-TIMESTAMP
50113Invalid signature

2. Request errors#

CodeHTTP statusDescription
50011429Request rate exceeds the limit allowed for this endpoint
50014400Required parameter {param} cannot be empty

3. Business errors#

CodeHTTP statusDescription
50026500System error, please retry later
81001200Invalid {param} parameter
81004200Unsupported chain
80007200Risky address

4. verify / settle business fields#

x402 endpoints return failure reasons in data via invalidReason (verify) or errorReason (settle / settle/status). Common values:

Field valueEndpointsDescription
insufficient_fundsverify, settlePayer balance is below required amount
nonce_already_usedverify, settleNonce has already been used
expired_authorizationverify, settleAuthorization has expired
signature_invalidverify, settleSignature verification failed
requirements_mismatchverify, settleaccepted does not match paymentRequirements
transaction_revertedsettleOn-chain transaction reverted
chain_unavailablesettleOn-chain RPC unavailable
not_foundsettle/statustxHash not found in Facilitator records