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 methods
  • scheme - 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 address
  • asset - 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?

  1. Client requested /weather without payment
  2. Server returned 402 Payment Required with payment details
  3. Client created a signed payment payload
  4. FareSide facilitator verified the payment on-chain
  5. Server delivered the weather data

The payment goes directly to your wallet.

Next Steps