How to Use Ace Data Cloud SDK with X402 Payments

How to Use Ace Data Cloud SDK with X402 Payments

Ace Data Cloud supports an X402 payment flow that lets the SDK pay for a request after the server responds with 402 Payment Required. Instead of providing an API token, configure a payment handler. The handler signs the server-provided payment envelope locally, and the SDK retries the original request with a PAYMENT-SIGNATURE header.

Understand the X402 request flow

The flow begins when a request such as /openai/v1/chat/completions is sent without an Authorization header. The server returns 402 Payment Required and an accepts array. The SDK calls your local payment hook with:

paymentHandler({ url, method, body, accepts })

Your handler returns headers containing PAYMENT-SIGNATURE. The SDK then resends the original request with that header. After verification and settlement, the server returns the normal 200 business response.

The payment envelope includes fields such as x402Version: 2, an accepted scheme and network, and a payload. An example accepted value uses scheme: 'upto' with network: 'eip155:8453'. The payload can contain permit2.permitted token and amount information, plus a nonce, deadline, witness, and signature.

Choose the correct payment scheme

Two schemes are available:

  • exact is for a fixed price.
  • upto is for metered billing, including chat and token types.

Use preferScheme in TypeScript or prefer_scheme in Python to select among schemes offered by the server. If the server exposes only exact, the preference is ignored. If upto is requested but unavailable, selection falls back to the first matching item. Chat types must use preferScheme: 'upto' or prefer_scheme='upto'.

Set up TypeScript in a browser wallet

Install the Ace Data Cloud SDK and X402 client package:

npm install @acedatacloud/sdk @acedatacloud/x402-client

The documented tested versions are @acedatacloud/sdk@2026.504.2 and @acedatacloud/x402-client@2026.531.3. For Base in a browser, request an account, switch to chain ID 0x2105, and create the handler with the injected EIP-1193 provider.

import { AceDataCloud } from '@acedatacloud/sdk'
import { createX402PaymentHandler } from '@acedatacloud/x402-client'

const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' })
const userAddress = accounts[0]

await window.ethereum.request({
  method: 'wallet_switchEthereumChain',
  params: [{ chainId: '0x2105' }],
})

const client = new AceDataCloud({
  paymentHandler: createX402PaymentHandler({
    network: 'base',
    evmProvider: window.ethereum,
    evmAddress: userAddress,
    preferScheme: 'upto',
  }),
})

const response = await client.openai.chat.completions.create({
  model: 'gpt-4o-mini',
  messages: [{ role: 'user', content: 'hi' }],
  max_tokens: 20,
})

Do not pass apiToken in X402 mode. The TypeScript handler supports solana, base, and skale. Solana requires solanaWallet; Base and SKALE require both an EIP-1193 evmProvider and evmAddress.

On the first EVM browser call, expect two signature prompts. The first is a one-time USDC Permit2 approval using MaxUint256 that is written on-chain. The second is an EIP-712 X402 envelope signature and is not written on-chain. Later calls require only the second signature.

Use Node with viem

The TypeScript X402 client accepts EIP-1193 providers rather than raw private keys. A standard Node approach is to create a viem wallet client with privateKeyToAccount, the Base chain, and http(BASE_RPC_URL). Pass walletClient as any as evmProvider and pass account.address as evmAddress. This is stable, but using as any removes type checking.

Use Solana from TypeScript

const handler = createX402PaymentHandler({
  network: 'solana',
  solanaWallet: { publicKey, signTransaction },
})

Solana currently exposes only the exact scheme, so preferScheme does not apply there. Solana also does not use Permit2.

Set up Python payments

Install the Python packages:

pip install acedatacloud acedatacloud-x402

The documented tested versions are acedatacloud==2026.4.26.1 and acedatacloud-x402==2026.5.31.3. For Base, create an EVM signer from an environment-provided private key and use the metered chat scheme.

import os
from acedatacloud import AceDataCloud
from acedatacloud_x402 import create_x402_payment_handler, EVMAccountSigner

signer = EVMAccountSigner.from_private_key(os.environ['EVM_PRIVATE_KEY'])
client = AceDataCloud(
    payment_handler=create_x402_payment_handler(
        network='base',
        evm_signer=signer,
        prefer_scheme='upto',
    )
)

res = client.openai.chat.completions.create(
    model='gpt-4o-mini',
    messages=[{'role': 'user', 'content': 'hi'}],
    max_tokens=20,
)
print(res['choices'][0]['message']['content'])

You can perform the one-time EVM Permit2 approval explicitly. Solana does not need this step.

from acedatacloud_x402 import approve_permit2

tx_hash = approve_permit2(
    evm_signer=signer,
    rpc_url=os.environ['BASE_RPC_URL'],
)

For Solana, create a signer with SolanaKeypairSigner.from_secret_key_base58(os.environ['SOLANA_PRIVATE_KEY']), then call create_x402_payment_handler with network='solana', solana_signer=signer, and optionally rpc_url='https://api.mainnet-beta.solana.com'.

Test wiring before spending USDC

You can verify local wiring without an end-to-end on-chain payment. Constructing AceDataCloud with a payment handler and no apiToken should succeed, and createX402PaymentHandler should return a function. The handler is called only after the SDK receives a 402. A real end-to-end on-chain test consumes real USDC.

When troubleshooting, separate payment failures from normal API failures. A failed 402 handler can surface as an X402SignError, whose type varies by chain. Normal business errors, including 401, 422, and 5xx, are different failures.

For the complete SDK and X402 payment reference, see the Ace Data Cloud SDK + X402 Payment Hook documentation.

Comments

Popular posts from this blog

Artistic QR Code API Integration Guidance

How to Configure Claude Code with CC Switch and Ace Data Cloud

How to Build a Server-Side Image Editing Workflow with GPT-Image-2