> For the complete documentation index, see [llms.txt](/llms.txt).

# Pay for an x402 API with Advanced Permissions

In this guide, you request [Advanced Permissions](/smart-accounts-kit/development/reference/glossary#advanced-permissions)**Advanced Permissions** Fine-grained, wallet execution permissions that dapps can request from MetaMask extension users. Based on ERC-7715. with a fixed ERC-20 allowance to pay for a specific x402-protected resource.

## Prerequisites[​](#prerequisites "Direct link to Prerequisites")

- [Install and set up the Smart Accounts Kit.](/smart-accounts-kit/get-started/install/)

## Steps[​](#steps "Direct link to Steps")

### 1\. Set up a Wallet Client[​](#1-set-up-a-wallet-client "Direct link to 1. Set up a Wallet Client")

Set up a Wallet Client using Viem's [createWalletClient](https://viem.sh/docs/clients/wallet) function. Use this client to interact with MetaMask.

Extend the Wallet Client with `erc7715ProviderActions` to enable [Advanced Permissions](/smart-accounts-kit/development/reference/glossary#advanced-permissions)**Advanced Permissions** Fine-grained, wallet execution permissions that dapps can request from MetaMask extension users. Based on ERC-7715. requests.

```
import { createWalletClient, custom } from 'viem'
import { erc7715ProviderActions } from '@metamask/smart-accounts-kit/actions'

const walletClient = createWalletClient({
  transport: custom(window.ethereum),
}).extend(erc7715ProviderActions())

```

### 2\. Set up a session account[​](#2-set-up-a-session-account "Direct link to 2. Set up a session account")

Set up a session account. The requested permissions are granted to the session account, which is responsible for making x402 API calls.

The session account can be either a [smart account](/smart-accounts-kit/development/reference/glossary#metamask-smart-account)**MetaMask smart account** A smart contract account created using the Smart Accounts Kit that supports programmable behavior, flexible signing options, and ERC-7710 delegations. or an [EOA](/smart-accounts-kit/development/reference/glossary#externally-owned-account-eoa)**Externally owned account (EOA)** A private-key-controlled account with no built-in programmable execution logic.. This example uses an EOA as the session account.

```
import { privateKeyToAccount } from 'viem/accounts'
import { sepolia as chain } from 'viem/chains'
import { createWalletClient, http } from 'viem'

const sessionAccount = privateKeyToAccount('0x...')

```

### 3\. Get payment requirements[​](#3-get-payment-requirements "Direct link to 3. Get payment requirements")

Call the protected API route once without the `PAYMENT-SIGNATURE` header.

The server returns `402` with the payment terms (`PAYMENT-REQUIRED`) in the response, which you use to build the payment payload.

- example.ts
- types.ts

```
import { PaymentRequirements } from './types'

// Update the URL
const challengeResponse = await fetch('https://api.example.com/paid-endpoint')
if (challengeResponse.status !== 402) {
  console.error('Expected 402 challenge from protected route')
  // Handle error
}

const paymentRequiredHeader = challengeResponse.headers.get('PAYMENT-REQUIRED')
if (!paymentRequiredHeader) {
  console.error('PAYMENT-REQUIRED header is missing')
  // Handle error
}

const decodedPaymentRequired = Buffer.from(paymentRequiredHeader, 'base64').toString('utf-8')
const paymentRequired = JSON.parse(decodedPaymentRequired) as {
  accepts: PaymentRequirements[]
}

const accepted = paymentRequired.accepts[0]
if (!accepted) {
  console.error('Server did not provide accepted payment requirements')
  // Handle error
}

if (accepted.extra.assetTransferMethod !== 'erc7710') {
  console.error('Server does not support ERC-7710 delegation payments')
  // Handle error
}

```

```
import { Address } from 'viem'

export type PaymentRequirements = {
  scheme: string
  network: string
  amount: string
  asset: Address
  payTo: Address
  maxTimeoutSeconds: number
  extra: {
    assetTransferMethod: string
    facilitators?: Address[]
  }
}

```

### 4\. Request Advanced Permissions[​](#4-request-advanced-permissions "Direct link to 4. Request Advanced Permissions")

Request Advanced Permissions from the user with the Wallet Client's `requestExecutionPermissions` action.

In this example, you request an ERC-20 allowance permission with a fixed allowance equal to the resource cost. Use the [redeemer](/smart-accounts-kit/reference/advanced-permissions/rules/#redeemer) rule to restrict redemption to facilitator addresses from the payment requirements.

See the [requestExecutionPermissions](/smart-accounts-kit/reference/advanced-permissions/wallet-client/#requestexecutionpermissions) API reference for more information.

```
import { base as chain } from 'viem/chains'

const facilitators = accepted.extra.facilitators
if (!facilitators || facilitators.length === 0) {
  console.error('No facilitators found in PAYMENT-REQUIRED')
  // Handle error
}

const currentTime = Math.floor(Date.now() / 1000)
const expiry = currentTime + 3600

const grantedPermissions = await walletClient.requestExecutionPermissions([
  {
    chainId: chain.id,
    expiry,
    to: sessionAccount.address,
    permission: {
      type: 'erc20-token-allowance',
      data: {
        tokenAddress: accepted.asset,
        // Fixed allowance for this resource.
        allowanceAmount: BigInt(accepted.amount),
        justification: 'Permission to pay for a specific x402-protected API resource',
      },
      isAdjustmentAllowed: false,
    },
    rules: [
      {
        type: 'redeemer',
        data: {
          addresses: facilitators!,
        },
      },
    ],
  },
])

```

### 5\. Create a redelegation[​](#5-create-a-redelegation "Direct link to 5. Create a redelegation")

The granted advanced permission is delegated to the session account. To let facilitator addresses redeem this permission context for x402 settlement, create an [open redelegation](/smart-accounts-kit/development/reference/glossary#open-redelegation)**Open redelegation** A redelegation with no specific delegate, allowing any account to redeem inherited permissions. from the session account.

Use the Wallet Client's [redelegatePermissionContextOpen](/smart-accounts-kit/reference/erc7710/wallet-client/#redelegatepermissioncontextopen)action to create a redelegated permission context. The granted permission already includes a [redeemer enforcer](/smart-accounts-kit/reference/delegation/caveats/#redeemer), so you do not add extra caveats here.

- example.ts
- config.ts

```
import { environment, sessionAccountWalletClient } from './config.ts'

const permission = grantedPermissions[0]
if (!permission) {
  console.error('No permission response returned by requestExecutionPermissions')
  // Handle error
}

const { permissionContext: redelegatedPermissionContext } =
  await sessionAccountWalletClient.redelegatePermissionContextOpen({
    environment,
    permissionContext: permission!.context,
  })

```

```
import { createWalletClient, http } from 'viem'
import { base as chain } from 'viem/chains'
import { getSmartAccountsEnvironment } from '@metamask/smart-accounts-kit'
import { erc7710WalletActions } from '@metamask/smart-accounts-kit/actions'
import { sessionAccount } from './session-account.ts'

export const environment = getSmartAccountsEnvironment(chain.id)

export const sessionAccountWalletClient = createWalletClient({
  account: sessionAccount,
  chain,
  transport: http(),
}).extend(erc7710WalletActions())

```

### 6\. Create the payment payload[​](#6-create-the-payment-payload "Direct link to 6. Create the payment payload")

Create a payment payload using the redelegated permission context and accepted requirements. For ERC-7710 (Smart Contract Delegation), x402 requires the payload fields `delegationManager`, `permissionContext`, and `delegator`. The facilitator uses `permissionContext` to simulate during verification and then settle the payment.

Encode the full x402 payment payload as base64, then send it in the `PAYMENT-SIGNATURE` header.

- example.ts
- types.ts

```
import { PaymentPayload } from './types'

const permission = grantedPermissions[0]

const paymentPayload: PaymentPayload = {
  x402Version: 2,
  accepted,
  payload: {
    delegationManager: permission.delegationManager,
    permissionContext: redelegatedPermissionContext,
    delegator: permission.from,
  },
}

const encodedPayment = Buffer.from(JSON.stringify(paymentPayload)).toString('base64')

```

```
import { Address, Hex } from 'viem'

export type PaymentPayload = {
  x402Version: 2
  accepted: PaymentRequirements
  payload: {
    delegationManager: Address
    permissionContext: Hex
    delegator: Address
  }
}

```

### 7\. Make the paid request[​](#7-make-the-paid-request "Direct link to 7. Make the paid request")

Send the base64-encoded x402 payment payload in the `PAYMENT-SIGNATURE` header. If verification succeeds, the server returns the protected data.

```
const apiResponse = await fetch('https://api.example.com/paid-endpoint', {
  headers: {
    'PAYMENT-SIGNATURE': encodedPayment,
  },
})

if (!apiResponse.ok) {
  const errorBody = await apiResponse.json()
  console.error(errorBody.error ?? 'API request failed')
  // Handle error
}

const data = await apiResponse.json()
console.log('Protected API response:', data)

```
