> ## Documentation Index
> Fetch the complete documentation index at: https://anypay-docs-update-resources-2026-06-29.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# x402 Payments

> Learn how to integrate Trails with gasless HTTP payment authentication using x402

# What is x402?

x402 is an HTTP payment protocol that enables **gasless, signature-based payments** to authenticate API requests. Instead of on-chain transactions, users sign an EIP-712 message that authorizes a payment facilitator to transfer tokens on their behalf.

Key benefits:

* ✅ No gas fees for users
* ✅ Instant payment verification
* ✅ Works over standard HTTP
* ✅ Perfect for API monetization

## Why Combine Them?

Many facilitators only accept specific tokens on specific chains. In addition, x402 requires EIP-3009 on the token contract further limiting token support. However, Trails enables x402 using any token from any chain.

Trails + x402 creates a powerful payment flow:

1. **User pays** with Trails using any token from any chain
2. **Payment arrives** on your chosen chain and token that the facilitator supports (e.g., Base USDC)
3. **Automatic trigger** of x402 signature for API access
4. **Gasless authentication** to your protected endpoints
5. **API responds** with paid content/service

## Architecture

```
┌──────────────┐
│   Frontend   │
│   (React)    │
└──────┬───────┘
       │
       │ 1. User clicks "Pay & Get Access"
       │
       ▼
┌──────────────────────┐
│   Trails Widget      │
│   (Cross-chain Pay)  │
└──────┬───────────────┘
       │
       │ 2. Routes payment from any chain/token
       │    to Base USDC (or your target)
       │
       ▼
┌──────────────────────┐
│  onPaymentSuccess    │
│     (Callback)       │
└──────┬───────────────┘
       │
       │ 3. Triggers x402 signature
       │
       ▼
┌──────────────────────┐
│  x402-axios          │
│  (Payment Signer)    │
└──────┬───────────────┘
       │
       │ 4. Adds payment header to HTTP request
       │
       ▼
┌──────────────────────┐
│  Backend API         │
│  (x402-hono)         │
└──────┬───────────────┘
       │
       │ 5. Verifies payment & transfers tokens
       │
       ▼
┌──────────────────────┐
│  Protected Response  │
│  (API Data)          │
└──────────────────────┘
```

## Implementation

### Frontend Setup

#### 1. Install Dependencies

```bash theme={null}
pnpm add 0xtrails x402-axios axios
```

This example pairs Trails with an existing wagmi + RainbowKit setup. Since [`0xtrails@0.16.0`](/sdk/changelog/0xtrails-0.16.0), wagmi is opt-in for Trails — also install `@0xtrails/adapter-wagmi` so Trails can share the wagmi session:

```bash theme={null}
pnpm add @0xtrails/adapter-wagmi
```

#### 2. Configure Providers

<CodeGroup>
  ```tsx Providers.tsx theme={null}
  import { WagmiProvider, createConfig, http } from "wagmi"
  import { RainbowKitProvider } from "@rainbow-me/rainbowkit"
  import { QueryClientProvider, QueryClient } from "@tanstack/react-query"
  import { mainnet, base } from "wagmi/chains"
  import { TrailsProvider } from "0xtrails"
  import { wagmiAdapter } from "@0xtrails/adapter-wagmi"

  const config = createConfig({
    chains: [mainnet, base],
    transports: {
      [mainnet.id]: http(),
      [base.id]: http(),
      [baseSepolia.id]: http(),
    },
  })

  const queryClient = new QueryClient()

  const adapters = [wagmiAdapter({ wagmiConfig: config })]

  export function Providers({ children }: { children: React.ReactNode }) {
    return (
      <WagmiProvider config={config}>
        <QueryClientProvider client={queryClient}>
          <TrailsProvider config={{ trailsApiKey: "YOUR_TRAILS_API_KEY", adapters }}>
            <RainbowKitProvider>
              {children}
            </RainbowKitProvider>
          </TrailsProvider>
        </QueryClientProvider>
      </WagmiProvider>
    )
  }
  ```
</CodeGroup>

#### 3. Create x402 API Client

<CodeGroup>
  ```ts services/api.ts theme={null}
  import axios from "axios"
  import type { WalletClient } from "viem"
  import { withPaymentInterceptor } from "x402-axios"

  const baseApiClient = axios.create({
    baseURL: "http://localhost:3001",
    headers: { "Content-Type": "application/json" },
  })

  let apiClient = baseApiClient

  // Update API client when wallet connects
  export function updateApiClient(walletClient: WalletClient | null) {
    if (walletClient && walletClient.account) {
      // Attach x402 payment interceptor to axios
      apiClient = withPaymentInterceptor(baseApiClient, walletClient as any)
      console.log("💳 API client ready for payments")
    } else {
      apiClient = baseApiClient
    }
  }

  // API endpoints
  export const api = {
    // Protected endpoint - requires x402 payment
    purchaseOneTimeAccess: async () => {
      const response = await apiClient.post("/api/pay/onetime")
      return response.data
    },
  }
  ```
</CodeGroup>

<Info>
  The `withPaymentInterceptor` automatically handles EIP-712 signature creation and attaches payment headers to HTTP requests.
</Info>

#### 4. Build Payment Widget Component

<CodeGroup>
  ```tsx components/PayWidget.tsx theme={null}
  import { Pay } from "0xtrails/widget"
  import type { TrailsWidgetRef } from "0xtrails/widget"
  import { useState, useCallback, useRef } from "react"
  import { useWalletClient, useSwitchChain } from "wagmi"
  import { base } from "wagmi/chains"
  import { api, updateApiClient } from "../services/api"

  export default function PayWidget() {
    const widgetRef = useRef<TrailsWidgetRef | null>(null)
    const [loading, setLoading] = useState(false)
    const [result, setResult] = useState<string>("")
    const { data: walletClient } = useWalletClient()
    const { switchChainAsync } = useSwitchChain()

    // Handle Trails payment completion
    const handleTrailsComplete = useCallback(
      async (data: { sessionId: string }) => {
        console.log("✅ Trails payment complete:", data.sessionId)
        
        // Close Trails modal
        widgetRef.current?.closeModal?.()
        
        // Switch to payment network (Base)
        try {
          await switchChainAsync?.({ chainId: base.id })
        } catch (err) {
          console.error("Network switch failed:", err)
        }

        if (!walletClient) {
          setResult("❌ Wallet not connected")
          return
        }

        try {
          setLoading(true)
          setResult("🔄 Authorizing API access via x402...")
          
          // Update API client with wallet for x402 signing
          updateApiClient(walletClient)
          
          // Make payment-protected API request
          // x402-axios will automatically:
          // 1. Prompt user to sign EIP-712 message
          // 2. Add payment signature to request headers
          // 3. Facilitator verifies and transfers tokens
          const response = await api.purchaseOneTimeAccess()
          
          setResult(`✅ API access granted! Session: ${response.sessionId}`)
        } catch (error: any) {
          console.error("x402 payment error:", error)
          setResult(`❌ Payment failed: ${error.message}`)
        } finally {
          setLoading(false)
        }
      },
      [walletClient, switchChainAsync]
    )

    return (
      <div className="space-y-4">
        <Pay
          ref={widgetRef}
          apiKey="YOUR_API_KEY"
          theme="auto"
          to={{
            recipient: "0xYourAddress",
            currency: "USDC",
            chain: "base",
            amount: "0.1",
          }}
          buttonText="Pay & Get Access"
          onPaymentSuccess={handleTrailsComplete}
          customCss={`
            --trails-border-radius-button: 9999px;
            --trails-primary: #4285F4;
            --trails-primary-hover: #357AE8;
          `}
        />
        
        {loading && <p>Processing...</p>}
        {result && <p>{result}</p>}
      </div>
    )
  }
  ```
</CodeGroup>

<Tip>
  The `onPaymentSuccess` callback is the bridge between Trails and x402. It fires when the cross-chain payment succeeds, then triggers the x402 signature flow.
</Tip>

### Backend Setup

#### 1. Install Dependencies

```bash theme={null}
pnpm add hono @hono/node-server x402-hono dotenv uuid
```

#### 2. Configure Environment

<CodeGroup>
  ```env server/.env theme={null}
  # Your wallet address to receive x402 payments
  ADDRESS=0xYourWalletAddress

  # Network for x402 payments
  NETWORK=base

  # x402 Facilitator URL
  FACILITATOR_URL=https://facilitator.payai.network

  # Server Port
  PORT=3001
  ```
</CodeGroup>

#### 3. Create x402 Protected API

<CodeGroup>
  ```ts server/index.ts theme={null}
  import { Hono } from "hono"
  import { serve } from "@hono/node-server"
  import { cors } from "hono/cors"
  import { paymentMiddleware, Network, Resource } from "x402-hono"
  import { v4 as uuidv4 } from "uuid"
  import { config } from "dotenv"

  config()

  const facilitatorUrl = process.env.FACILITATOR_URL as Resource
  const payTo = process.env.ADDRESS as `0x${string}`
  const network = process.env.NETWORK as Network || "base"
  const port = parseInt(process.env.PORT || "3001")

  const app = new Hono()

  // Enable CORS for frontend
  app.use("/*", cors({
    origin: ["http://localhost:5173"],
    credentials: true,
  }))

  // In-memory session storage (use Redis/DB in production)
  const sessions = new Map<string, any>()

  // Configure x402 payment middleware
  app.use(
    paymentMiddleware(
      payTo, // Your wallet address
      {
        // Define paid endpoints and prices
        "/api/pay/onetime": {
          price: "$0.10",
          network,
        },
        "/api/pay/session": {
          price: "$1.00",
          network,
        },
      },
      {
        url: facilitatorUrl, // x402 facilitator
      }
    )
  )

  // Protected endpoint - requires x402 payment ($0.10)
  app.post("/api/pay/onetime", async (c) => {
    // This code only runs if payment succeeds!
    const sessionId = uuidv4()
    const now = new Date()
    
    const session = {
      id: sessionId,
      createdAt: now,
      expiresAt: new Date(now.getTime() + 5 * 60 * 1000), // 5 min
      type: "onetime",
    }
    
    sessions.set(sessionId, session)
    
    // Return protected data/service
    return c.json({
      success: true,
      sessionId,
      message: "Payment verified! Access granted.",
      data: {
        // Your protected API response here
        exampleData: "This is only visible after payment",
      },
    })
  })

  // Free endpoint - health check
  app.get("/api/health", (c) => {
    return c.json({
      status: "ok",
      network,
      payTo,
    })
  })

  serve({ fetch: app.fetch, port })
  console.log(`🚀 x402 Server running on port ${port}`)
  ```
</CodeGroup>

<Note>
  The `paymentMiddleware` intercepts requests to protected routes and verifies the x402 payment signature before allowing access.
</Note>

## Payment Flow Breakdown

### Step 1: User Initiates Payment (Trails)

```tsx theme={null}
<Pay
  apiKey="YOUR_API_KEY"
  to={{
    recipient: "0xYourAddress",
    currency: "USDC",
    chain: "base",
    amount: "0.1",
  }}
  onPaymentSuccess={handleTrailsComplete}
/>
```

The user clicks the Trails button and:

* Selects their source chain and token (e.g., ETH on Arbitrum)
* Trails calculates optimal route (swap → bridge → execute)
* User approves transaction
* Payment arrives as USDC on Base

<Info>
  Trails handles all complexity: token swaps, bridge routing, gas estimation, and delivery confirmation.
</Info>

### Step 2: Trails Callback Triggers x402

```tsx theme={null}
const handleTrailsComplete = useCallback(async (data) => {
  // Update API client with wallet for signing
  updateApiClient(walletClient)
  
  // Make x402-protected API request
  const response = await api.purchaseOneTimeAccess()
}, [walletClient])
```

When `onPaymentSuccess` fires:

1. API client is configured with the user's wallet
2. HTTP request is made to protected endpoint
3. x402 interceptor prompts for EIP-712 signature
4. Signature is attached to request headers

### Step 3: x402 Signature Creation

```ts theme={null}
// x402-axios handles this automatically
withPaymentInterceptor(axiosInstance, walletClient)
```

The interceptor:

1. Detects `402 Payment Required` response
2. Parses payment details from response headers
3. Creates EIP-712 typed data structure
4. Prompts user to sign (gasless, off-chain)
5. Retries request with payment signature

<Warning>
  Users sign a message, not a transaction. This is **gasless** and instant.
</Warning>

### Step 4: Backend Verification

```ts theme={null}
app.use(
  paymentMiddleware(
    payTo,
    {
      "/api/pay/onetime": { price: "$0.10", network: "base" },
    },
    { url: facilitatorUrl }
  )
)
```

The middleware:

1. Validates payment signature
2. Sends transfer request to facilitator
3. Facilitator transfers tokens from user → your wallet
4. If successful, request proceeds to handler
5. If failed, returns `402 Payment Required`

### Step 5: Protected Response

```ts theme={null}
app.post("/api/pay/onetime", (c) => {
  // Payment verified! Return protected data
  return c.json({
    success: true,
    data: "Your protected content",
  })
})
```

Only accessible if payment succeeds.

## Conclusion

Combining Trails and x402 creates a seamless payment experience:

* **Trails** handles the complexity of cross-chain payments
* **x402** provides gasless, instant API authentication
* **Together** they enable truly user-friendly paid services - paid with any token from any chain.

This pattern works for:

* 🔐 API monetization
* 📰 Content paywalls
* 🎮 Gaming microtransactions
* 📊 Data services
* 🤖 AI API access
* 💼 SaaS applications

Start building payment-gated services today!
