> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polygon.technology/llms.txt
> Use this file to discover all available pages before exploring further.

# x402 Quickstart for Buyers

> Tutorial: set up an x402 buyer client on Polygon to automatically pay for and access paywalled API endpoints.

This tutorial walks through setting up an x402 buyer client on Polygon. By the
end, your client will automatically detect 402 Payment Required responses,
pay in USDC, and retrieve the unlocked resource.

<Warning title="Security notice">
  This tutorial uses test credentials and local endpoints for clarity.
  In production, never expose private keys or facilitator URLs publicly.
</Warning>

## Prerequisites

| Requirement     | Example / Notes                                                                  |
| --------------- | -------------------------------------------------------------------------------- |
| Wallet          | Metamask, Rabby, or any Polygon-compatible wallet with USDC                      |
| JS env          | Node.js 18+ with npm or something of better quality, like [Bun](https://bun.sh/) |
| Polygon testnet | Amoy RPC                                                                         |
| .env            | Must include PRIVATE\_KEY, .KEY; optional FACILITATOR\_URL, RESOURCE\_URL        |

## Install dependencies

Install one of the official HTTP clients:

> Wherever `bun` is used, replace it with `npm` or your preferred package manager.

```bash theme={null}
bun install x402-fetch
# or
bun install x402-axios
```

We will use x402-fetch in this tutorial.

Then install viem + dotenv:

```bash theme={null}
bun install viem dotenv
```

## Create a wallet client

Set up a Polygon wallet using [viem](https://viem.sh/).

This wallet signs and sends the USDC payment when a 402 challenge is detected.

```ts theme={null}
import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { polygonAmoy } from "viem/chains";
import "dotenv/config";

const privateKey = process.env.PRIVATE_KEY;
if (!privateKey) throw new Error("PRIVATE_KEY not set in .env");

const account = privateKeyToAccount(`0x${privateKey}`);
const client = createWalletClient({
  account,
  chain: polygonAmoy,
  transport: http(),
});

console.log("Wallet address:", account.address);
```

Expected output:

```bash theme={null}
Wallet address: 0x1234abcd...
```

## Make paid requests automatically

Use x402-fetch or x402-axios to intercept 402 responses and complete the payment
automatically.

```ts theme={null}
import { wrapFetchWithPayment, decodeXPaymentResponse } from "x402-fetch";
import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { polygonAmoy } from "viem/chains";
import "dotenv/config";

const account = privateKeyToAccount(`0x${process.env.PRIVATE_KEY}`);
const client = createWalletClient({ account, chain: polygonAmoy, transport: http() });
const fetchWithPayment = wrapFetchWithPayment(fetch, client);

const FACILITATOR_URL = process.env.FACILITATOR_URL || "https://x402-amoy.polygon.technology";
const RESOURCE_URL = process.env.RESOURCE_URL || "http://127.0.0.1:4021/weather";

(async () => {
  const response = await fetchWithPayment(RESOURCE_URL, { method: "GET" });
  const body = await response.json();
  console.log("Response body:", body);

  if (body.report) {
    const rawPaymentResponse = response.headers.get("x-payment-response");
    console.log("Raw payment header:", rawPaymentResponse);
    const decoded = decodeXPaymentResponse(rawPaymentResponse);
    console.log("Decoded payment:", decoded);
  }
})();
```

The client:

* Sends the request
* Receives 402 Payment Required
* Pays in USDC via facilitator
* Retries automatically
* Returns the unlocked JSON data

## Reference

Configuration, error codes, and guardrails.

### Schema

| name             | type   | required | example                                   | description            |
| ---------------- | ------ | -------- | ----------------------------------------- | ---------------------- |
| PRIVATE\_KEY     | string | ✅        | `"abcd1..."`                              | Wallet key for Polygon |
| FACILITATOR\_URL | string | optional | `"https://x402-amoy.polygon.technology"`  | Payment relay endpoint |
| RESOURCE\_URL    | string | ✅        | `"https://api.example.com/paid-endpoint"` | Target API URL         |
| USDC             | token  | implied  | USDC on Polygon                           | Payment asset          |

### Errors

Common failure modes and fixes:

| code / case          | meaning                     | fix                                         |
| -------------------- | --------------------------- | ------------------------------------------- |
| MISSING\_CONFIG      | Wallet or URL not set       | Verify .env keys                            |
| DUPLICATE\_PAYMENT   | Payment replay detected     | Retry with new request ID                   |
| BAD\_PAYMENT\_HEADER | Invalid signature or amount | Ensure client and facilitator are in sync   |
| 402\_LOOP            | API keeps returning 402     | Check facilitator health or endpoint config |

### Do / Don't Do Guardrails

| ✅ Do                                     | ❌ Don't                               |
| ---------------------------------------- | ------------------------------------- |
| Use a sandbox facilitator for testing    | Hardcode private keys in your scripts |
| Log decoded payment responses            | Parse payment headers manually        |
| Use `wrapFetchWithPayment` or x402-axios | Re-implement 402 logic yourself       |

### References

* [x402-fetch npm docs](https://www.npmjs.com/package/x402-fetch)
* [x402-axios npm docs](https://www.npmjs.com/package/x402-axios)
* [x402 Developer Docs](https://x402.dev)
