Payments

x402 payments

Implement paid API calls using the x402 protocol. Every request is paid for by the user with a micro payment onchain.

React

x402 Playground

Try out a x402 payment in our live playground

Client Side

wrapFetchWithPayment wraps the native fetch API to automatically handle 402 Payment Required responses from any API call. It will:

  • Make the initial request
  • If a 402 response is received, parse the payment requirements
  • Verify the payment amount is within the allowed maximum
  • Sign a payment authorization
  • Create a payment header using the provided wallet signature
  • Retry the request with the payment header

Here's an example:

import { wrapFetchWithPayment } from "thirdweb/x402";
import { createThirdwebClient } from "thirdweb";
import { createWallet } from "thirdweb/wallets";
const client = createThirdwebClient({ clientId: "your-client-id" });
const wallet = createWallet("io.metamask"); // or any other wallet
await wallet.connect({ client });
const fetchWithPay = wrapFetchWithPayment(fetch, client, wallet);
// Make a request that may require payment
const response = await fetchWithPay(
"https://api.example.com/paid-endpoint",
);

Server Side

To make your API calls payable, you can use the verifyPayment function in a simple middleware or in your endpoint directly.

Use the facilitator configuration function settle transactions with your thirdweb server wallet gaslessly and pass it to the verifyPayment function.

Here's an example with a Next.js middleware:

import { createThirdwebClient } from "thirdweb";
import { facilitator, verifyPayment } from "thirdweb/x402";
import { paymentMiddleware } from "x402-next";
const client = createThirdwebClient({ secretKey: "your-secret-key" });
const thirdwebX402Facilitator = facilitator({
client,
serverWalletAddress: "0xYourWalletAddress",
});
export async function middleware(request: NextRequest) {
const method = request.method.toUpperCase();
const resourceUrl = request.nextUrl.toString();
const paymentData = request.headers.get("X-PAYMENT");
const result = await verifyPayment({
resourceUrl,
method,
paymentData,
payTo: "0xYourWalletAddress",
network: "eip155:1", // or any other chain id in CAIP2 format: "eip155:<chain_id>"
price: "$0.01", // can also be a ERC20 token amount
routeConfig: {
description: "Access to paid content",
},
facilitator: thirdwebX402Facilitator,
});
if (result.status === 200) {
// payment successful, execute the request
const response = NextResponse.next();
// optionally set the response headers back to the client
for (const [key, value] of Object.entries(
result.responseHeaders,
)) {
response.headers.set(key, value);
}
return response;
}
// otherwise, request payment
return NextResponse.json(result.responseBody, {
status: result.status,
headers: result.responseHeaders,
});
}
// Configure which paths the middleware should run on
export const config = {
matcher: ["/api/paid-endpoint"],
};