Skip to content
← All articles
commerceAdvanced12 min readLast updated: Apr 30, 2026

x402: Agent Payment Flow Over HTTP 402

Use Coinbase's x402 spec to let agents pay your API in USDC. Express middleware example, AIDE's commerce-x402 and x402-pass checks.

  • #x402
  • #agentic-commerce
  • #payments
  • #usdc
  • #advanced

x402 turns HTTP 402 Payment Required — reserved but unused since 1997 — into a live protocol Coinbase shipped in 2025. When an agent calls your API, it can pay in USDC instantly, with no card or invoice. AIDE's commerce-x402 and x402-pass checks verify your stack is wired correctly.

What AIDE actually checks

commerce-x402 validates three things:

  1. Does an unauthenticated request to a protected endpoint return 402?
  2. Does the 402 response include WWW-Authenticate: x402?
  3. Is there a valid x402 paywall body (scheme: exact, network, maxAmountRequired, payTo, asset)?

x402-pass additionally probes the end-to-end payment flow — facilitator + settlement.

Why x402?

Traditional API monetization (Stripe + API key) is awkward for agents:

  • Issuing API keys requires human oversight
  • Invoice cycles run 30 days; agents act in seconds
  • Sharing card numbers is a risk surface for an agent

x402 collapses this: an agent receiving a 402 pays USDC from its wallet (seconds, on-chain) and replays the request. Micropayments under one cent are economically viable.

Minimum server

Express + x402-express middleware is the shortest path:

// server.js
import express from "express"
import { x402Middleware } from "x402-express"

const app = express()

app.use(
  "/api/scan",
  x402Middleware({
    network: "base",
    payTo: "0xYourReceiverAddress",
    asset: {
      address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",  // USDC on Base
      decimals: 6,
      symbol: "USDC"
    },
    pricing: {
      "/api/scan": "0.05"  // 5 cents per scan
    },
    facilitator: "https://x402.org/facilitator"
  })
)

app.post("/api/scan", async (req, res) => {
  // If we got here, payment is verified — run the real scan
  const result = await runScan(req.body.url)
  res.json(result)
})

app.listen(3000)

The middleware:

  1. Looks for Authorization: x402 ... on each request.
  2. If missing or invalid, returns 402 + paywall payload.
  3. If present, asks the facilitator to verify the signature.
  4. Once settled, hands the request to your handler.

Anatomy of the 402 response

HTTP/1.1 402 Payment Required
WWW-Authenticate: x402
Content-Type: application/json

{
  "x402Version": 1,
  "accepts": [{
    "scheme": "exact",
    "network": "base",
    "maxAmountRequired": "50000",
    "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
    "payTo": "0xYourReceiverAddress",
    "resource": "/api/scan",
    "description": "AIDE site scan, 0.05 USDC per result",
    "mimeType": "application/json",
    "maxTimeoutSeconds": 60
  }],
  "error": "X-PAYMENT header is required"
}

Key fields:

| Field | Meaning | AIDE impact | |---|---|---| | scheme: exact | Exact-amount payment; tipping/subscription variants aren't standardized yet | Other schemes are out of spec | | network | Which chain (base, base-sepolia, polygon) | Non-mainnet → AIDE WARNING; testnet payments aren't "real" | | maxAmountRequired | Cap, in atomic units (6 decimals for USDC) | Excessive (>$1) → WARNING | | payTo | Receiver wallet | Zero-address or non-contract → FAIL | | maxTimeoutSeconds | Signature TTL | <30 s — agents can't react in time |

Second request: signed payment

The agent receives the 402, mints an EIP-3009 signature via the facilitator, and replays the call:

POST /api/scan HTTP/1.1
Authorization: x402 eyJ4NDAyVmVyc2lvbiI6MSwic2NoZW1lIjoiZXhhY3QiLCJuZXR3b3JrIjoiYmFzZSIsInBheWxvYWQiOiJ7XCJzaWduYXR1cmVcIjoiMHguLi4ifSJ9

{"url": "https://stripe.com"}

Authorization: x402 <base64> payload contains a signed transferWithAuthorization call. The server pings the facilitator:

const verification = await fetch("https://x402.org/facilitator/verify", {
  method: "POST",
  headers: {"Content-Type": "application/json"},
  body: JSON.stringify({ paymentPayload, paymentRequirements })
})

isValid: true triggers settlement, then your /api/scan handler runs.

Common mistakes

| Mistake | Symptom | Fix | |---|---|---| | Protected endpoint still returns 200 | Middleware not on the route | Order matters — app.use(x402Middleware) must come before the handler | | Facilitator verify always fails | Network mismatch (testnet vs mainnet) | Manifest says network: "base" but facilitator URL might be on base-sepolia; align them | | 402 response blocked by CORS | Browser-based agents can't reach you | Add Access-Control-Expose-Headers: WWW-Authenticate | | maxAmountRequired too low | Gas cost > payment | On Base mainnet anything under 0.001 USDC isn't economic; minimum 0.01 |

Testing — what AIDE does

Manual probe with curl:

# 1. Unauthenticated call — should return 402
curl -i https://api.your-site.com/api/scan \
  -H 'Content-Type: application/json' \
  -d '{"url":"https://example.com"}'

Expected:

HTTP/1.1 402 Payment Required
WWW-Authenticate: x402

If not present: commerce-x402 FAIL. Then:

# 2. Trigger a full AIDE scan
curl -X POST https://api.aide.tr/v1/scans \
  -H 'Content-Type: application/json' \
  -d '{"url":"https://your-site.com","profile":"ai_ready"}'

commerce-x402 should be PASS. x402-pass may stay WARNING (E2E payment isn't tested by default).

Production hardening

  • Replay protection: Each signature has a nonce — never accept the same nonce twice. The facilitator doesn't track this for you; keep a seen_nonces table in your DB.
  • No refunds: x402 has no protocol-level refund. If your handler fails after settlement, the content wasn't delivered and the agent retries. Design your handler to be idempotent.
  • Dynamic pricing: You can charge per-agent. The middleware supports a priceModifier callback.
  • Audit log: Persist every successful settlement to ClickHouse/Postgres — for tax reporting you'll need tx hash and amount.

Related resources

1284 subscribers

Weekly AI-Readiness newsletter

New articles, industry trends, check updates — one email a week.

Sitenizde deneyin

Tek bir tıklamayla bu kontrolü çalıştırın.

Which check do you want?
x402: Agent Payment Flow Over HTTP 402 | AIDE