← Blog

How an agent pays for a single public-data request

HTTP 402, sign USDC, retry — or a bby_live_ key. The product is the JSON. x402 is how the agent pays for it.

A white robot arm in a workshop
Photo by Alex Knight on Unsplash.

An agent should not open a dashboard to fetch a tweet. It should call a URL, pay if asked, and read JSON. That loop is the only thing this note is about. The product is still public web data. x402 is the rail.

Call a priced path with no payment. The response is 402 Payment Required. The payment-required header is machine-readable: amount, asset (USDC), network (Base first, then Polygon, Arbitrum, Monad, Solana), recipient. The agent signs and retries with X-Payment. Libraries such as @x402/fetch run that loop so your code looks like an ordinary fetch.

Prepaid credits skip the loop. Authorization: Bearer bby_live_… debits a balance minted at /topup. MCP clients do the same on https://mcp.fetcher.sh: paid tools return requirements in _meta unless a key is already on the connection. Free tools — search_endpoints, describe_endpoint, check_balance — do not charge. The envelope is always { status, message, data }.

This is not a primer on trading USDC, and it is not the x402 spec as a crypto essay. For “Twitter without a developer account,” use the Twitter host note. For whether you pay a month or a GET, use pay per call.

A minimal client

Configure @x402/fetch with an ExactEvmScheme for eip155:8453 (Base), then:

fetch('https://twitter.fetcher.sh/api/search?query=hello')

The wrapper handles 402. Or top up and send the Bearer key. Setup for agents is /skill.md. Human docs: /docs.

MCP is the same idea on a different transport. Point the client at https://mcp.fetcher.sh. Paid tools return payment requirements in _meta unless you already put a key on the connection. Free tools search the catalog without charging, so an agent can discover an endpoint before it spends.

A few practical rules save a lot of retries:

  • Do not scrape HTML for a price. Read the 402.
  • Do not store a human’s credit card in the agent. USDC on the advertised networks, or a prepaid key.
  • Do not treat a 402 as an application bug. It is the checkout.
  • Do not send the key to the wrong host naming scheme. twitter.fetcher.sh is the Twitter API; fetcher.sh/api/twitter/… still works as a compatibility path, but discovery documents point at the service origin.

Failed calls still return JSON. That matters more for agents than for humans. An HTML error page is a dead end for a tool-using model. An envelope with status and message is something it can branch on.

When a key is the right answer

Sign-every-call is elegant when the agent already has a wallet and you do not want a long-lived secret in the environment. It is awkward when a cron runs sixty times a day and you would rather debit a balance.

In that case mint a key at /topup, put bby_live_ in the environment, and forget the 402 loop until the balance runs out. Credits do not expire. The key works on every host. Rotation is “mint another, delete the old one,” not “re-apply to a platform.”

MCP connections that already carry the key never see payment requirements on paid tools. Connections that do not will, and the client should be ready to settle or to fail closed. Free discovery tools stay free either way, which is how an agent can look up google_maps_place_search before it spends.

A case: a cron that grounds itself once an hour

A small bot answers “what did the open web say about this repo in the last hour?” It should not hold a Google Cloud key, and it should not keep a human in the loop to paste a SERP.

Each hour it:

1. Calls google.fetcher.sh with site:github.com plus the repo name (operators). 2. Optionally pulls a News pass on google-news.fetcher.sh if the story is a headline, not a repo. 3. Writes a short summary with the rows in context (live grounding).

Payment is either a wallet on the fetcher wrapper, or a bby_live_ key in the environment. The bot never sees a dashboard. If it fails, the error is JSON. If it succeeds, the cost is the GETs.

That is all “an agent pays” means here. Grounding is a different job. OSINT is a different job. The rail is: challenge, sign or debit, JSON.

A case: a chat agent that should not keep a secret

A desktop agent runs on a user’s machine. Putting a shared bby_live_ key in the prompt is a leak waiting to happen. Putting the user’s wallet behind @x402/fetch means each GET is a payment they can see, for an amount the 402 already named.

The agent searches X, fetches a tweet, maybe pulls a YouTube comment thread. Each call is a checkout. The user can refuse. The agent does not accumulate a surprise invoice at the end of the month, because there is no month.

If that same agent later grows into a hosted service with many users, a prepaid key in the server environment is usually cleaner than asking every end user to sign USDC. The rail supports both. Pick the one that matches who is allowed to spend.

Grounding, OSINT, and market research all sit on top of this loop. They are not substitutes for it. If the agent cannot pay, it cannot fetch. If it can pay, the rest of the catalog is just URLs.