x402 Paywall Reference
Detailed API reference for @x402-avm/paywall and framework middleware packages.
Package: @x402-avm/paywall
Installation
npm install @x402-avm/paywall @x402-avm/avm @x402-avm/core
Exports from @x402-avm/paywall
| Export |
Type |
Description |
createPaywall |
Function |
Creates a new PaywallBuilder instance |
PaywallBuilder |
Class |
Builder for configuring and building paywall providers |
avmPaywall |
Object |
AVM network handler (algorand:*) |
evmPaywall |
Object |
EVM network handler (eip155:*) |
svmPaywall |
Object |
SVM network handler (solana:*) |
PaywallProvider |
Type |
Interface for paywall HTML generation |
PaywallConfig |
Type |
Configuration options for paywall branding |
PaywallNetworkHandler |
Type |
Interface for network-specific handlers |
PaymentRequired |
Type |
402 response structure |
PaymentRequirements |
Type |
Individual payment requirement |
Exports from @x402-avm/paywall/avm
| Export |
Type |
Description |
avmPaywall |
Object |
AVM paywall handler (same as main export) |
PaywallBuilder
createPaywall()
Factory function that creates a new PaywallBuilder instance.
function createPaywall(): PaywallBuilder;
PaywallBuilder Methods
| Method |
Signature |
Description |
.withNetwork(handler) |
(handler: PaywallNetworkHandler) => PaywallBuilder |
Register a network-specific paywall handler. Order matters -- first match wins. |
.withConfig(config) |
(config: PaywallConfig) => PaywallBuilder |
Set default paywall configuration. |
.build() |
() => PaywallProvider |
Build and return a PaywallProvider. |
PaywallProvider
interface PaywallProvider {
/**
* Generate an HTML paywall page for the given payment requirements.
* @param paymentRequired - The full 402 response from the server
* @param config - Optional runtime config override
* @returns Full HTML page as a string
*/
generateHtml(paymentRequired: PaymentRequired, config?: PaywallConfig): string;
}
PaywallConfig
interface PaywallConfig {
/** App name shown in wallet connection modal title */
appName?: string;
/** App logo URL shown in the paywall header */
appLogo?: string;
/** URL of the content being accessed (used for retry after payment) */
currentUrl?: string;
/** Whether to use testnet (default: true) */
testnet?: boolean;
}
PaywallNetworkHandler
Interface for creating custom network-specific paywall handlers.
interface PaywallNetworkHandler {
/**
* Check if this handler supports the given payment requirement.
* @param requirement - A single payment requirement from the 402 response
* @returns true if this handler can generate HTML for this requirement
*/
supports(requirement: PaymentRequirements): boolean;
/**
* Generate the full HTML paywall page.
* @param requirement - The matched payment requirement
* @param paymentRequired - The full PaymentRequired response
* @param config - Paywall configuration
* @returns Full HTML page as a string
*/
generateHtml(
requirement: PaymentRequirements,
paymentRequired: PaymentRequired,
config: PaywallConfig,
): string;
}
Built-in Handlers
| Handler |
Supports |
Networks |
avmPaywall |
network.startsWith("algorand:") |
Algorand Testnet, Algorand Mainnet |
evmPaywall |
network.startsWith("eip155:") |
Base, Ethereum, etc. |
svmPaywall |
network.startsWith("solana:") |
Solana |
Handler Selection
When PaywallProvider.generateHtml() is called, it iterates through registered handlers in order. The first handler whose supports() returns true for any of the accepts requirements is used to generate the HTML.
avmPaywall Handler
The avmPaywall handler generates a full React-based HTML page with:
- window.x402 global -- Embeds payment configuration for the client-side app
- Wallet discovery -- Uses
@wallet-standard/app to find Algorand wallets
- Wallet selection UI -- Dropdown with icons for detected wallets
- Balance checking -- Reads USDC ASA balance for the connected account
- Transaction signing -- Uses
algorand:signTransaction wallet-standard feature
- Payment submission -- Retries original request with
PAYMENT-SIGNATURE header
- Automatic redirect -- Redirects to paid content after successful payment
Supported Wallets
| Wallet |
Type |
Feature |
| Pera Wallet |
Mobile + WalletConnect |
algorand:signTransaction |
| Defly Wallet |
Mobile + WalletConnect |
algorand:signTransaction |
| Lute Wallet |
Browser Extension |
algorand:signTransaction |
window.x402 Configuration Object
The generated HTML page injects this configuration:
window.x402 = {
amount: 0.01, // Amount in USDC (human-readable)
paymentRequired: {...}, // Full PaymentRequired response
testnet: true, // Network mode
currentUrl: "...", // URL to retry after payment
config: { chainConfig: {} },
appName: "My App",
appLogo: "https://...",
};
Framework Middleware
@x402-avm/express
| Function |
Signature |
Description |
paymentMiddleware |
(routes, server, config?, paywall?) |
Express middleware |
paymentMiddlewareFromHTTPServer |
(httpServer, config?, paywall?) |
Express middleware from HTTP server |
paymentMiddlewareFromConfig |
(routes, facilitator?, schemes?, config?, paywall?) |
Express middleware from config |
x402ResourceServer |
Class |
Resource server for facilitator communication |
x402HTTPResourceServer |
Class |
HTTP-aware resource server with route config |
@x402-avm/hono
| Function |
Signature |
Description |
paymentMiddleware |
(routes, server, config?, paywall?) |
Hono middleware |
paymentMiddlewareFromHTTPServer |
(httpServer, config?, paywall?) |
Hono middleware from HTTP server |
paymentMiddlewareFromConfig |
(routes, facilitator?, schemes?, config?, paywall?) |
Hono middleware from config |
x402ResourceServer |
Class |
Resource server for facilitator communication |
@x402-avm/next
| Function |
Signature |
Description |
paymentProxy |
(routes, server, config?, paywall?) |
Next.js middleware proxy |
withX402 |
(handler, routeConfig, server, config?, paywall?) |
Next.js route wrapper |
paymentProxyFromHTTPServer |
(httpServer, config?, paywall?) |
Next.js proxy from HTTP server |
paymentProxyFromConfig |
(routes, facilitator?, schemes?, config?, paywall?) |
Next.js proxy from config |
x402ResourceServer |
Class |
Resource server for facilitator communication |
Route Configuration
interface RouteConfig {
[path: string]: {
/** Payment requirements -- single object or array for multi-network */
accepts: PaymentAccepts | PaymentAccepts[];
/** Human-readable description of the resource */
description: string;
/** MIME type of the response */
mimeType: string;
};
}
interface PaymentAccepts {
/** Payment scheme (currently "exact") */
scheme: string;
/** CAIP-2 network identifier */
network: string;
/** Asset identifier (ASA ID for Algorand, contract address for EVM) */
asset: string;
/** Receiver address */
payTo: string;
/** Price string (e.g., "$0.01") */
price: string;
/** Maximum timeout in seconds for payment validity */
maxTimeoutSeconds: number;
}
Bundle Sizes
The paywall system is designed for tree-shaking. Import only the network handlers you need:
// AVM only -- smallest bundle
import { avmPaywall } from "@x402-avm/paywall/avm";
// AVM + EVM
import { avmPaywall, evmPaywall } from "@x402-avm/paywall";
// All networks
import { avmPaywall, evmPaywall, svmPaywall } from "@x402-avm/paywall";
USDC Asset IDs
| Network |
ASA ID |
CAIP-2 |
| Algorand Testnet |
10458941 |
algorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI= |
| Algorand Mainnet |
31566704 |
algorand:wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8= |
Testing
Testing the Paywall HTML Generation
import { createPaywall, avmPaywall } from "@x402-avm/paywall";
const paywall = createPaywall()
.withNetwork(avmPaywall)
.withConfig({ appName: "Test App", testnet: true })
.build();
const html = paywall.generateHtml({
x402Version: 2,
accepts: [{
scheme: "exact",
network: "algorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=",
asset: "10458941",
payTo: "TEST_ADDRESS",
amount: "10000",
maxTimeoutSeconds: 300,
}],
resource: {
url: "https://test.example.com/premium",
description: "Test content",
mimeType: "application/json",
},
});
// Verify the HTML contains expected elements
console.assert(html.includes("window.x402"));
console.assert(html.includes("Test App"));
Testing Middleware Integration
# Start server
npm start
# Test JSON 402 response (API client)
curl -H "Accept: application/json" http://localhost:3000/api/premium
# Test HTML paywall (browser-like)
curl -H "Accept: text/html" http://localhost:3000/api/premium
# Test with payment header (after obtaining one)
curl -H "PAYMENT-SIGNATURE: <base64-payload>" http://localhost:3000/api/premium
Important Notes
- The paywall HTML page is a self-contained React application served inline. No additional static files or CDN dependencies are required.
withNetwork() order determines handler priority. Register your preferred network first.
- The
testnet flag in PaywallConfig affects which Algod endpoint the paywall page connects to (AlgoNode testnet vs mainnet).
- Route paths support Express-style patterns (
:param, * wildcards).
- The
price field in route config accepts human-readable strings like "$0.01" which are converted to microunits internally.
External Resources