A Practical Guide to Pay-Per-Call AI APIs with the Ace Data Cloud SDK and X402

If you are building a CLI, backend worker, or agent that calls AI APIs on behalf of different users, API keys are often the awkward part: who owns the balance, who rotates the token, and how do you charge only for one call? The paymentHandler hook in the Ace Data Cloud SDK gives you another path: let the first request receive 402 Payment Required, sign an X402 payment envelope locally, then retry the same API call with a PAYMENT-SIGNATURE header.
What you can do
The documented flow is useful when you want business code to stay close to a normal SDK call while payment happens per request. In practice, you can:
- Call
client.openai.chat.completions.create(...)without passing anapiToken. - Inject a TypeScript or Python
paymentHandlerthat signs the payment challenge after a402. - Use EVM networks such as
baseorskale, or usesolanawhere the Solana signer path is supported. - Choose
preferScheme: 'upto'/prefer_scheme="upto"for metered chat-style usage, where actual settlement depends on usage rather than a fixed amount.
How it works
The SDK request path is intentionally simple. The first request goes to /openai/v1/chat/completions without an Authorization header. The server responds with 402 Payment Required and an accepts array describing acceptable schemes, networks, and required amounts. The SDK then calls your local paymentHandler({ url, method, body, accepts }). Your handler returns headers, usually including PAYMENT-SIGNATURE. The SDK resends the original request with that header and receives the normal business response.
The X402 envelope itself is JSON, base64-encoded into the PAYMENT-SIGNATURE header. At the top level it includes x402Version: 2 and an accepted object with the chosen scheme and network, for example scheme: "upto" and network: "eip155:8453" for Base.
Choosing between exact and upto
The documentation distinguishes two schemes. exact is for fixed-price work, such as a one-off generation or search call where the required amount is known before execution. upto is for metered billing, especially chat completions or token-based APIs. With upto, the signer authorizes an upper limit, and settlement is based on actual usage.
For chat completions, the practical rule is straightforward: prefer upto. In TypeScript that means preferScheme: 'upto'; in Python it is prefer_scheme="upto". If the server exposes only exact, the preference is ignored or falls back to a matching item. Solana currently exposes only exact, so preferScheme does not affect that path.
TypeScript browser wallet setup
For a browser app, the TypeScript package accepts an EIP-1193 provider. That means MetaMask or WalletConnect-style providers can be used directly. The complete documented option shape is:
export interface X402PaymentHandlerOptions {
network: 'solana' | 'base' | 'skale';
solanaWallet?: SolanaWalletAdapter;
evmProvider?: EVMProvider;
evmAddress?: string;
preferScheme?: 'exact' | 'upto';
}
A minimal browser flow looks like this:
import { AceDataCloud } from '@acedatacloud/sdk';
import { createX402PaymentHandler } from '@acedatacloud/x402-client';
const accounts: string[] = await (window as any).ethereum.request({
method: 'eth_requestAccounts'
});
const userAddress = accounts[0];
await (window as any).ethereum.request({
method: 'wallet_switchEthereumChain',
params: [{ chainId: '0x2105' }] // 8453 = Base
});
const client = new AceDataCloud({
paymentHandler: createX402PaymentHandler({
network: 'base',
evmProvider: (window as any).ethereum,
evmAddress: userAddress,
preferScheme: 'upto'
})
});
const res: any = await client.openai.chat.completions.create({
model: 'gpt-4o-mini',
messages: [{ role: 'user', content: 'hi' }],
max_tokens: 20
});
console.log(res.choices[0].message.content);
The first EVM call can involve two approvals: a one-time USDC Permit2 approval and an EIP-712 signature for the X402 envelope. Later calls generally require only the envelope signature. That distinction matters for UX: explain the first-time approval separately from the per-call signature.
Python private-key mode for workers
For backend workers or task runners, the Python package signs directly from a private key. The documented installation is:
pip install acedatacloud acedatacloud-x402
The EVM path uses EVMAccountSigner.from_private_key and injects payment_handler into AceDataCloud:
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"])
On EVM Base, Permit2 approval can be handled once with approve_permit2 and a BASE_RPC_URL. Solana does not use Permit2; the documented Solana path uses SolanaKeypairSigner.from_secret_key_base58 and can optionally pass rpc_url="https://api.mainnet-beta.solana.com".
Common mistakes to avoid
- Do not pass both token authentication and X402 assumptions into the same mental model. For X402 mode, construct the client without
apiTokenand providepaymentHandler. - Do not use raw private keys with the TypeScript
createX402PaymentHandler. The documented TypeScript EVM path expects an EIP-1193 provider; for Node, wrap the key with a viemWalletClient. - Use
preferScheme: 'upto'for chat-style metered usage. Usingexactfor chat can authorize the maximum required amount instead of usage-based settlement. - Separate payment errors from API errors. A
402leads into the handler; after retry, normal business errors such as401,422, or5xxare still ordinary SDK exceptions.
Where this fits
X402 is not a replacement for every API key. For your own backend, a token can still be the simplest path. But for agentic calls, third-party developers, CLIs, and per-user payment flows, the SDK hook keeps the API call readable while moving payment authorization to the wallet that owns the spend.
Read the full source documentation here: SDK + X402 Payment Hook.
Comments
Post a Comment