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.001 for $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) (default HTTPFacilitatorClient from @x402/core): Facilitator client class. Override for custom facilitators.
  • facilitatorUrl (string) (default "https://x402.org/facilitator"): URL of the x402 facilitator service.
  • decimals (integer) (default 6): Asset decimal places used to convert price to 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. Return true to bypass payment for this request (e.g. to let browser traffic through based on User-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 header
  • requirements: Full payment requirements used for verification
  • payer: Wallet address of the payer (available after settlement)
  • transaction: Settlement transaction hash
  • network: 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.