Documentation Index
Fetch the complete documentation index at: https://anypay-docs-sdk-0-15-0-updates.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
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:
- User pays with Trails using any token from any chain
- Payment arrives on your chosen chain and token that the facilitator supports (e.g., Base USDC)
- Automatic trigger of x402 signature for API access
- Gasless authentication to your protected endpoints
- 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
pnpm add 0xtrails x402-axios axios
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"
const config = createConfig({
chains: [mainnet, base],
transports: {
[mainnet.id]: http(),
[base.id]: http(),
[baseSepolia.id]: http(),
},
})
const queryClient = new QueryClient()
export function Providers({ children }: { children: React.ReactNode }) {
return (
<WagmiProvider config={config}>
<QueryClientProvider client={queryClient}>
<RainbowKitProvider>
{children}
</RainbowKitProvider>
</QueryClientProvider>
</WagmiProvider>
)
}
3. Create x402 API Client
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
},
}
The withPaymentInterceptor automatically handles EIP-712 signature creation and attaches payment headers to HTTP requests.
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>
)
}
The onPaymentSuccess callback is the bridge between Trails and x402. It fires when the cross-chain payment succeeds, then triggers the x402 signature flow.
Backend Setup
1. Install Dependencies
pnpm add hono @hono/node-server x402-hono dotenv uuid
# 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
3. Create x402 Protected API
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}`)
The paymentMiddleware intercepts requests to protected routes and verifies the x402 payment signature before allowing access.
Payment Flow Breakdown
Step 1: User Initiates Payment (Trails)
<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
Trails handles all complexity: token swaps, bridge routing, gas estimation, and delivery confirmation.
Step 2: Trails Callback Triggers x402
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:
- API client is configured with the userโs wallet
- HTTP request is made to protected endpoint
- x402 interceptor prompts for EIP-712 signature
- Signature is attached to request headers
Step 3: x402 Signature Creation
// x402-axios handles this automatically
withPaymentInterceptor(axiosInstance, walletClient)
The interceptor:
- Detects
402 Payment Required response
- Parses payment details from response headers
- Creates EIP-712 typed data structure
- Prompts user to sign (gasless, off-chain)
- Retries request with payment signature
Users sign a message, not a transaction. This is gasless and instant.
Step 4: Backend Verification
app.use(
paymentMiddleware(
payTo,
{
"/api/pay/onetime": { price: "$0.10", network: "base" },
},
{ url: facilitatorUrl }
)
)
The middleware:
- Validates payment signature
- Sends transfer request to facilitator
- Facilitator transfers tokens from user โ your wallet
- If successful, request proceeds to handler
- If failed, returns
402 Payment Required
Step 5: Protected Response
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!