A minimal AI agent that pays Inferit per request with x402: no account, no API key, and no WBT until it withdraws.
One TypeScript file, the official x402 client and viem. It runs against Inferit's hosted testnet API on Whitechain Sepolia.
Status: Testnet demo on Whitechain Sepolia. Prices settle in Inferit Test Credit (ITC), a test token with no monetary value. The contracts are not audited.
x402 is an open payment protocol built on HTTP 402 Payment Required. Inferit's API speaks x402 v2, so an agent can pay for each request with a signature instead of an account. src/agent.ts does it in four steps:
- Discovery.
GET /.well-known/x402says what is paid and how: theexactscheme (EIP-3009transferWithAuthorization), the network (eip155:1874, Whitechain Sepolia), the token (ITC) andpayTo, the market's escrow contract (MarketEscrow). - Test tokens. If the agent holds less than the minimum payment, it claims 1,000 test ITC from Inferit's sponsored faucet (
POST /v1/faucet). The API pays the gas, once per 24 h per address. - Pay per request. A
POST /v1/chat/completionswith noAuthorizationheader answers 402 with a quote inPAYMENT-REQUIRED: the worst-case cost of that exact body, at least 10 000 µ (0.01 ITC), pinned for 120 s. The x402 client signs an EIP-3009 authorization for the quote, to the escrow, and resends the request withPAYMENT-SIGNATURE. The API deposits the payment as the agent's own escrow balance, then serves the request. - Receipt.
PAYMENT-RESPONSEnames the deposit transaction. The request is charged its metered cost (x-inferit-buyer-cost-micro, settled on chain in batches later), not the quote. The rest stays the agent's escrow balance.
The payment is standard x402 v2; only the faucet claim and the x-inferit-* cost headers are Inferit's. The dependencies are @x402/fetch, @x402/evm and viem, with tsx to run the TypeScript.
You need Node.js 20 or newer.
npm install
npm start # a fresh throwaway key for this runTo pay from the same address every time, put its private key in AGENT_KEY:
export AGENT_KEY=0x... # 0x + 64 hex characters: a test key only
npm startThe key is read from the environment and never written anywhere. Use a key made for testing, never one that holds anything of value.
| Token | What it is for | Where it comes from |
|---|---|---|
| ITC (Inferit Test Credit) | Paying for inference: 1 µ = 0.000001 ITC | The agent claims it from Inferit's faucet by itself: POST https://api-production-c74b9.up.railway.app/v1/faucet with {"address": "0x..."}, 1,000 ITC per address per 24 h, gas sponsored. A second claim within 24 h gets 429 faucet_cooldown |
| WBT (Whitechain's gas token) | Not needed to pay with x402. Only for transactions you send yourself, such as a withdrawal from the escrow | The Whitechain faucet: https://faucet.testnet.whitechain.io |
Both are test tokens with no monetary value.
A run on 2026-10-13 with a reused test key (AGENT_KEY), which already held ITC, so it skipped the faucet (the agent's address is shortened here; the run prints it in full):
agent 0x48C7…1A53 -> https://api-production-c74b9.up.railway.app
pays ITC on Whitechain Sepolia (eip155:1874) into the escrow 0x705dD9eCffa888FbcF2849eAE2D3b136eb78B7e0
holds 1999.95 ITC
Pay-per-request suits AI agents because it allows for cost-efficiency by billing only for the actual usage of AI services, which is particularly beneficial for services with variable demand.
model: qwen/qwen-2.5-14b-instruct
paid 10000 base units of ITC (deposit tx https://explorer.testnet.whitechain.io/tx/0x3b77ef78671ca06466c2e05d17b105039fa11fa07aa6174b0a4ba75773808787)
charged 9 base units for this request; the rest stays 0x48C7…1A53's escrow balance
With a fresh key, the third line reads holds 0 ITC and the next one faucet: 1000 ITC minted (tx 0x…). ITC has 6 decimals, so a base unit is one µ: this run paid 10 000 µ into the escrow and was charged 9 µ.
verified 2026-10-13: model qwen/qwen-2.5-14b-instruct, max_tokens 64, @x402/fetch 2.28.0 and viem 2.57.5: answered, paid 10000 base units (0.01 ITC), charged 9, deposit 0x3b77ef78…8787 (status 1, to the escrow).
| Variable | Default | What it is |
|---|---|---|
AGENT_KEY |
A fresh key per run | The payer's private key, 0x + 64 hex characters |
INFERIT_BASE_URL |
https://api-production-c74b9.up.railway.app/v1 |
The hosted testnet API |
INFERIT_MODEL |
qwen/qwen-2.5-14b-instruct |
A model with a live seller (GET /v1/models, rows with a best_price), or auto when GET /v1/routing lists a model in candidates_now |
PROMPT |
A one-sentence question | What to ask |
MAX_TOKENS |
64 |
The answer's token limit. The quote is the worst case for the body, so a small limit keeps it small |
STREAM |
off | STREAM=1 streams the answer (server-sent events). A streamed answer's cost comes as an HTTP trailer, which fetch does not expose, so that run prints no charged line |
MAX_PAYMENT |
1000000 (1 ITC) |
The most the client signs for one request, in base units |
RPC_URL |
https://rpc.testnet.whitechain.io |
A Whitechain Sepolia RPC, to read the agent's ITC balance |
import { wrapFetchWithPayment, x402Client } from '@x402/fetch';
import { ExactEvmScheme } from '@x402/evm/exact/client';
import { privateKeyToAccount } from 'viem/accounts';
const account = privateKeyToAccount(process.env.AGENT_KEY as `0x${string}`);
const client = new x402Client()
.register('eip155:*', new ExactEvmScheme(account))
// Recent x402 clients pay only assets they know: allow ITC on Whitechain Sepolia, capped per payment.
.setSpendControls({
allowedAssets: [{ network: 'eip155:1874', asset: '0x2E672dFE33EA977FD064E01aDe7d8c73B3Be7fBB', maxAmountPerPayment: '1000000' }],
});
const paidFetch = wrapFetchWithPayment(fetch, client);
const res = await paidFetch('https://api-production-c74b9.up.railway.app/v1/chat/completions', {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ model: 'qwen/qwen-2.5-14b-instruct', max_tokens: 64, messages: [{ role: 'user', content: 'Hello' }] }),
});Standard x402 v2 clients pay once the asset is allowed in the client's spend controls, as above, with plain-key (EOA) signers. To use x402 from LangChain or the Vercel AI SDK, see inferit-examples.
The unused part of each payment stays the agent's balance in the escrow contract, MarketEscrow. The agent can spend it later with an API key (sign in with the same wallet: POST /v1/auth/evm/challenge, /v1/auth/evm/verify, then POST /v1/keys) or withdraw it. A withdrawal is two steps, with a 1 h delay, and it is a transaction, so it needs a little WBT. Escrow details: https://inferit.cc/docs/payments/whitechain
- inferit-examples: LangChain, the Vercel AI SDK, LiteLLM, CrewAI and OpenCode on Inferit.
- inferit-seller: sell inference from your own computer, one command, no open port.
- whitechain-x402-facilitator: the first public x402 v2 facilitator for Whitechain, live on Whitechain Sepolia (testnet).
- For agents: https://inferit.cc/agents and the machine-readable https://inferit.cc/agents.md