# I let AI agents pay my API per call in USDC (x402 on Cloudflare's free plan, zero dependencies)

> Source: <https://dev.to/freetierkits/i-let-ai-agents-pay-my-api-per-call-in-usdc-x402-on-cloudflares-free-plan-zero-dependencies-28d2>
> Published: 2026-10-19 09:07:09+00:00

*Disclosure: this post was written with AI assistance and reviewed before publishing. I sell a starter kit based on this code (link at the end); everything below works without buying it.*

HTTP has had a status code for this since 1997: **402 Payment Required**. With the x402 protocol it finally does something. An AI agent calls your endpoint, gets a 402 with machine-readable payment terms, signs a USDC authorization and retries. Then it gets the data. There's no signup, no API key and no Stripe account.

I wanted to know how little it takes, so I shipped a real one: [freetier-agent-api.pages.dev](https://freetier-agent-api.pages.dev). It's one `_worker.js` on Cloudflare Pages (free plan) with **no npm dependencies**.

`GET /api/apis/search?q=weather` with no payment returns `PAYMENT-REQUIRED` header (x402 v2) and a JSON body (x402 v1, for older clients). Both say: pay 5000 atomic units of USDC (= $0.005) on Base to this address.`transferWithAuthorization` and retries with a `PAYMENT-SIGNATURE` header.`/verify`, runs the handler, then calls `/settle`. The facilitator broadcasts the transfer and pays the gas, and the USDC lands in my wallet.
Coinbase's facilitator needs CDP keys on mainnet. Several public facilitators don't: PayAI (`facilitator.payai.network`) and xpay (` facilitator.xpay.sh`) both settle Base mainnet USDC without auth. I use PayAI and fall back to xpay:

``` js
const FACILITATORS = ['https://facilitator.payai.network', 'https://facilitator.xpay.sh'];
async function fac(op, body) {
  for (const f of FACILITATORS) {
    try {
      const r = await fetch(`${f}/${op}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) });
      const j = await r.json();
      if ('isValid' in j || 'success' in j) return j;
    } catch {}
  }
  return { error: 'no facilitator' };
}
```

Verify, run, settle, in that order. If the handler fails (bad URL, missing parameter), return 400 and **never call settle**, so the agent pays nothing. This matters, because agents retry a lot.

I generated a brand-new empty wallet with `viem`, signed a correct authorization and sent it to the live API. The facilitator answered `invalid_exact_evm_insufficient_balance`. So the signature, EIP-712 domain (` USD Coin`, version `2`, chain 8453), amount and recipient were all accepted, and the only thing missing was money. That's a nice zero-cost end-to-end check.

A paid API nobody can find earns nothing. What worked:

`extensions.bazaar` with input/output JSON schemas)`/openapi.json` with `x-payment-info` on each paid operation, plus `/.well-known/x402`
`POST https://api.x402dash.com/v1/register {"url": ...}` per endpoint. It probes the 402 live`@x402/extensions` handles`/api/apis/search` ($0.001): 2,230 link-checked public and free-tier APIs, with filters like `auth=none&alive=yes`
`/api/free-tiers` ($0.001): current free-tier limits for dev services and LLM APIs`/api/robots-check` ($0.001): may user-agent X crawl this URL?`/api/page-meta` ($0.001): title/OG/headings of a public page (respects robots.txt)
Free: `/api/apis/sample`, `/openapi.json`, `/health`.

If you want the cleaned-up code with tests and the listing steps, it's in the [x402 Pay-Per-Call Starter](https://freetier-kits-shop.fourthwall.com/products/x402-pay-per-call-starter). Or just read the 402 response from the live API and build your own.
