QUICKSTART · 5 MINUTES
Your agent's first paid call
Any agent with USDC on Base buys a result per call, no account. You are charged only when the result exists; failures are never charged.
1. Discover what you can buy
The machine list has every product with its price, network and input schema.
curl -s https://a-upgradenet.com/.well-known/x4022. Read the price
An unpaid POST answers 402 with the PAYMENT-REQUIRED header. Nothing is charged.
curl -i -X POST https://a-upgradenet.com/x402/web-read \
-H "content-type: application/json" \
-d '{"url":"https://example.com"}'
# HTTP/2 402
# payment-required: <base64 JSON: price, payTo, network eip155:8453, USDC, input schema>
# {"x402Version":2,"error":"Pay 0.005 USDC on Base with x402. No account needed.", ...}3. Pay and get the result
Sign exactly that price with an x402 client and repeat the same request with PAYMENT-SIGNATURE. Use a wallet with a small balance.
npm install @x402/core @x402/evm viemimport { x402Client } from "@x402/core/client";
import { ExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";
const url = "https://a-upgradenet.com/x402/web-read";
const headers = { "content-type": "application/json" };
const body = JSON.stringify({ url: "https://example.com" });
// 1) Ask for the price: unpaid POST answers 402 + PAYMENT-REQUIRED
const quote = await fetch(url, { method: "POST", headers, body });
if (quote.status !== 402) throw new Error(`expected 402, got ${quote.status}`);
const required = JSON.parse(
Buffer.from(quote.headers.get("PAYMENT-REQUIRED")!, "base64").toString("utf8")
);
// 2) Sign exactly that price (EIP-3009, USDC on Base) with the agent's own wallet
const account = privateKeyToAccount(process.env.AGENT_WALLET_KEY as `0x${string}`);
const client = new x402Client().register("eip155:8453", new ExactEvmScheme(account));
const payload = await client.createPaymentPayload(required);
const signature = Buffer.from(JSON.stringify(payload)).toString("base64");
// 3) Repeat the same request with PAYMENT-SIGNATURE
const res = await fetch(url, {
method: "POST",
headers: { ...headers, "PAYMENT-SIGNATURE": signature },
body
});
const result = await res.json();
if (!res.ok) throw new Error(`${result.error.code}: ${result.error.message}`);
console.log(result.status, result.transaction); // "completed", 0x... settlement tx4. Retry without paying twice
If the response says retryable, wait Retry-After and repeat with the same signature. You get the stored result.
// Same request + same PAYMENT-SIGNATURE = stored result, never a second charge.
async function buyWithRetry(send: () => Promise<Response>, attempts = 4) {
for (let i = 0; i < attempts; i++) {
const res = await send();
if (res.ok) return res.json();
const { error } = await res.json();
if (!error?.retryable) throw new Error(`${error?.code}: ${error?.message}`);
const wait = Number(res.headers.get("Retry-After") ?? 5);
await new Promise(r => setTimeout(r, wait * 1000));
}
throw new Error("still not completed; retry later with the same signature");
}5. Handle errors by code
Every error is JSON with a stable code. Decide with error.code and error.retryable, never with the message text.
{"error":{"code":"INVALID_INPUT","message":"... Nothing was charged.","retryable":false,"request_id":"req_..."}}Per-call products
POST /x402/tool-call-audit 0.1 USDC Tool-Call Audit
POST /x402/tool-call-audit-pro 0.15 USDC Tool-Call Audit Pro
POST /x402/tool-call-audit-max 0.2 USDC Tool-Call Audit Max
POST /x402/planning-benchmark 0.1 USDC Planning Benchmark
POST /x402/memory-health 0.05 USDC Memory Health Check
POST /x402/web-read 0.005 USDC Web Page Reader
POST /x402/base-balance 0.001 USDC Base Wallet Balance
POST /x402/base-tx 0.002 USDC Base Transaction Lookup
POST /x402/base-token 0.002 USDC Base Token Info
POST /x402/base-block 0.001 USDC Base Latest BlockNext
GET https://a-upgradenet.com/AGENTS.md AGENTS.md: full rules for agents
GET https://a-upgradenet.com/openapi.json OpenAPI 3.1: schemas, examples and limits
GET https://a-upgradenet.com/changelog.md API changelog