http-x402
Implements the x402 payment protocol for API Gateway and Function URL handlers. On each request the middleware checks the payment-signature header, verifies it with a facilitator, runs the handler, then settles the payment on-chain. Returns HTTP 402 with payment requirements when no valid payment header is present.
After settlement, payer info is available via request.internal.x402 for downstream use (e.g. logging, rate-limiting per wallet).
Install
npm install --save @middy/http-x402 @x402/core Options
price(number) (required): Amount to charge in human-readable units (e.g.0.001for $0.001 USDC).payTo(string) (required): Wallet address that receives the payment.asset(string) (required): On-chain asset contract address (e.g. USDC on Base).FacilitatorClient(class) (defaultHTTPFacilitatorClientfrom@x402/core): Facilitator client class. Override for custom facilitators.facilitatorUrl(string) (default"https://x402.org/facilitator"): URL of the x402 facilitator service.decimals(integer) (default6): Asset decimal places used to convertpriceto on-chain units.network(string) (default"eip155:8453"): CAIP-2 chain ID. Default is Base mainnet.description(string) (default""): Human-readable description included in the payment requirements.mimeType(string) (default"application/json"): MIME type of the protected resource.human(function) (optional):(request) => boolean. Returntrueto bypass payment for this request (e.g. to let browser traffic through based onUser-Agent).
Sample usage
import middy from '@middy/core'
import httpX402 from '@middy/http-x402'
export const handler = middy()
.use(
httpX402({
price: 0.001,
payTo: '0xYourWalletAddress',
asset: '0xYourAssetAddress', // USDC on Base
}),
)
.handler(async (event, context) => {
return {
statusCode: 200,
body: JSON.stringify({ message: 'Paid content' }),
}
}) Bypass for browser traffic
import middy from '@middy/core'
import httpX402 from '@middy/http-x402'
export const handler = middy()
.use(
httpX402({
price: 0.001,
payTo: '0xYourWalletAddress',
asset: '0xYourAssetAddress',
human: (request) => {
const ua = request.event.headers?.['user-agent'] ?? ''
return /Mozilla|Chrome|Safari/.test(ua)
},
}),
)
.handler(async (event, context) => {
return { statusCode: 200, body: JSON.stringify({ message: 'Content' }) }
}) Internal storage
After a successful payment, the middleware stores settlement details in request.internal.x402:
payload: Decoded payment headerrequirements: Full payment requirements used for verificationpayer: Wallet address of the payer (available after settlement)transaction: Settlement transaction hashnetwork: Chain ID of the settlement
Bundling
Add @x402/core to your bundler’s external list if you include it as a Lambda layer, otherwise bundle it with your handler.