> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/cloudflare/agents/llms.txt
> Use this file to discover all available pages before exploring further.

# x402 HTTP Payments Example

> HTTP payment gating using the x402 protocol with Hono middleware and automatic payment signing

HTTP payment gating using the [x402 protocol](https://x402.org) with Hono middleware. A `/protected-route` requires a \$0.10 payment on Base Sepolia - an Agent with a test wallet pays automatically.

## What it demonstrates

* **`@x402/hono` middleware** - `paymentMiddleware()` gates any Hono route behind a price
* **`@x402/fetch`** - `wrapFetchWithPayment(fetch)` wraps `fetch` so the agent signs and pays automatically
* **`@x402/evm`** - EVM scheme registration for both client and server
* **`@callable`** - the agent exposes `fetchProtectedRoute` as a callable method
* **`useAgent` + `agent.call()`** - the React frontend triggers the paid fetch via WebSocket RPC

## Architecture

```
┌─────────────┐
│   Client    │
│  (Browser)  │
└──────┬──────┘
       │ agent.call("fetchProtectedRoute")
       │
       v
┌─────────────────────────────────────┐
│         PayAgent (DO)               │
│  - Has private key                  │
│  - Signs payment                    │
│  - Makes HTTP request               │
└──────┬──────────────────────────────┘
       │ fetch("/protected-route")
       │ + x402 payment header
       │
       v
┌─────────────────────────────────────┐
│   Protected Route (Hono)            │
│  - Verifies payment                 │
│  - Returns content if paid          │
└─────────────────────────────────────┘
```

## Server Implementation

### Gating a Route

```typescript src/server.ts theme={null}
import { Hono } from "hono";
import { paymentMiddleware, x402ResourceServer } from "@x402/hono";
import { HTTPFacilitatorClient } from "@x402/core/server";
import { registerExactEvmScheme } from "@x402/evm/exact/server";

const app = new Hono<{ Bindings: Env }>();

const facilitatorClient = new HTTPFacilitatorClient({
  url: "https://x402.org/facilitator"
});
const resourceServer = new x402ResourceServer(facilitatorClient);
registerExactEvmScheme(resourceServer);

app.use(
  paymentMiddleware(
    {
      "GET /protected-route": {
        accepts: [
          {
            scheme: "exact",
            price: "$0.10",
            network: "eip155:84532",  // Base Sepolia testnet
            payTo: process.env.SERVER_ADDRESS as `0x${string}`
          }
        ],
        description: "Access to premium content",
        mimeType: "application/json"
      }
    },
    resourceServer
  )
);

app.get("/protected-route", (c) => {
  return c.json({
    message: "This content is behind a paywall. Thanks for paying!"
  });
});

export default app;
```

### Agent That Pays

```typescript src/server.ts theme={null}
import { Agent, callable } from "agents";
import { wrapFetchWithPayment } from "@x402/fetch";
import { x402Client } from "@x402/core/client";
import { registerExactEvmScheme } from "@x402/evm/exact/client";
import { toClientEvmSigner } from "@x402/evm";
import { privateKeyToAccount } from "viem/accounts";

export class PayAgent extends Agent<Env> {
  fetchWithPay?: ReturnType<typeof wrapFetchWithPayment>;

  onStart() {
    const pk = process.env.CLIENT_TEST_PK;
    if (!pk) {
      console.warn("CLIENT_TEST_PK not set");
      return;
    }

    const account = privateKeyToAccount(pk as `0x${string}`);
    console.log("Agent will pay from:", account.address);

    const client = new x402Client();
    registerExactEvmScheme(client, { signer: toClientEvmSigner(account) });
    this.fetchWithPay = wrapFetchWithPayment(fetch, client);
  }

  @callable()
  async fetchProtectedRoute() {
    if (!this.fetchWithPay) {
      return {
        text: "Agent not ready - CLIENT_TEST_PK not configured",
        isError: true
      };
    }

    const paidUrl = "http://localhost:5173/protected-route";
    const res = await this.fetchWithPay(paidUrl, {});
    const data = await res.json();

    return {
      text: JSON.stringify(data, null, 2),
      isError: !res.ok
    };
  }
}
```

## How It Works

<Steps>
  <Step title="Server defines price">
    The `paymentMiddleware` configures which routes require payment and at what price:

    ```typescript theme={null}
    "GET /protected-route": {
      accepts: [{
        scheme: "exact",
        price: "$0.10",
        network: "eip155:84532",
        payTo: "0x..."
      }]
    }
    ```
  </Step>

  <Step title="Client makes request">
    The client calls the agent's `fetchProtectedRoute` method:

    ```typescript theme={null}
    const result = await agent.call("fetchProtectedRoute", []);
    ```
  </Step>

  <Step title="Agent discovers price">
    When `fetchWithPay` makes a request, it receives a `402 Payment Required` response with payment options.
  </Step>

  <Step title="Agent signs payment">
    The agent automatically:

    * Selects a payment method (EVM on Base Sepolia)
    * Signs a payment transaction with its private key
    * Retries the request with payment headers
  </Step>

  <Step title="Server verifies and serves">
    The middleware verifies the payment signature and on-chain transaction, then serves the content.
  </Step>
</Steps>

## Environment Setup

Copy `.env.example` to `.env`:

```bash theme={null}
cp .env.example .env
```

Fill in the required variables:

```bash .env theme={null}
# Address to receive payments (Base Sepolia testnet)
SERVER_ADDRESS=0x...

# Private key for signing payments (test key only!)
# Get test funds from https://faucet.circle.com/
CLIENT_TEST_PK=0x...
```

<Note>
  **Never commit real private keys!** Use test keys only and get testnet funds from the [Circle faucet](https://faucet.circle.com/).
</Note>

## Running the Example

<Steps>
  <Step title="Install dependencies">
    ```bash theme={null}
    npm install
    ```
  </Step>

  <Step title="Configure environment">
    ```bash theme={null}
    cp .env.example .env
    # Edit .env with your addresses
    ```
  </Step>

  <Step title="Start the server">
    ```bash theme={null}
    npm start
    ```
  </Step>

  <Step title="Trigger payment">
    Open [http://localhost:5173](http://localhost:5173) and click **"Fetch & Pay"**. The agent will automatically pay and fetch the protected content.
  </Step>
</Steps>

## Payment Flow Details

### 1. Initial Request (No Payment)

```http theme={null}
GET /protected-route HTTP/1.1
Host: localhost:5173
```

### 2. Server Response (402 Payment Required)

```http theme={null}
HTTP/1.1 402 Payment Required
WWW-Authenticate: x402 resource="http://localhost:5173/protected-route"

{
  "accepts": [
    {
      "scheme": "exact",
      "price": "$0.10",
      "network": "eip155:84532",
      "payTo": "0x..."
    }
  ]
}
```

### 3. Client Signs Payment

The agent:

1. Parses the payment options
2. Creates an EVM transaction
3. Signs with its private key
4. Submits to the blockchain
5. Gets a transaction hash

### 4. Retry with Payment Proof

```http theme={null}
GET /protected-route HTTP/1.1
Host: localhost:5173
Authorization: x402 scheme=exact, txhash=0x..., network=eip155:84532
```

### 5. Server Verifies and Responds

The middleware:

1. Extracts the payment proof
2. Verifies the transaction on-chain
3. Checks amount and recipient
4. Serves the content if valid

```http theme={null}
HTTP/1.1 200 OK
Content-Type: application/json

{
  "message": "This content is behind a paywall. Thanks for paying!"
}
```

## Comparison: x402 vs x402-mcp

| Feature          | x402 (This Example)              | x402-mcp                         |
| ---------------- | -------------------------------- | -------------------------------- |
| **What's gated** | HTTP endpoints                   | MCP tools                        |
| **Protocol**     | HTTP with `402 Payment Required` | MCP with payment extensions      |
| **Use case**     | REST APIs, web content           | AI agent tools                   |
| **Libraries**    | `@x402/hono`, `@x402/fetch`      | `withX402()`, `withX402Client()` |
| **Integration**  | Hono middleware                  | Agent SDK wrappers               |

## Security Considerations

### Private Key Management

* **Never hardcode private keys** in source code
* Use environment variables or Cloudflare secrets
* Use test keys for development, real keys only in production
* Rotate keys regularly

### Payment Verification

The middleware automatically:

* Verifies transaction signatures
* Checks transaction confirmation on-chain
* Validates payment amount and recipient
* Prevents replay attacks

### Network Configuration

For production:

* Use mainnet (`eip155:8453` for Base)
* Monitor payment transactions
* Set appropriate timeout values
* Handle network errors gracefully

## Related Examples

<CardGroup cols={2}>
  <Card title="x402 MCP" icon="plug" href="/examples/x402-mcp">
    Paid MCP tools using Agent SDK integration
  </Card>

  <Card title="MCP Server" icon="server" href="/examples/mcp-server">
    Build MCP servers with persistent state
  </Card>

  <Card title="GitHub Webhook" icon="webhook" href="/examples/github-webhook">
    Handle webhooks with signature verification
  </Card>

  <Card title="Email Agent" icon="envelope" href="/examples/email-agent">
    Process emails with secure routing
  </Card>
</CardGroup>

## Further Reading

* [x402 Protocol Specification](https://x402.org)
* [x402 npm packages](https://www.npmjs.com/search?q=%40x402)
* [Base Sepolia Testnet](https://docs.base.org/network-information/#base-testnet-sepolia)
* [Circle Testnet Faucet](https://faucet.circle.com/)
