# Paying with x402 (/docs/x402)

[x402](https://x402.org) is an open standard for paying for a web request. The server
answers `402 Payment Required` with what to pay; the client signs a USDC payment with
its wallet and sends the request again with it. quarry uses x402 version 2 and
charges in USDC on Base.

This is for agents that hold their own wallet, with no quarry account. It doesn't apply
to free datasets, which answer without payment, or to datasets that only sell monthly
subscriptions (their [contract](/docs/api) has `"payment": null`), which can't be paid
this way: see [Subscriptions and API keys](/docs/subscriptions). To give an assistant
such as Claude Code or Codex a wallet without writing code, see
[Give your assistant a wallet](/docs/wallet).

## Over HTTP [#over-http]

1. Send `POST /{username}/{slug}` with a JSON body, `{ "query": "...", "top_k": 5 }`,
   and no payment.
2. quarry answers `402`. The `PAYMENT-REQUIRED` header holds the requirements as
   base64 JSON: an `accepts` list with the scheme (`exact`), network, USDC contract,
   `amount` in USDC's smallest unit, and `payTo`, the seller's payout wallet.
3. Sign a payment for one of the `accepts` entries and send the same request again,
   with the signed payment, base64-encoded, in the `PAYMENT-SIGNATURE` header.
4. You get the passages. The `PAYMENT-RESPONSE` header, base64 JSON, holds the
   receipt: `success`, `transaction` (the transaction hash), `network`, and `payer`.

Only x402 version 2 is accepted: a version 1 `X-PAYMENT` header gets another `402`.

The x402 client libraries handle steps 2 to 4. Install them with
`npm install @x402/fetch @x402/evm viem`, and run this as an ES module (for example
`node agent.mjs`):

```js
import { decodePaymentResponseHeader, wrapFetchWithPayment, x402Client } from "@x402/fetch";
import { registerExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";

const endpointUrl = "https://quarry.market/alice/market-outlook";

const client = new x402Client();
registerExactEvmScheme(client, { signer: privateKeyToAccount(process.env.AGENT_PRIVATE_KEY) });
const fetchWithPayment = wrapFetchWithPayment(fetch, client);

const res = await fetchWithPayment(endpointUrl, {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({ query: "Which segment grew fastest?", top_k: 5 }),
});
if (res.status === 402) {
  // Refused: the reason is in PAYMENT-RESPONSE (settlement) or PAYMENT-REQUIRED (verification).
  const header = res.headers.get("PAYMENT-RESPONSE") ?? res.headers.get("PAYMENT-REQUIRED");
  const info = JSON.parse(Buffer.from(header, "base64").toString());
  console.log("Not paid:", info.errorReason ?? info.error);
} else {
  console.log(res.status, await res.json());
  const receipt = res.headers.get("PAYMENT-RESPONSE");
  if (receipt) console.log(decodePaymentResponseHeader(receipt).transaction);
}
```

`endpointUrl` is the dataset's `request.url` from its [contract](/docs/api), and
`AGENT_PRIVATE_KEY` the private key of a wallet holding USDC on the right network. The
wallet needs no ETH: the facilitator pays the network fee. The client refuses to sign
more than $1 per payment by default, and `fetchWithPayment` throws when it can't sign;
raise the cap with `client.setSpendControls({ maxAmountPerPayment: "$5" })`.

The answer is described in [Ask over HTTP](/docs/api/query#response).

## Inside MCP [#inside-mcp]

The same payment works inside a tool call: `ask` returns the `PaymentRequired` object,
and you call it again with the signed payment in `_meta["x402/payment"]`. See
[Pay per question inside MCP](/docs/mcp#pay-per-question-inside-mcp).

## Try it [#try-it]

`GET https://quarry.market/api/x402/demo` charges 0.001 USDC and answers
`{ "message": "Hello, paying agent.", "timestamp": "…" }`. Use it to check a wallet
setup before paying for a dataset. With the client above:
`await fetchWithPayment("https://quarry.market/api/x402/demo")`.

## Networks [#networks]

| Network      | Identifier in `accepts` | USDC                                                               |
| ------------ | ----------------------- | ------------------------------------------------------------------ |
| Base         | `eip155:8453`           | Real USDC                                                          |
| Base Sepolia | `eip155:84532`          | Test USDC, free from [Circle's faucet](https://faucet.circle.com/) |

quarry currently runs on Base. The dataset contract's `payment.network` and
`payment.caip2` say the same. Sign on that network: a payment for another network is
refused.

## When you're charged [#when-youre-charged]

* quarry checks the payment, runs the search, and only then settles the payment
  on-chain, before sending the passages. A failed search is never charged, and the
  signed payment stays unspent, so you can send it again.
* A request with an invalid body is refused with `400` and isn't charged. Without a
  payment, though, you get the `402` first, since the body is only read once a payment
  is attached.
* If settlement itself fails, you get a `402` whose `PAYMENT-RESPONSE` has
  `"success": false`, and nothing is charged.
* Send one request at a time with a given signed payment. A second request using it
  while the first is running gets `409 PAYMENT_IN_FLIGHT`.
* When the relevance check finds no passage that answers the question, you get
  `404 NO_MATCH` and nothing settles:
  the same signed payment can be sent again with another question to the dataset.
  Passages that answer only part of the question are charged: see
  [How paying works](/docs/paying#what-you-pay-for).
* A wallet over its limit of paid questions gets `429 RATE_LIMITED` once its payment
  is checked, and nothing settles: send the same signed payment again after
  `Retry-After`.

Rate limits are in [Limits](/docs/limits), and every error in
[Error codes](/docs/api/errors).

## Facilitator and Bazaar [#facilitator-and-bazaar]

quarry verifies and settles payments through Coinbase's x402 facilitator. Your agent
only talks to quarry. Priced datasets also carry x402 Bazaar discovery metadata, which
Coinbase's x402 Bazaar uses to list them. To
search quarry's own catalog, use the [MCP server](/docs/mcp).
