For AI agents: a documentation index is available at /llms.txt. A markdown version of this page is available at the same URL with .md appended (or via Accept: text/markdown).
Skip to main content

Pay for an x402 API with delegation

In this guide, you use a buyer account to access API data from an x402 server by creating an open delegation that authorizes token transfers on your behalf.

You set up an x402Erc7710Client with a delegation provider, register it with the x402 client, and use wrapFetchWithPayment to automatically handle payment when calling a protected API route.

Prerequisites

Steps

1. Install the dependencies

npm install @x402/core @x402/fetch @metamask/x402

2. Create a buyer account

Create an account to represent the buyer, the delegatorDelegator account The account that creates and signs a delegation to grant limited authority to another account. who creates a delegation.

The delegator must be a MetaMask smart accountMetaMask smart account A smart contract account created using the Smart Accounts Kit that supports programmable behavior, flexible signing options, and ERC-7710 delegations.. Use the toolkit's toMetaMaskSmartAccount method to create the buyer account.

Important

Fund the smart account with USDC for the requested payment.

import { Implementation, toMetaMaskSmartAccount } from '@metamask/smart-accounts-kit'
import { publicClient, buyerAccount } from './config'

export const buyerSmartAccount = await toMetaMaskSmartAccount({
client: publicClient,
implementation: Implementation.Hybrid,
deployParams: [buyerAccount.address, [], [], []],
deploySalt: '0x',
signer: { account: buyerAccount },
})

3. Create an x402 ERC-7710 client

Create an x402Erc7710Client with a delegationProvider callback. The x402 client calls this function automatically when it needs to pay for a request, passing in the payment requirements from the server.

Inside the provider, create an open delegation using createOpenDelegation. This example uses the erc20TransferAmount scope to allow USDC transfers up to the requested amount, and the timestamp caveat to set a short expiry.

For ERC-7710, x402 requires the payload fields delegationManager, permissionContext, and delegator. Use encodeDelegations to encode the delegation chain.

import { CaveatType, createOpenDelegation, ScopeType } from '@metamask/smart-accounts-kit'
import { encodeDelegations } from '@metamask/smart-accounts-kit/utils'
import { x402Erc7710Client } from '@metamask/x402'
import { getAddress } from 'viem'

const erc7710Client = new x402Erc7710Client({
delegationProvider: async requirements => {
// Expires in 1 minute.
const expiry = Math.floor(Date.now() / 1000) + 60

const delegation = createOpenDelegation({
environment: buyerSmartAccount.environment,
from: buyerSmartAccount.address,
scope: {
type: ScopeType.Erc20TransferAmount,
tokenAddress: getAddress(requirements.asset),
maxAmount: BigInt(requirements.amount),
},
caveats: [
{
type: CaveatType.Timestamp,
afterThreshold: 0,
beforeThreshold: expiry,
},
],
})

const signature = await buyerSmartAccount.signDelegation({
delegation,
})

const signedDelegation = {
...delegation,
signature,
}

return {
delegationManager: buyerSmartAccount.environment.DelegationManager,
permissionContext: encodeDelegations([signedDelegation]),
delegator: buyerSmartAccount.address,
}
},
})

4. Register the client

Register the ERC-7710 client with the x402 core client for all EVM networks. Create an HTTP client and a payment-aware fetch function using wrapFetchWithPayment.

import { x402Client, x402HTTPClient } from '@x402/core/client'
import { wrapFetchWithPayment } from '@x402/fetch'

const coreClient = new x402Client().register('eip155:*', erc7710Client)
const httpClient = new x402HTTPClient(coreClient)

const fetchWithPayment = wrapFetchWithPayment(fetch, httpClient)

5. Make the paid request

Call the protected endpoint using fetchWithPayment. It handles the x402 payment flow, calling your delegationProvider to create an open redelegation when the server returns a 402 response.

const paidResponse = await fetchWithPayment('https://api.example.com/paid-endpoint', {
method: 'GET',
})