Getting Started • 5 min read
Quickstart
Accept your first x402 payment in 5 minutes
Prerequisites
- Node.js 18+ or Rust 1.80+
- A wallet address to receive payments
- Your FareSide API key (join the waitlist if you don’t have one)
Choose Your Stack
The examples below use Hono (TypeScript) and Axum (Rust) for illustration. x402 is a protocol. While Express, Hono, Next.js, Axum are supported out of the box, adding x402-payment-gating to any other framework or language is relatively straightforward.
TypeScript (Hono)
Step 1: Install Dependencies
npm install hono x402-hono @hono/node-server tsx
Step 2: Create Your Server
import { Hono } from "hono";
import { serve } from "@hono/node-server";
import { paymentMiddleware } from "x402-hono";
const app = new Hono();
// Configure payment middleware with FareSide facilitator
app.use(
paymentMiddleware(
"0xYourWalletAddress", // Your receiving wallet
{
"/weather": {
price: "$0.01",
network: "base-sepolia",
config: {
description: "Weather API access",
},
},
},
{
url: "https://facilitator.fareside.com/YOUR_API_KEY",
},
),
);
// Your paid endpoint
app.get("/weather", (c) => {
return c.json({
location: "San Francisco",
temperature: 68,
conditions: "Sunny",
});
});
serve({ fetch: app.fetch, port: 3000 });
console.log("Server running on http://localhost:3000");
Step 3: Test It
Start your server:
npx tsx server.ts
Make a request without payment:
curl http://localhost:3000/weather
You’ll get a 402 Payment Required response with payment instructions:
{
"error": "X-PAYMENT header is required",
"accepts": [
{
"scheme": "exact",
"network": "base-sepolia",
"maxAmountRequired": "10000",
"resource": "http://localhost:3000/weather",
"description": "Weather API access",
"mimeType": "application/json",
"payTo": "0xYourWalletAddress",
"maxTimeoutSeconds": 300,
"asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
"outputSchema": {
"input": {
"type": "http",
"method": "GET",
"discoverable": true
}
},
"extra": {
"name": "USDC",
"version": "2"
}
}
],
"x402Version": 1
}
Key fields in the response:
accepts- Array of accepted payment methodsscheme- Payment scheme (e.g., “exact” for exact amount)network- Blockchain network (e.g., “base-sepolia”)maxAmountRequired- Amount in smallest units (10000 = $0.01 USDC)payTo- Your wallet addressasset- Token contract address (USDC on Base Sepolia)x402Version- Protocol version
Rust (Axum)
Step 1: Add Dependencies
[dependencies]
x402-rs = "0.10"
x402-axum = "0.6"
axum = "0.8"
tokio = "1"
serde_json = "1"
Step 2: Create Your Server
use axum::{routing::get, Router};
use axum::http::StatusCode;
use axum::response::IntoResponse;
use serde_json::json;
use x402_axum::{IntoPriceTag, X402Middleware};
use x402_rs::network::{Network, USDCDeployment};
use x402_rs::address_evm;
#[tokio::main]
async fn main() {
// Configure FareSide facilitator
let x402 = X402Middleware::try_from(
"https://facilitator.fareside.com/YOUR_API_KEY"
).unwrap();
// Configure USDC on Base Sepolia with your receiving address
let usdc = USDCDeployment::by_network(Network::BaseSepolia)
.pay_to(address_evm!("0xYourWalletAddress"));
let app = Router::new()
.route("/weather", get(weather_handler).layer(
x402.with_description("Weather API access")
.with_mime_type("application/json")
.with_price_tag(usdc.amount(0.01).unwrap())
));
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
println!("Server running on http://localhost:3000");
axum::serve(listener, app).await.unwrap();
}
async fn weather_handler() -> impl IntoResponse {
(StatusCode::OK, axum::Json(json!({
"location": "San Francisco",
"temperature": 68,
"conditions": "Sunny"
})))
}
Step 3: Test It
cargo run
curl http://localhost:3000/weather
You’ll get a 402 Payment Required response:
{
"error": "X-PAYMENT header is required",
"accepts": [
{
"scheme": "exact",
"network": "base-sepolia",
"maxAmountRequired": "10000",
"resource": "http://localhost/weather",
"description": "Weather API access",
"mimeType": "application/json",
"payTo": "0xYourWalletAddress",
"maxTimeoutSeconds": 300,
"asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
"extra": {
"name": "USDC",
"version": "2"
}
}
],
"x402Version": 1
}
Making a Payment (Client Side)
To actually pay for the endpoint, you need an x402-compatible client. Here’s how to test with x402-fetch:
npm install x402-fetch viem
import { privateKeyToAccount } from "viem/accounts";
import { wrapFetchWithPayment, decodeXPaymentResponse } from "x402-fetch";
// Create a wallet from your private key (never hardcode real keys!)
const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
// Wrap fetch with automatic payment handling
// The third parameter is the max amount in smallest units (1000000 = $1 USDC)
const fetchWithPayment = wrapFetchWithPayment(fetch, account, 1000000n);
// Make a request - payments are handled automatically!
fetchWithPayment("http://localhost:3000/weather", { method: "GET" })
.then(async (response) => {
const data = await response.json();
console.log("Weather:", data);
// Optionally decode the payment response header
const paymentResponse = decodeXPaymentResponse(
response.headers.get("x-payment-response")!,
);
console.log("Payment:", paymentResponse);
})
.catch((error) => {
console.error("Error:", error);
});
For more details, see the Making Payments guide.
What Just Happened?
- Client requested
/weatherwithout payment - Server returned
402 Payment Requiredwith payment details - Client created a signed payment payload
- FareSide facilitator verified the payment on-chain
- Server delivered the weather data
The payment goes directly to your wallet.
Next Steps
- Setup Guide - Get your FareSide API key
- Hono/Express Integration - Detailed TypeScript examples
- Rust (Axum) Integration - Detailed Rust examples
- Making Payments - Build x402 clients
- Supported Networks - Available chains and tokens