{"slug": "x402-explained-http-native-micropayments-for-ai-agents-with-real-code", "title": "x402 Explained: HTTP-Native Micropayments for AI Agents (With Real Code)", "summary": "A developer has introduced x402, an HTTP-native micropayment specification that enables AI agents to pay for external services using stablecoins directly within the HTTP request/response flow. The protocol repurposes the HTTP 402 status code to signal payment requirements, allowing agents to discover prices, make payments, and receive resources without leaving the HTTP context. The developer provides real code examples demonstrating how to implement x402 on both the server and agent sides.", "body_md": "When autonomous AI agents need to call external services—LLM inference, data feeds, compute functions—they often encounter two practical problems:\n\nThe x402 specification addresses both by embedding a lightweight payment handshake directly into HTTP status codes. Agents can discover a price, pay it with a stablecoin, and receive the requested resource—all without leaving the HTTP request/response flow.\n\nx402 is an extension of the HTTP status code space. It repurposes the **402 Payment Required** code (originally reserved for future use) to signal that a resource is behind a paywall. The response includes a `WWW-Authenticate` header that conveys:\n\n`x402`).\nUpon receiving a 402, the client can:\n\n`Authorization` header.\nBecause the flow stays within HTTP, existing libraries, proxies, and caching layers continue to work unchanged—only the client needs to understand the 402 flow.\n\n| Component | Role | \n|---|---|\n| **Resource Server** | Exposes endpoints that may return 402. Holds a price list and validates payments. | \n| **Payment Processor** | Usually a smart contract on a low‑cost L2 (e.g., Base) that escrowed USDC and emits an event on successful transfer. | \n| **Client (Agent)** | Implements the 402 handshake: reads the challenge, signs/pays, retries with proof. | \n| **Metadata** | The `WWW-Authenticate` header contains a JSON object (`x402` scheme) with fields:`amount` ,`asset` ,`network` ,`paymentPointer` ,`maxTimeout` . | \n\n```\nWWW-Authenticate: x402 amount=\"0.05\", asset=\"USDC\", network=\"base:8453\", paymentPointer=\"pay:0xA1b2.../invoice\"\n```\n\n`Cache-Control: no-store` for paid resources to avoid stale content.\nThese trade‑offs mean x402 is best suited for services where the per‑call cost is low enough to absorb the blockchain overhead, and where agents can tolerate a few seconds of latency for guaranteed payment.\n\nBelow is a self‑contained example that demonstrates:\n\n`/summarize` endpoint with x402.\n**Note**: For brevity, the payment processor is a mock contract that simply records the payer and amount. In production you would deploy a real ERC‑20 escrow contract (e.g., OpenZeppelin’s `ERC20Votes` with a `receive()` fallback) and verify the transaction via an RPC call or a subgraph.\n\n`server.js`)\n\n``` js\n// server.js\nconst express = require('express');\nconst app = express();\nconst PORT = 3000;\n\n// Mock price: $0.05 USDC per call\nconst PRICE_USDC = BigInt('5000000'); // 6 decimals => 0.05 * 1e6\nconst USDC_ADDRESS = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913'; // Base USDC\n\napp.use(express.json());\n\nfunction x402Challenge() {\n  return `x402 amount=\"${Number(PRICE_USDC/1e6)}\", asset=\"USDC\", network=\"base:8453\", paymentPointer=\"pay:${USDC_ADDRESS}/invoice\"`;\n}\n\n// Protect endpoint\napp.get('/summarize', (req, res) => {\n  const auth = req.headers.authorization || '';\n  // Expect proof: \"x402 <txHash>\"\n  if (!auth.startsWith('x402 ')) {\n    return res.status(402)\n              .set('WWW-Authenticate', x402Challenge())\n              .json({error: 'Payment required'});\n  }\n  const txHash = auth.slice(5);\n  // In real code: verify txHash on-chain, confirm amount >= PRICE_USDC, and that sender is allowed.\n  // Here we just accept any hash for demo.\n  res.json({summary: 'This is a dummy summary of the requested content.'});\n});\n\napp.listen(PORT, () => console.log(`Server listening on :${PORT}`));\n```\n\n`agent.js`)\n\n``` js\njavascript\n// agent.js\nconst fetch = require('node-fetch');\nconst { ethers } = require('ethers');\n\n// Configure provider (Base Sepolia testnet for demo)\nconst provider = new ethers.JsonRpcProvider('https://sepolia.base.org');\nconst USDC_ABI = [\n  \"function balanceOf(address) view returns (uint256)\",\n  \"function transfer(address to, uint256 amount) returns (bool)\"\n];\nconst USDC_ADDRESS = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913';\nconst USDC = new ethers.Contract(USDC_ADDRESS, USDC_ABI, provider);\n\n// Wallet funded with USDC on Base Sepolia (replace with your own)\nconst PRIVATE_KEY = '0xYOUR_PRIVATE_KEY';\nconst wallet = new ethers.Wallet(PRIVATE_KEY, provider);\nconst usdcWithSigner = USDC.connect(wallet);\n\nasync function callSummarize(text) {\n  const url = 'http://localhost:3000/summarize';\n  let attempts = 0;\n  while (true) {\n    attempts++;\n    const resp = await fetch(url, {\n      method: 'GET',\n      headers: { 'Content-Type': 'application/json' }\n    });\n    if (resp.ok) {\n      const data = await resp.json();\n      return data.summary;\n    }\n    if (resp.status !== 402) {\n      throw new Error(`Unexpected status ${resp.status}`);\n    }\n    // Parse challenge\n    const wwwAuth = resp.headers.get('www-authenticate') || '';\n    const match = wwwAuth.match(/amount=\"([^\"]+)\"/);\n    if (!match) throw new Error('Malformed 402 challenge');\n    const amountUSDC = parseFloat(match[1]); // e.g., 0.05\n    const amountWei = ethers.parseUnits(amountUSDC.toString(), 6); // USDC has 6 decimals\n\n    // Ensure we have enough balance\n    const bal = await USDC.balanceOf(wallet.address);\n    if (bal < amountWei) {\n      throw new Error(`Insufficient USDC balance: ${ethers.formatUnits(bal,6)} < ${amountUSDC}`);\n    }\n\n    // Send payment (mock: just transfer to a fixed payee)\n    const payee = '0xPayeeAddressHere'; // In real scenario, this is the escrow contract\n    const tx = await usdcWithSigner.transfer(payee, amountWei);\n    await tx.wait(); // wait for inclusion on Base (~2s)\n\n    // Retry with proof\n    const authHeader = `x402 ${tx.hash}`;\n    console.log(`Paid ${amountUSDC} USDC (tx ${tx.hash}), retrying…`);\n    const secondResp = await fetch(url, {\n      method: 'GET',\n      headers: {\n        'Content-Type': 'application/json',\n        'Authorization': authHeader\n      }\n    });\n    if (secondResp.ok) {\n      return (await secondResp.json()).summary;\n    }\n    // If still 402, something went wrong; break to avoid loop\n    throw new Error('Payment not recognized by server');\n  }\n}\n\n// Example usage\n(async () => {\n  try {\n    const summary = await callSummarize('Explain quantum entanglement in two sentences.');\n    console.log('Result:', summary);\n  } catch (e) {\n    console.error('Failed:', e.message);\n  }\n```\n\n", "url": "https://wpnews.pro/news/x402-explained-http-native-micropayments-for-ai-agents-with-real-code", "canonical_source": "https://dev.to/nikhilranka23/x402-explained-http-native-micropayments-for-ai-agents-with-real-code-28d6", "published_at": "2026-09-07 08:17:28+00:00", "updated_at": "2026-09-07 08:27:24.688480+00:00", "lang": "en", "topics": ["artificial-intelligence", "ai-agents", "developer-tools", "ai-infrastructure"], "entities": ["x402", "HTTP", "USDC", "Base", "OpenZeppelin"], "alternates": {"html": "https://wpnews.pro/news/x402-explained-http-native-micropayments-for-ai-agents-with-real-code", "markdown": "https://wpnews.pro/news/x402-explained-http-native-micropayments-for-ai-agents-with-real-code.md", "text": "https://wpnews.pro/news/x402-explained-http-native-micropayments-for-ai-agents-with-real-code.txt", "jsonld": "https://wpnews.pro/news/x402-explained-http-native-micropayments-for-ai-agents-with-real-code.jsonld"}}