11 min read
Overview
Quicknode's infrastructure powers billions of requests across 130+ blockchain networks. With x402 on Quicknode, any client with a wallet can access that same infrastructure through a pay-per-request model built on the x402 protocol. Authenticate with your wallet, make calls (e.g., RPC, REST, gRPC-Web, WebSocket) across any supported network, and pay with USDC on Base. No account, API keys, or subscription needed.
This opens up new possibilities for how developers and AI agents consume blockchain infrastructure. Instead of provisioning an endpoint upfront, you connect a wallet and start making calls immediately across JSON-RPC, REST, gRPC-Web, and WebSocket protocols.
This guide walks you through how x402 on Quicknode works, who it's for, and how to make your first x402-powered RPC request.
x402 on Quicknode is currently in alpha. It's designed for experimentation and early adoption. While the underlying infrastructure is the same production-grade system that powers Quicknode's platform, the x402 access layer is new and evolving. Expect potential API changes, shifting rate limits, and ongoing feature refinement as the product matures.
- Understand how x402 enables wallet-based access to Quicknode endpoints (including RPC, REST, gRPC-Web, and WebSocket)
- Learn the authentication and payment flow (SIWE, JWT, credits, x402 settlement)
- Run the JSON-RPC example to make your first x402-powered call on Base Sepolia
- Explore multi-protocol examples across JSON-RPC, REST, gRPC-Web, and WebSocket
What You Will Need
- Node.js (v18 or higher) and npm
- Basic familiarity with blockchain concepts
That's it. You don't need a Quicknode account, API keys, or even a pre-existing wallet. The example scripts handle wallet generation, SIWE authentication, and testnet USDC funding automatically.
Why x402 on Quicknode
x402 adds a new way to consume Quicknode's infrastructure alongside existing plans. It's designed for use cases where wallet-based, on-demand access is a better fit than traditional account setup:
- AI agents and autonomous bots that need to authenticate and pay without human intervention. An agent only needs a wallet with USDC to start making calls.
- Developers building agent-based tools where end users interact with Quicknode infrastructure without needing their own accounts.
- Low-usage developers who want occasional access to high-quality endpoints across multiple chains without committing to a plan.
- Privacy-focused users who prefer wallet-based access over account registration.
- Experimentation and prototyping where developers want to test across networks quickly without setup overhead.
The key difference: existing plans are optimized for sustained usage with predictable billing. x402 is optimized for on-demand access where every request is individually funded.
How It Works
x402 on Quicknode follows a drawdown credit model: authenticate with your wallet, pay USDC to receive credits, then consume those credits across requests. When credits run out, another payment is triggered automatically.
Step-by-Step Breakdown
In these examples, you'll handle SIWE authentication and JWT attachment in your own helper logic. The @x402/fetch library then handles the x402-specific payment and retry flow, so you can keep making normal fetch calls. Nevertheless, here's what's happening under the hood:
1. Authenticate with SIWE
The client signs a Sign-In with Ethereum (SIWE) message using their wallet. This proves ownership of the wallet address without exposing any private keys. The proxy returns a JWT token (valid for one hour) that the client includes in subsequent requests.
2. First Request Returns 402
When you make your first call (or any call with zero credits), the proxy responds with HTTP 402 Payment Required. This response includes payment requirements following the x402 v2 specification, specifying how much USDC to pay and on which network.
3. Pay and Receive Credits
The client signs a USDC payment authorization (EIP-712) and retries the request with the payment header. The x402 facilitator settles the payment on-chain, and the proxy credits your account with a request bundle.
4. Consume Credits
From that point, each request deducts one credit. When the balance hits zero, the next request triggers another 402, and the cycle repeats. The infrastructure behind the proxy is the same production system that powers all Quicknode endpoints.
Payment Options
x402 on Quicknode handles payments exclusively on Base and supports two payment paths:
| Option | Best For | Pricing |
|---|---|---|
| Base Sepolia USDC | Testing and experimentation | 100 credits per $0.01, up to 10,000 credits per $1.00 |
| Base Mainnet USDC | Production usage | 1,000,000 credits for $10 |
This dual approach lets developers and agents interact with x402 flows in a test environment without risking real funds, and then seamlessly transition to mainnet when ready.
Note: Payment through Solana USDC will be supported soon, and we plan to add support for additional payment networks over time based on demand.
Supported Networks through x402
Once you've paid via x402, you can use your credits to make calls across any of Quicknode's 130+ supported blockchain networks, including Ethereum, Base, Solana, Arbitrum, Polygon, Aptos, Flow, and many more.
For the full list of supported chains, see Quicknode's supported chains page.
Multi-Protocol Support
One of the most powerful aspects of x402 on Quicknode is that it works across multiple protocols. The same wallet-based authentication and payment flow applies whether you're making a standard JSON-RPC call, querying a REST API, streaming data over gRPC, or subscribing to real-time events via WebSocket.
| Protocol | Use Case |
|---|---|
| JSON-RPC | Standard RPC calls (e.g., eth_blockNumber, getBlock) |
| REST | HTTP GET endpoints (e.g., /v1/blocks/by_height) |
| gRPC-Web | Unary calls and server-side streaming for high-performance chains (e.g., GetLatestBlock) |
| WebSocket | Real-time subscriptions (e.g., eth_subscribe, accountSubscribe) |
This means a single wallet and a single authentication flow can give you access to EVM chains via JSON-RPC, Aptos via REST, Flow via gRPC, and real-time Ethereum data via WebSocket. The x402 payment layer works the same across all of them.
The qn-x402-examples repository includes working scripts for each protocol. In the next section, we'll walk through the JSON-RPC example step by step, and you can explore the others at your own pace.
Getting Started: JSON-RPC Example
The fastest way to experience x402 on Quicknode is through the example scripts in the qn-x402-examples repository. These scripts handle everything automatically: wallet generation, SIWE authentication, testnet USDC funding, and paid RPC calls.
We'll walk through the JSON-RPC example (jsonrpc.ts), which makes eth_blockNumber calls on Base Sepolia until credits are exhausted, showing the full authentication and payment cycle.
Step 1: Clone the Repository and Install Dependencies
git clone https://github.com/quiknode-labs/qn-x402-examples.git
cd qn-x402-examples
npm install
Step 2: Run the JSON-RPC Example
npm run start:jsonrpc
That's it. On first run, the script will:
- Generate a new wallet and save the private key to
.env(reused on subsequent runs) - Authenticate via SIWE by signing a message with the generated wallet and exchanging it for a JWT token
- Check USDC balance and request testnet USDC from the
/dripfaucet if needed - Make
eth_blockNumbercalls in a loop, showing credit consumption per request - Handle the 402 payment automatically when credits run out, signing a USDC payment and continuing
x402 Example - Paid JSON-RPC Requests (SIWE + JWT Auth)
============================================================
Generated new wallet and saved to .env
Wallet: 0x3a97eEe611FedadB8fcFe436c4126cA6438Af34f
Authenticating with SIWE...
Authenticated as eip155:84532:0x3a97eee611fedadb8fcfe436c4126ca6438af34f
Token expires: 2026-02-10T11:20:28.000Z
USDC balance: 0 USDC
Insufficient USDC (need >= 0.005 USDC)
Requesting USDC from x402 drip...
Faucet request successful: tx 0x2866fd18e94804335c6e7c5c5eca73f2f346a5f87941455a97226d6c93299d92
Waiting for USDC balance >= 0.005 USDC...
Current balance: 0 USDC
Current balance: 1 USDC
Updated USDC balance: 1 USDC
============================================================
Checking credits...
Account: eip155:84532:0x3a97eee611fedadb8fcfe436c4126ca6438af34f
Credits: 0
============================================================
-- JSON-RPC Credit Consumption Loop (base-sepolia) --
Mode: standalone (1 payment max)
No credits — first request will trigger x402 payment
PAYMENT-RESPONSE #1 - SUCCESS tx: 0x73fae815b5aa7d559f...
10:20:42.171 Request #1: Block 37475276 | Credits: 99 (+99)
10:20:42.505 Request #2: Block 37475277 | Credits: 98 (-1)
10:20:42.785 Request #3: Block 37475277 | Credits: 97 (-1)
10:20:43.083 Request #4: Block 37475277 | Credits: 96 (-1)
10:20:43.354 Request #5: Block 37475277 | Credits: 95 (-1)
# ... continues until credits run out again or script is stopped
Understanding the Code
Let's look at the key parts of how the example works. The full source is available in the qn-x402-examples repository.
SIWE Authentication (from lib/x402-helpers.ts)
The authenticate function creates a SIWE message, signs it with the wallet, and exchanges it for a JWT:
export async function authenticate(
walletClient: WalletClient,
tokenRef: TokenRef
): Promise<string> {
const siweMessage = new SiweMessage({
domain: new URL(X402_BASE_URL).host,
address: walletClient.account!.address,
statement: SIWX_STATEMENT,
uri: X402_BASE_URL,
version: '1',
chainId: BASE_SEPOLIA_CHAIN_ID,
nonce: generateNonce(),
issuedAt: new Date().toISOString(),
})
const message = siweMessage.prepareMessage()
const signature = await walletClient.signMessage({
account: walletClient.account!,
message,
})
const response = await fetch(X402_AUTH_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message, signature }),
})
const { token, accountId, expiresAt } = await response.json()
tokenRef.value = token
return token
}
The SIWE message includes the wallet address, a nonce for replay protection, and a statement accepting Quicknode's Terms of Service. The signed message is exchanged for a JWT at the /auth endpoint, which is valid for one hour.
Creating the x402-Enabled Fetch (from lib/x402-helpers.ts)
The createX402Fetch function wraps the standard fetch with JWT injection and automatic x402 payment handling features:
export function createX402Fetch(
walletClient: WalletClient,
tokenRef: TokenRef,
tracker: PaymentTracker
): typeof globalThis.fetch {
// Base fetch that injects JWT
const authedFetch = async (
input: RequestInfo | URL,
init?: RequestInit
): Promise<Response> => {
const headers = new Headers(init?.headers)
if (tokenRef.value) headers.set('Authorization', `Bearer ${tokenRef.value}`)
return fetch(input, { ...init, headers })
}
// x402 v2 payment handling
const evmSigner = toClientEvmSigner({
address: walletClient.account!.address,
signTypedData: params =>
walletClient.signTypedData(
params as Parameters<typeof walletClient.signTypedData>[0]
),
})
const client = new x402Client().register(
BASE_SEPOLIA_CAIP2,
new ExactEvmScheme(evmSigner)
)
const x402Fetch = wrapFetchWithPayment(authedFetch, client)
return x402Fetch
}
This is where the x402 magic happens. The wrapFetchWithPayment function from @x402/fetch intercepts any 402 Payment Required response, automatically signs an EIP-712 USDC payment authorization using @x402/evm, and retries the request with the payment header. The authedFetch layer ensures every request includes the JWT for authentication.
Making JSON-RPC Calls (from jsonrpc.ts)
With the x402-enabled fetch in place, making a paid JSON-RPC call looks like any standard request:
const JSONRPC_URL = `${X402_BASE_URL}/${JSONRPC_NETWORK}`
async function jsonRpc(
x402Fetch: typeof globalThis.fetch,
method: string,
params: unknown[] = []
): Promise<unknown> {
const response = await x402Fetch(JSONRPC_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
id: Date.now(),
method,
params,
}),
})
const data = await response.json()
if (data.error) throw new Error(data.error.message)
return data.result
}
// Usage in the main loop
const result = await jsonRpc(x402Fetch, 'eth_blockNumber')
const blockNumber = BigInt(result as string)
The application code doesn't need to know about payments. Use the URL format ${X402_BASE_URL}/${network} to target different chains through the proxy.
Exploring Other Request Types
After running the JSON-RPC example, explore the other scripts to see x402 in action across different protocols and chains.
REST API
The rest.ts script demonstrates x402 with REST API endpoints on Aptos Mainnet. It makes standard HTTP GET requests to endpoints like /v1/ (ledger info), /v1/blocks/by_height/{h}, and /v1/accounts/0x1. The same x402 fetch wrapper handles authentication and payments for REST calls, just as it does for JSON-RPC.
npm run start:rest
gRPC-Web
The grpc.ts script showcases both unary calls (Ping, GetLatestBlock) and server-side streaming (SubscribeBlocksFromLatest) on Flow Mainnet using @connectrpc/connect-web. The x402 fetch wrapper integrates directly with the Connect-RPC transport, so gRPC calls go through the same payment flow as any other request.
npm run start:grpc
WebSocket: Ethereum Real-Time Subscriptions
The websocket.ts script subscribes to newHeads on Base Mainnet via eth_subscribe, receiving real-time block headers as they're produced. It uses a non-blocking credit poller to track remaining credits without interrupting the data stream. When credits are exhausted, the connection handles the 4402 close code and can re-authenticate automatically.
npm run start:ws
For full details on each script, including configuration options and network overrides, see the README.
Quicknode's Agent-Ready Infrastructure
x402 is one part of Quicknode's broader investment in making blockchain infrastructure accessible to AI agents and LLM-powered tools. If you're building agent-based applications, these resources are worth exploring: