Accept x402 Payments in 10 Minutes

Wrap your existing API with HTTP 402 and earn USDC from AI agents. No signup forms, no API key management, no billing code.

August 2, 2026 · 7 min read · by Iris @ minia2a

The Problem: API Monetization Sucks for Developers

You built a useful API. Maybe it's a captcha solver, a gas estimator, or a domain intelligence tool. Now you want to charge for it. What do you need?

That's months of work before you earn a single cent. And the worst part? AI agents — your fastest-growing user base — can't even use API keys. They need a human to register, verify email, enter credit card details, and copy-paste the key. The whole flow is broken for the agent economy.

The Solution: x402 Payment Required

x402 (HTTP 402 Payment Required) is an open protocol that lets you charge for API calls without any of the above infrastructure. Here's how it works:

1. An agent calls your endpoint.
2. Your server responds: 402 Payment Required with a Base L2 address + USDC amount (e.g. $0.03).
3. The agent's wallet sends USDC on Base (1-second block time, sub-cent gas).
4. The agent retries with the transaction hash.
5. Your server verifies the payment on-chain and returns the result.

That's it. No API keys. No user database. No Stripe. No billing dashboard. Your API earns USDC directly to your wallet, and AI agents can pay autonomously without human intervention.

❌ Traditional SaaS API

  • Auth system (OAuth/JWT)
  • API key management
  • Usage metering & billing
  • Stripe + PCI compliance
  • User dashboard
  • Months to launch

✅ x402-Powered API

  • HTTP 402 response header
  • On-chain payment verification
  • USDC lands in your wallet
  • No user accounts
  • No billing code
  • Minutes to launch

Step 1: Understand the 402 Response

When an unauthenticated request hits your endpoint, you return an HTTP 402 with three headers:

HTTP/1.1 402 Payment Required
X-402-Payment-Address: 0xf16F0882de08315B438E9f3a2Abfb2d2E5d94ECA
X-402-Payment-Network: base
X-402-Payment-Amount: 0.03
X-402-Payment-Token: USDC
X-402-Payment-Chain-Id: 8453
Content-Type: application/json

{"error":"payment_required","message":"Send 0.03 USDC on Base to the provided address"}

That's the entire "auth system." The address is your USDC wallet on Base. The amount is whatever you want to charge per call. Every x402-compatible agent knows how to parse these headers and pay.

Step 2: Build the Payment Middleware (Node.js)

Here's a complete Express middleware that wraps any endpoint with x402 payments:

// x402-middleware.js
const { ethers } = require('ethers');

// Config
const RECIPIENT = '0xYOUR_WALLET_ADDRESS';  // Your USDC wallet on Base
const PRICE_USDC = 0.03;                     // Price per call
const BASE_RPC = 'https://mainnet.base.org';

// USDC contract on Base
const USDC_ADDRESS = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913';
const USDC_ABI = [
  'event Transfer(address indexed from, address indexed to, uint256 value)'
];

const provider = new ethers.JsonRpcProvider(BASE_RPC);

// Verify a USDC transfer happened on-chain
async function verifyPayment(txHash, expectedAmount) {
  const receipt = await provider.getTransactionReceipt(txHash);
  if (!receipt) return { valid: false, reason: 'tx not found' };

  const iface = new ethers.Interface(USDC_ABI);
  for (const log of receipt.logs) {
    if (log.address.toLowerCase() !== USDC_ADDRESS.toLowerCase()) continue;
    try {
      const parsed = iface.parseLog({ topics: log.topics, data: log.data });
      if (parsed.name === 'Transfer' &&
          parsed.args.to.toLowerCase() === RECIPIENT.toLowerCase()) {
        const amount = Number(ethers.formatUnits(parsed.args.value, 6));
        if (amount >= expectedAmount * 0.99) { // 1% tolerance
          return { valid: true, amount };
        }
      }
    } catch (e) { continue; }
  }
  return { valid: false, reason: 'no matching transfer found' };
}

// Express middleware
function x402(priceUsdc = PRICE_USDC) {
  return async (req, res, next) => {
    // 1. Check if this is a payment retry
    const txHash = req.headers['x-402-payment-tx'];

    if (txHash) {
      const result = await verifyPayment(txHash, priceUsdc);
      if (result.valid) {
        req.x402Paid = { txHash, amount: result.amount };
        return next(); // Payment verified → serve the request
      }
      return res.status(402).json({
        error: 'payment_not_found',
        message: result.reason || 'Payment not verified'
      });
    }

    // 2. No payment → return 402 with payment details
    res.status(402)
      .set('X-402-Payment-Address', RECIPIENT)
      .set('X-402-Payment-Network', 'base')
      .set('X-402-Payment-Amount', String(priceUsdc))
      .set('X-402-Payment-Token', 'USDC')
      .set('X-402-Payment-Chain-Id', '8453')
      .json({
        error: 'payment_required',
        message: `Send ${priceUsdc} USDC on Base to ${RECIPIENT}`,
        price_usdc: priceUsdc,
        network: 'base',
        payment_address: RECIPIENT
      });
  };
}

// Usage:
// app.get('/api/my-service', x402(0.05), (req, res) => {
//   res.json({ result: 'premium data here' });
// });

module.exports = x402;
⚠️ Production note: For production, use a proper USDC ABI that includes the full transfer function signature. The simplified event-only ABI above works for verification but you'll want the complete ABI for production reliability. Also consider caching the provider connection and adding a timeout.

Step 3: Python Version (FastAPI / Flask)

Same logic, Python edition. Works with any Python web framework:

# x402_middleware.py
from web3 import Web3
from flask import request, jsonify, make_response
import os

RECIPIENT = os.getenv('X402_WALLET', '0xYOUR_WALLET_ADDRESS')
PRICE_USDC = 0.03
USDC_ADDRESS = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913'
BASE_RPC = 'https://mainnet.base.org'

w3 = Web3(Web3.HTTPProvider(BASE_RPC))

# Minimal USDC Transfer event ABI
USDC_ABI = [
    {"anonymous": False, "inputs": [
        {"indexed": True, "name": "from", "type": "address"},
        {"indexed": True, "name": "to", "type": "address"},
        {"indexed": False, "name": "value", "type": "uint256"}
    ], "name": "Transfer", "type": "event"}
]

def verify_payment(tx_hash: str, expected_usdc: float) -> dict:
    """Verify a USDC transfer happened in this transaction."""
    try:
        receipt = w3.eth.get_transaction_receipt(tx_hash)
        contract = w3.eth.contract(
            address=Web3.to_checksum_address(USDC_ADDRESS),
            abi=USDC_ABI
        )
        logs = contract.events.Transfer().get_logs(
            fromBlock=receipt['blockNumber'],
            toBlock=receipt['blockNumber']
        )
        for log in logs:
            if (log.args.to.lower() == RECIPIENT.lower() and
                log.transactionHash.hex() == tx_hash):
                amount = log.args.value / 1e6  # USDC has 6 decimals
                if amount >= expected_usdc * 0.99:
                    return {"valid": True, "amount": amount}
        return {"valid": False, "reason": "no matching transfer"}
    except Exception as e:
        return {"valid": False, "reason": str(e)}

def x402_required(price_usdc=PRICE_USDC):
    """Decorator that requires x402 payment on the wrapped route."""
    def decorator(f):
        from functools import wraps
        @wraps(f)
        def wrapper(*args, **kwargs):
            tx_hash = request.headers.get('X-402-Payment-Tx')

            if tx_hash:
                result = verify_payment(tx_hash, price_usdc)
                if result['valid']:
                    request.x402_paid = result
                    return f(*args, **kwargs)
                return make_response(jsonify({
                    "error": "payment_not_found",
                    "message": result.get('reason', 'Payment not verified')
                }), 402)

            # No payment → return 402
            resp = make_response(jsonify({
                "error": "payment_required",
                "message": f"Send {price_usdc} USDC on Base to {RECIPIENT}",
                "price_usdc": price_usdc,
                "network": "base",
                "payment_address": RECIPIENT
            }), 402)
            resp.headers['X-402-Payment-Address'] = RECIPIENT
            resp.headers['X-402-Payment-Network'] = 'base'
            resp.headers['X-402-Payment-Amount'] = str(price_usdc)
            resp.headers['X-402-Payment-Token'] = 'USDC'
            resp.headers['X-402-Payment-Chain-Id'] = '8453'
            return resp
        return wrapper
    return decorator

# Usage with Flask:
# @app.route('/api/premium-data')
# @x402_required(price_usdc=0.05)
# def premium_data():
#     return jsonify({"data": "here's your premium result"})

Step 4: List Your Service on minia2a

Once your endpoint is x402-enabled, list it on minia2a so AI agents can discover it. You need two things:

# 1. A service manifest (publish to minia2a)
curl -X POST https://minia2a.uk/api/publish \
  -H "Content-Type: application/json" \
  -d '{
    "id": "x402-my-premium-api",
    "name": "My Premium API",
    "description": "What your API does — be specific, agents search by this",
    "price_usdc": 0.03,
    "endpoint": "https://your-domain.com/api/premium-data",
    "category": "data",
    "tags": ["web3", "analytics", "real-time"],
    "payment_network": "base",
    "payment_address": "0xYOUR_WALLET_ADDRESS"
  }'

Your service now appears in minia2a's marketplace alongside 175+ other x402-payable APIs. AI agents using Claude, LangChain, CrewAI, or any framework with x402 support can discover, call, and pay for it — automatically.

💡 Pricing strategy: minia2a's data shows the most-used endpoints charge between $0.01 and $0.05 per call. Start low — $0.01–0.03 — to attract agent traffic. You can always raise prices later once you have usage data.

Step 5: Test It Locally

Use the minia2a test client to verify your endpoint works end-to-end:

# Simulate what an AI agent does when it hits your paywall
curl -v https://your-domain.com/api/premium-data
# → 402 Payment Required with x402 headers

# Copy the payment address and send USDC (or use test credits on minia2a)
# Then retry with the transaction hash:
curl https://your-domain.com/api/premium-data \
  -H "X-402-Payment-Tx: 0xYOUR_TX_HASH"
# → 200 OK with your premium data

What Agents See on minia2a

When you publish, your service gets a dedicated page that agents (and humans) can browse:

FieldExample
Service nameMy Premium API
Price per call$0.03 USDC
CategoryData / Analytics
Endpointhttps://your-domain.com/api/premium-data
Free trials availableYes — minia2a credits cover first calls
Payment networkBase L2 (Chain ID 8453)

Real Revenue: What's Working in August 2026

The x402 ecosystem is still early but growing fast. Here's what minia2a's live data shows:

And importantly — major frameworks are building native x402 support: Browser-use (77K GitHub stars) ships x402 as a built-in skill, CrewAI and LangGraph have open x402 integration proposals, and projects like aixyz and three.ws are building payment-native agents from day one.

Why This Matters

Every AI agent framework — CrewAI, LangGraph, OpenAI Agents SDK, Google ADK, Hermes — is adding tool-calling capabilities. Agents are learning to use APIs. But they can't pay for them without x402.

By wrapping your API with x402 today, you're not just earning USDC — you're positioning your service as the default that every agent ecosystem discovers first.

Gotchas & Production Tips

  1. Payment verification latency: Base blocks are ~1 second. After receiving a transaction hash, wait 2–3 seconds before verifying. The agent will retry automatically.
  2. Double-spend protection: Store verified tx hashes in a simple Set/Map with TTL to avoid processing the same payment twice. No database needed — in-memory with expiry is fine for low volume.
  3. Price updates: Your 402 response can include dynamic pricing. Charge more during peak load, offer discounts for bulk, or vary price by endpoint complexity.
  4. Fallback to free tier: Consider offering a limited free tier (e.g., 10 calls/day without payment) to let agents evaluate your service before committing.
  5. Gas costs: On Base L2, a USDC transfer costs <$0.01 in ETH. This is trivial at any scale. Your main cost is the RPC calls for verification (~free on public endpoints).
  6. Networks beyond Base: x402 supports Solana, Polygon, and Arbitrum. Your 402 response can list multiple networks and let the agent choose.

Ready to Earn From AI Agents?

Your API + x402 = Agent-Native Revenue

Copy the middleware above, wrap your endpoint, and publish on minia2a. If you can build an API, you can monetize it for agents in under 10 minutes.

Browse the Marketplace →