x402

Pay per request in USDC, over HTTP.
View as MarkdownOpen in Claude

x402 is an open payment protocol that uses the HTTP 402 Payment Required status code to settle payment for a resource inside the request that asks for it. It is maintained by the x402 Foundation, founded by Coinbase and Cloudflare.

The You.com Web Search and Finance Research APIs accept x402. A client with a funded wallet can call either one with no API key and no You.com account.

Web Search costs $0.005 per call and Finance Research $0.11 or $0.50 depending on the effort tier, all matching the standard credit prices. Payments settle on-chain and do not draw down your credit balance. MPP costs twice as much for Web Search and the same for Finance Research. See Pricing.


How It Works

  1. The client makes a normal request. No X-API-Key, no payment header.
  2. You.com responds 402 Payment Required. The response carries a base64-encoded PaymentRequired object in the PAYMENT-REQUIRED header. It lists one set of acceptable terms per network in accepts.
  3. The client picks a set of terms matching a network and asset it can pay on.
  4. The client signs a payment authorization. For EVM networks this is an EIP-3009 transferWithAuthorization signed with EIP-712. The client signs but does not broadcast, so settlement is gasless from the client’s perspective.
  5. The client retries the same request with the authorization in the PAYMENT-SIGNATURE header.
  6. You.com verifies, runs the request, and settles. Verification and settlement go through a facilitator, which submits the transfer on-chain and pays gas.
  7. You.com responds 200 OK with the results and a PAYMENT-RESPONSE header containing the settlement result.

Total added latency is one extra round trip plus settlement, typically a few hundred milliseconds on Base.

Headers

HeaderDirectionContents
PAYMENT-REQUIREDYou.com → clientBase64-encoded PaymentRequired object
PAYMENT-SIGNATUREClient → You.comBase64-encoded PaymentPayload object
PAYMENT-RESPONSEYou.com → clientBase64-encoded SettlementResponse object

These are the x402 V2 header names. The older V1 X-PAYMENT header is not supported.


Supported Endpoints

EndpointPrice per callAtomic units (USDC, 6 decimals)
GET /v1/search$0.0055000
GET /v1/search with livecrawl$0.005 + $0.001 per result5000 + 1000 × count
POST /v1/finance_research (deep)$0.11110000
POST /v1/finance_research (exhaustive)$0.50500000

The HTTP method differs per endpoint, and the wrong one returns 401 with no payment terms rather than a helpful error. Web Search offers payment on GET only, and Finance Research on POST only. POST /v1/search and GET /v1/finance_research both return 401.

Both prices match the key-authenticated rate for the same call, so machine payments are not a surcharge. The Contents and Research APIs return 401 on every method and do not offer payment terms.

Query parameters and the response body are the same as the key-authenticated GET endpoint, including query, count, freshness, country, language, and the domain filters. See the Web Search API reference for the full list.

Result count is count, not num_results. An unrecognized parameter is ignored rather than rejected, so num_results=2 silently returns the default 10 results instead of erroring.

livecrawl is supported and priced into the quote. Adding it raises the amount in accepts by $0.001 per result, on top of the $0.005 base call:

RequestQuoted amountAtomic units
?query=...&count=10$0.0055000
?query=...&count=10&livecrawl=web$0.01515000
?query=...&count=50&livecrawl=web$0.05555000

count sets how many pages are charged for. The crawl mode does not change the price, so livecrawl=all costs the same as livecrawl=web at the same count.

If you are comparing costs against a key-authenticated integration, machine payments charge per count regardless of crawl mode, where credit billing charges per page fetched. At count=10 with livecrawl=all that is 10 pages here and 20 there. Budget from the amount in accepts, which is what you actually pay on this path.

Read the price off accepts rather than computing it. Because the amount scales with count, terms fetched for one request are not valid for a request with a different count or a different livecrawl setting. Sign against the 402 you were handed for the exact request you intend to send.

Finance Research

Finance Research takes a JSON body on POST, so there is no query-string form. The financial question goes in input, and research_effort selects the tier:

$curl -X POST https://api.you.com/v1/finance_research \
> -H "Content-Type: application/json" \
> -d '{"input": "NVDA Q2 guidance vs consensus", "research_effort": "deep"}'

The price is fixed per tier rather than scaling with the request, and deep is the default when research_effort is omitted. See the Finance Research API reference for the response shape.

Send deep or exhaustive and nothing else. Those are the only values the Finance Research API reference accepts, and it returns 422 for anything else. The 402 is issued before the body is validated, so it will quote a price for an unsupported tier rather than refusing it. Paying against that quote risks spending on a request the endpoint will reject.

Latency is the other thing to plan for. A deep call takes under 120 seconds and exhaustive under 300, well beyond a typical HTTP client default, so raise your timeout before the payment round trip rather than after.


Networks and Assets

NetworkCAIP-2 identifierAssetAsset address
Baseeip155:8453USDC0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
Solanasolana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpUSDCEPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v

Solana terms include an extra.feePayer address. Use the value from the accepts entry you selected rather than caching one, because it changes between challenges.

There is no testnet. Both networks are mainnet, so your first successful call spends real funds. Start with a wallet holding only what you intend to spend while you get the handshake working.

Additional networks are on the roadmap. Read the accepts array from the 402 response rather than hardcoding a network, so your client keeps working as we add them.


The 402 Response

402 Payment Required
1{
2 "x402Version": 2,
3 "error": "Payment required",
4 "resource": {
5 "url": "https://api.you.com/v1/search",
6 "description": "You.com Search API: real-time web search that returns ranked results (url, title, snippets) plus an optional AI-generated answer.",
7 "mimeType": "application/json"
8 },
9 "accepts": [
10 {
11 "scheme": "exact",
12 "network": "eip155:8453",
13 "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
14 "amount": "5000",
15 "payTo": "0x...",
16 "maxTimeoutSeconds": 600,
17 "extra": {
18 "name": "USD Coin",
19 "version": "2"
20 }
21 },
22 {
23 "scheme": "exact",
24 "network": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
25 "asset": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
26 "amount": "5000",
27 "payTo": "...",
28 "maxTimeoutSeconds": 600,
29 "extra": {
30 "feePayer": "..."
31 }
32 }
33 ]
34}
FieldMeaning
x402VersionProtocol version. Always 2.
resourceWhat is being paid for, as a URL, description, and MIME type. Sent once, not per entry.
schemeHow payment is formed. exact means pay exactly amount.
networkCAIP-2 network identifier.
assetContract or mint address of the accepted token.
amountPrice in the asset’s atomic units. USDC has 6 decimals, so 5000 is $0.005.
payToThe You.com receiving address for this network. Read it from the response, never from these docs.
maxTimeoutSecondsHow long the terms stay valid. Currently 600, so 10 minutes to sign and retry.
extraScheme-specific data. Token name and version for EIP-3009, or feePayer on Solana.

The response also carries an extensions.bazaar block, which is an x402 discovery listing describing the endpoint’s inputs and outputs for agents that browse the bazaar. You can ignore it when paying directly.

The payTo and feePayer values above are illustrative. We deliberately do not publish our receiving addresses here, because the live 402 response is the only source that stays correct as we rotate keys, add networks, or change facilitators. Take payTo, asset, network, and amount from the accepts entry you selected, and sign against those values. A client that hardcodes an address from documentation will keep paying the wrong one after a rotation.


Making a Paid Request

The x402 SDKs wrap fetch and handle the 402 retry, so your application code makes one call.

$npm install @x402/fetch @x402/evm
1import { wrapFetchWithPayment } from "@x402/fetch";
2import { x402Client } from "@x402/core/client";
3import { ExactEvmScheme } from "@x402/evm/exact/client";
4import { privateKeyToAccount } from "viem/accounts";
5
6const signer = privateKeyToAccount(process.env.EVM_PRIVATE_KEY as `0x${string}`);
7
8const client = new x402Client();
9client.register("eip155:*", new ExactEvmScheme(signer));
10
11const fetchWithPayment = wrapFetchWithPayment(fetch, client);
12
13const params = new URLSearchParams({
14 query: "best practices for scaling microservices in production",
15 count: "10",
16});
17
18const response = await fetchWithPayment(`https://api.you.com/v1/search?${params}`);
19
20const data = await response.json();
21console.log(data.results.web.map((r) => r.url));

Official clients also exist for Go, Rust, and Java, plus an Axios wrapper and an MCP transport. See the x402 documentation for the current list.

Set a per-request spend ceiling in your client. The SDKs check amount against a limit you configure before signing, which protects you if terms change unexpectedly.


Receipts

On success, the PAYMENT-RESPONSE header contains a base64-encoded settlement result:

1{
2 "success": true,
3 "transaction": "0x9f2c...c41a",
4 "network": "eip155:8453",
5 "payer": "0x857b06519E91e3A54538791bDbb0E22373e36b66"
6}

The transaction hash is your record of payment. There is no invoice and no line item in your credit history, because there is no account. Log the hash alongside your request if you need an audit trail.


Limits and Safeguards

Replay protection. Each authorization carries a unique nonce and is valid for exactly one request. A replayed PAYMENT-SIGNATURE is rejected.

Expiry. Terms expire after maxTimeoutSeconds, currently 600 seconds. If your client takes longer to sign and retry, request fresh terms rather than reusing the old ones.

Rate limits. Challenge issuance is capped at 10 per minute per caller. An 11th unpaid request inside the same minute returns 429 with a Retry-After header instead of a fresh 402, so cache the terms you are handed rather than re-requesting them per retry. This limit applies to the unpaid first leg. Keyless requests cannot inherit an organization’s custom QPS limit, so if you need sustained concurrency, contact sales about an enterprise agreement.

No chargebacks. Stablecoin transfers are final once settled, and there is no testnet to rehearse on.


Data Retention

Zero Data Retention is not available on x402 requests.

ZDR is an account-level configuration. It is added to an enterprise agreement and enforced against a specific organization’s API keys. An x402 request presents no API key and no account, so there is no agreement to attach ZDR to and no identity to enforce it against. Keyless requests fall outside ZDR and are handled under You.com’s general terms.

Two consequences to plan around:

  • There is no account-scoped deletion path. Deletion and data subject requests are handled per organization. An x402 request has no organization, so there is no established route to scope such a request to your traffic.
  • Routing end-user queries through this path is a decision you own. If you have a retention, residency, or compliance commitment to your own users, send those queries with an API key on an enterprise agreement that has ZDR enabled.

If ZDR is a requirement, use API key authentication and ask your account team about adding ZDR to your agreement. The index and the results are identical either way, so this is a change of credential rather than a change of product.


Errors

StatusConditionWhat to do
402No PAYMENT-SIGNATURE headerExpected on the first call. Read accepts and retry with payment.
402Payment header present but not validA malformed, expired, or unverifiable payment re-issues fresh terms rather than returning a distinct status. Decode the new 402, check your signature against the accepts entry you selected, and retry.
401Right endpoint, wrong verbWeb Search offers payment on GET, Finance Research on POST. Switch the method rather than the endpoint.
401Invalid X-API-Key sentThe key path and the payment path are separate. Send a payment header and no key, or a valid key and no payment header.
429More than 10 unpaid challenge requests in a minuteHonor Retry-After. Reuse the terms you already hold instead of re-requesting a 402 per attempt.
5xxSettlement or upstream failureRetry with backoff using fresh terms. See the troubleshooting note below.

Troubleshooting

I sent PAYMENT-SIGNATURE and still got a 402. Decode the error field in the new response body. The most common causes are signing against stale terms after the 600-second window, and signing for the wrong asset or network when multiple options are offered.

My wallet has USDC but verification fails. Confirm the balance is on the network in the terms you selected. USDC on Ethereum mainnet cannot satisfy an eip155:8453 requirement, and USDC on Base cannot satisfy the Solana entry.

I am getting 401 instead of 402. Check the verb before anything else. Web Search offers payment terms on GET /v1/search and Finance Research on POST /v1/finance_research. The inverse of either returns 401 with no hint that the method is the problem. The Contents and Research APIs return 401 on every method, since they do not accept machine payments at all.

Payment settled but the request returned a 5xx. Each authorization is valid for exactly one request, so a retry needs fresh terms and settles a second payment. Keep the PAYMENT-RESPONSE header from the failed call and contact support with the settlement details rather than absorbing the double charge.

Can I use an API key and x402 on the same endpoint? Yes, on the same route, but not in the same request. Requests are routed by what they present. Send X-API-Key and the call bills to your credit balance. Send PAYMENT-SIGNATURE and it settles on-chain.

Which protocol version do you support? x402 V2. The V1 X-PAYMENT header is not accepted.



Questions & Support

For x402 questions, reach us in Discord or contact [email protected].