The internet was built on a suite of error codes that define our digital interactions: 200 for success, 404 for not found, and 500 for server errors. But for decades, one code remained a ghost in the machine, reserved for a future use case that never quite arrived in the Web2 era: HTTP 402 Payment Required.
Today, we are vibrating on a different frequency. With the advent of programmable money and high-performance Layer 2 blockchains like Base, we finally have the infrastructure to bring the 402 status code to life.
In Part 1 of this "Vibecoding" series, we aren't just building a web app; we are architecting a native economic layer for the web. We will use the X402 Protocol, a standardized framework that allows machines to negotiate prices and exchange value instantly over HTTP using cryptocurrency.
Traditional paywalls are clunky. They require sign-ups, credit card entries, and recurring subscriptions that users dread. X402 changes the paradigm to pay-per-request. Imagine an API that costs 0.01 USDC per call, or a premium blog post that unlocks for pennies in ETH, instantly, wallet-to-wallet, without a middleman taking 30%.

We will build the foundation of a Monetized Real-Time Intelligence Dashboard.
The Stack: Node.js, Express, and Viem.
The Editor: Cursor (AI-native).
The Goal: A protected backend route that returns a 402 error to unpaid requests and serves premium content to requests accompanied by a valid blockchain transaction hash.
Before we prompt Cursor to generate code, we need to understand the mental model of the X402 protocol. It operates on a decentralized Client/Server architecture that mirrors standard HTTP, but with an added financial handshake.
The Challenge: The Client requests a resource (e.g., /api/premium-data).
The Rejection: The Server checks for payment headers. Finding none, it responds with HTTP 402 Payment Required. Crucially, this response includes metadata: the price, the accepted token (ETH or USDC), and the receiver address.
The Payment: The Client (powered by x402-axios or similar) reads this metadata. It uses a connected wallet to execute a transaction on the Base network.
The Fulfillment: The Client retries the request, this time attaching the transaction hash as proof of payment.
The Delivery: The Server verifies the transaction on-chain using an RPC provider (facilitator), confirms the value matches the price, and serves the resource with HTTP 200 OK.
We are building on Base (Coinbase's L2) because micro-payments require micro-fees. Sending $0.05 on Ethereum Mainnet costs $5.00 in gas. On Base, it costs fractions of a cent. For development, we will stick to Base Sepolia to save real funds, but the code is identical for Base Mainnet.
Let's initialize our workspace. Open Cursor and open your terminal (Ctrl + ~).
We need a clean separation of concerns. Our project will house both the server (the merchant) and the client (the customer) to demonstrate the full loop.
mkdir x402-goldrush-app
cd x402-goldrush-app
npm init -yWe need a robust set of tools.
Express: The web server framework.
x402-express: The official middleware that handles the 402 logic automatically.
x402-client / x402-axios: The client-side wrappers to handle the "payment retry" logic.
viem: The modern, lightweight alternative to Ethers.js for wallet management.
dotenv: For keeping our private keys off GitHub.
Run the following vibecoding command:
npm install express x402-express x402-axios viem dotenv cors
npm install --save-dev nodemon
Create the following file structure using Cursor's file explorer or command line:
x402-goldrush-app/
├── .env # Secrets
├── server.js # The Payment-Protected API
├── client.js # The Paying Customer Script
└── public/
└── index.html # Frontend (for Part 2)Security is paramount. When dealing with private keys, one slip-up can drain your testnet funds (or worse, mainnet funds).
Create your .env file. Do not commit this file.
# Server Configuration
PORT=3000
# X402 Configuration
# Your wallet private key (The one PAYING for requests in the client script)
# Format: 0x...
PRIVATE_KEY=0xYOUR_PRIVATE_KEY_HERE
# The URL of the Facilitator (RPC Gateway)
# Base Sepolia is the default for testing
NETWORK=base-sepoliaVibecoding Tip: In Cursor, type Cmd+K and ask: "Generate a secure .env template for a Node.js web3 app including port and private key variables." Cursor will scaffold this for you instantly.
Let's build the server that will sell our data. Open server.js.
We will start with a basic Express setup. This is the "Merchant" node.
require('dotenv').config();
const express = require('express');
const cors = require('cors');
const app = express();
app.use(cors());
app.use(express.json());
// Public Route - Free for everyone
app.get('/', (req, res) => {
res.send('<h1>Welcome to the GoldRush X402 Gateway</h1><p>Public endpoint active.</p>');
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`🚀 Merchant Server running on http://localhost:${PORT}`);
});
Verify this works by running npx nodemon server.js . You should see the rocket emoji in your terminal.
Now comes the magic. We will protect a route using the x402-express middleware. This middleware intercepts requests and checks for payment proofs.
Add the integration code to server.js.
We need to import paymentMiddleware from the package. We will define a price and a receiver address.
Prompt for Cursor: "Add x402-express middleware to protect the /premium-data route. Set the price to 0.001 ETH on Base Sepolia."
Cursor will likely generate something like this:
const { paymentMiddleware } = require('x402-express');
// Configuration for the item we are selling
const premiumContentConfig = {
serviceName: 'GoldRush Intelligence Stream',
price: '0.001', // Price in ETH
currency: 'ETH', // Native token
recipientAddress: '0xYOUR_RECEIVER_WALLET_ADDRESS', // Replace with your public key!
network: 'base-sepolia'
};
// Protected Route
app.get('/api/premium-data', paymentMiddleware(premiumContentConfig), (req, res) => {
// This code only executes if payment is verified!
res.json({
success: true,
message: "PAYMENT VERIFIED: Here is your premium GoldRush data.",
data: {
alpha: "Base is booming.",
timestamp: new Date().toISOString()
}
});
});
When a user hits /api/premium-data, the middleware:
Checks headers for authorization.
If missing, it halts the request pipeline.
It constructs a 402 response containing the recipientAddress and price.
It sends this back to the client immediately.
Now we need a customer. A standard browser cannot handle 402 errors automatically yet (though wallets are working on it). We need to build a specialized client using x402-axios.
Open client.js. This script represents a bot or a specialized frontend trying to buy data.
We use viem because it handles EIP-1193 providers cleanly and is much smaller than Ethers.js.
require('dotenv').config();
const { createWalletClient, http, parseEther } = require('viem');
const { privateKeyToAccount } = require('viem/accounts');
const { baseSepolia } = require('viem/chains');
const { X402Axios } = require('x402-axios');
async function runClient() {
// 1. Setup the Wallet
const account = privateKeyToAccount(process.env.PRIVATE_KEY);
const walletClient = createWalletClient({
account,
chain: baseSepolia,
transport: http()
});
console.log(`🤖 Bot initialized with wallet: ${account.address}`);
// 2. Initialize the X402 Client wrapper
// This wraps axios to auto-handle 402 responses
const client = new X402Axios({
walletClient: walletClient,
// Logic to verify transaction receipt would go here in advanced implementations
});
try {
console.log("💸 Attempting to access premium content...");
// 3. Make the Request
// The client will hit the endpoint, get a 402, pay the ETH, and retry automatically.
const response = await client.get('http://localhost:3000/api/premium-data');
console.log("\n✅ SUCCESS! Data Received:");
console.log(response.data);
} catch (error) {
console.error("\n❌ TRANSACTION FAILED:");
if (error.response) {
console.error(`Status: ${error.response.status}`);
console.error(error.response.data);
} else {
console.error(error.message);
}
}
}
runClient();It's time to run our economic simulation.
Start the Server: Ensure node server.js is running.
Run the Client: In a new terminal, run node client.js.
When a user hits our frontend, they should see a clear "Paywall" requiring crypto payment. This is what the X402 checkout experience looks like:

Once the user pays, the backend validates the transaction hash. You can confirm this in your server terminal or via the client output. Here is a successful handshake where the x-payment header is verified, and the 200 OK response is returned.
This log confirms that our middleware intercepted the request, found the valid payment hash, and allowed the request to proceed to the data.

In the world of crypto-payments, debugging is critical. Here are the common "vibekillers."
Symptom: The client crashes with a gas estimation error.
Solution: You are on Base Sepolia. Go to the Coinbase Faucet or Alchemy Faucet and drip some ETH into the wallet address defined in your .env.
Symptom: The server expects Base Sepolia, but the client is trying to sign for Ethereum Mainnet.
Solution: Ensure the chain object in the viem client setup matches the network string in the server config. X402 relies on Chain IDs to prevent cross-chain replay attacks.
Symptom: 429 Too Many Requests errors.
Solution: The default public RPCs for Base Sepolia can get congested. For a robust app, grab a free RPC URL from GoldRush/Covalent or another provider and pass it into the transport: http('YOUR_RPC_URL') configuration in client.js.
Don't just trust the console logs. Verify the blockchain state.
Copy the transaction hash from your console output.
Go to BaseScan Sepolia (sepolia.basescan.org).
Search the hash.
Verify the Value transfer matches the 0.001 ETH price.
Verify the From and To addresses match your .env configuration.
This on-chain verification is the "Receipt" of the Web3 world. It is immutable proof that your application successfully monetized a resource.
As we prepare for Part 2, let's harden our setup.
You don't have to hardcode 0.001 ETH. You can make the price dynamic based on the request body.
const dynamicPriceMiddleware = (req, res, next) => {
const resourceType = req.query.type;
const price = resourceType === 'premium' ? '0.01' : '0.001';
return paymentMiddleware({
...premiumContentConfig,
price: price
})(req, res, next);
};Rotation: Never reuse the private key from this tutorial for a mainnet wallet holding significant funds.
Facilitator: In production, you might run your own X402 facilitator node to verify transactions locally rather than trusting a public RPC, reducing latency and increasing trustlessness.
We have successfully built the Economic Layer of our application. We have a server that refuses to work for free, and a client willing to pay for value. This is the essence of a sustainable Web3 ecosystem.
However, right now, our server is just returning static text ("Base is booming"). To make this a truly valuable app worth paying for, we need Live Data. We need market movements, wallet activities, and token trends streamed in real-time.
In Part 2, we will integrate the GoldRush Streaming API. We will plug a firehose of blockchain data into our protected route, creating a "Pay-Per-View" terminal for DeFi intelligence.
Get your GoldRush API keys ready. The stream is about to open...