Create an x402 server with ERC-7710
In this guide, you build a Node.js server that charges for HTTP API access using x402 and accepts ERC-7710 delegation payments verified through the MetaMask facilitator.
You use the official @x402/express middleware with a custom ERC-7710 scheme that routes
verification and settlement through the MetaMask facilitator.
Prerequisites
- Node.js 18 or later.
- A Node.js Express server.
- A seller payout address to receive funds (for example, a MetaMask wallet address).
Steps
1. Install the dependencies
- npm
- Yarn
- pnpm
- Bun
npm install @x402/core @x402/evm @x402/express cors express
yarn add @x402/core @x402/evm @x402/express cors express
pnpm add @x402/core @x402/evm @x402/express cors express
bun add @x402/core @x402/evm @x402/express cors express
2. Create the ERC-7710 scheme
Create a custom scheme that extends ExactEvmScheme from @x402/evm to add ERC-7710
delegation support.
The scheme overrides enhancePaymentRequirements to set assetTransferMethod to erc7710
and include the facilitator addresses so buyers can scope their delegation to a specific
set of facilitators before creating the payment payload.
import { ExactEvmScheme } from '@x402/evm/exact/server'
import type { PaymentRequirements, SupportedKind } from '@x402/core/types'
import type { FacilitatorClient } from '@x402/core/server'
export class Erc7710ExactEvmScheme extends ExactEvmScheme {
constructor(private readonly facilitatorClient: FacilitatorClient) {
super()
}
async enhancePaymentRequirements(
paymentRequirements: PaymentRequirements,
supportedKind: SupportedKind,
facilitatorExtensions: string[]
): Promise<PaymentRequirements> {
const enhanced = await super.enhancePaymentRequirements(
paymentRequirements,
supportedKind,
facilitatorExtensions
)
const supported = await this.facilitatorClient.getSupported()
const facilitators = [
...(supported.signers[paymentRequirements.network] ?? []),
...(supported.signers['eip155:*'] ?? []),
]
return {
...enhanced,
extra: {
...enhanced.extra,
assetTransferMethod: 'erc7710',
facilitators,
},
}
}
}
3. Configure the server
Set up the Express server with the x402 paymentMiddleware and the custom ERC-7710 scheme.
The paymentMiddleware intercepts requests to protected routes and handles the full x402 payment
flow, including requirements advertisement, verification, and settlement.
In this example, you create a protected GET /api/hello endpoint that charges 0.01 USDC on
Base mainnet.
Replace the payout address in src/config.ts with your own seller wallet address.
- src/index.ts
- src/config.ts
import express, { type Request, type Response } from 'express'
import cors from 'cors'
import { paymentMiddleware } from '@x402/express'
import { x402ResourceServer } from '@x402/core/server'
import { Erc7710ExactEvmScheme } from './scheme.js'
import { NETWORK_ID, PORT, payToAddress, facilitatorClient } from './config.js'
const app = express()
app.use(cors({ exposedHeaders: ['PAYMENT-REQUIRED', 'PAYMENT-RESPONSE'] }))
app.use(
paymentMiddleware(
{
'GET /api/hello': {
accepts: [
{
scheme: 'exact',
price: '$0.01',
network: NETWORK_ID,
payTo: payToAddress,
},
],
description: 'Access to protected resource',
mimeType: 'application/json',
},
},
new x402ResourceServer(facilitatorClient).register(
NETWORK_ID,
new Erc7710ExactEvmScheme(facilitatorClient)
)
)
)
app.get('/api/hello', (_req: Request, res: Response) => {
res.json({ message: 'Hello!' })
})
app.listen(PORT, () => {
console.log(`[seller] Server running on http://localhost:${PORT}`)
})
import { HTTPFacilitatorClient } from '@x402/core/server'
export const NETWORK_ID = 'eip155:8453'
export const PORT = 4402
// Replace with your seller payout address.
export const payToAddress = '0x<PAY_TO_ADDRESS>'
// MetaMask facilitator base URL for x402 on Base mainnet.
export const facilitatorClient = new HTTPFacilitatorClient({
url: 'https://tx-sentinel-base-mainnet.dev-api.cx.metamask.io/platform/v2/x402',
})
Next steps
- Learn more about ERC-7710 delegation.
- See the x402 ERC-7710 specification.