Skip to main content
This guide walks through building a client that can automatically pay for x402-protected resources on Abstract. The facilitator supports any ERC-3009-capable token — the examples below use USDC.
  • A wallet with USDC on Abstract (mainnet or testnet).
  • Node.js 18+, Go 1.21+, or Python 3.10+ installed.

1. Install the client SDK

npm install @x402/fetch @x402/core @x402/evm viem

2. Create a wallet signer

The signer authorizes payment transactions from your wallet.
import { privateKeyToAccount } from "viem/accounts";

const signer = privateKeyToAccount(
  process.env.PRIVATE_KEY as `0x${string}`
);

3. Make paid requests

Wrap your HTTP client with x402 payment support. The wrapper automatically detects 402 responses, signs a payment with your wallet, and retries the request.
import { wrapFetchWithPayment } from "@x402/fetch";
import { x402Client } from "@x402/core/client";
import { ExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";

const signer = privateKeyToAccount(
  process.env.PRIVATE_KEY as `0x${string}`
);

const client = new x402Client();
client.register("eip155:*", new ExactEvmScheme(signer));

const fetchWithPayment = wrapFetchWithPayment(fetch, client);

const response = await fetchWithPayment(
  "https://api.example.com/weather",
  { method: "GET" },
);

const data = await response.json();
console.log("Response:", data);

How it works under the hood

The x402 client wrapper handles the full payment flow transparently:
  1. Your code makes a normal HTTP request.
  2. If the server responds with 402 Payment Required, the wrapper reads the payment requirements from the response headers.
  3. The wrapper uses your registered scheme and signer to create a signed payment payload.
  4. The request is retried with the payment attached in a PAYMENT-SIGNATURE header.
  5. The server verifies the payment (via the facilitator) and returns the resource.
From your code’s perspective, the request looks like any other HTTP call — the payment happens automatically.

Error handling

try {
  const response = await fetchWithPayment(url, { method: "GET" });
} catch (error) {
  if (error.message.includes("No scheme registered")) {
    console.error("Network not supported — register the appropriate scheme");
  } else if (error.message.includes("Payment already attempted")) {
    console.error("Payment failed on retry");
  } else {
    console.error("Request failed:", error);
  }
}

Next steps