> **Can't find what you're looking for?** Use `search_docs` on the docs MCP server at `https://mpp.dev/api/mcp` to find what you need.

# Next.js \[Payment middleware for Next.js]

## Choose a signing account

### Direct

Create a server-only wallet.ts module, then import account wherever an example creates a local signing account.

```ts
import { privateKeyToAccount } from 'viem/accounts'

export const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`)
```

### Privy

Create an EVM wallet in Privy, fund it with the required currency on this page's network, and keep PRIVY\_APP\_SECRET server-side.

```bash
pnpm add @privy-io/node
```

Create a server-only privy.ts module, then import its account wherever an example configures account or feePayer.

```ts
import { PrivyClient } from '@privy-io/node'
import { createViemAccount } from '@privy-io/node/viem'

const privy = new PrivyClient({
  appId: process.env.PRIVY_APP_ID!,
  appSecret: process.env.PRIVY_APP_SECRET!,
})

export const account = createViemAccount(privy, {
  address: process.env.PRIVY_WALLET_ADDRESS as `0x${string}`,
  walletId: process.env.PRIVY_WALLET_ID!,
})
```

createViemAccount delegates signatures to the Privy wallet, so it replaces any local viem account in the examples on this page.

Native [Next.js](https://nextjs.org) route handler wrapper that gates routes behind payment intents.

## Install

:::code-group
```bash [npm]
$ npm install mppx
```

```bash [pnpm]
$ pnpm add mppx
```

```bash [bun]
$ bun add mppx
```
:::

## Usage

Import `Mppx` and `tempo` from `mppx/nextjs` to create a Next.js-aware payment handler. Each intent (for example, `charge`) returns a wrapper that accepts a route handler.

```ts twoslash [app/api/premium/route.ts]
import { Mppx, tempo } from 'mppx/nextjs'

const mppx = Mppx.create({ methods: [tempo.charge()] }) // [!code hl]

export const GET = 
  mppx.charge({ amount: '1' }) // [!code hl]
  (() => Response.json({ data: 'paid content' }))
```

### Session payments

Use `mppx.session()` with `tempo.session()` to gate routes behind current v2 Sessions.

```ts twoslash [app/api/content/route.ts]
import { Store } from 'mppx'
import { Mppx, tempo } from 'mppx/nextjs'
import { privateKeyToAccount } from 'viem/accounts'

const account = privateKeyToAccount('0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef')

const mppx = Mppx.create({
  methods: [
    tempo.session({
      account,
      chainId: 4217,
      currency: '0x20c0000000000000000000000000000000000000', // pathUSD on Tempo
      store: Store.memory(),
    }),
  ],
})

export const GET =
  mppx.session({ amount: '1', unitType: 'token' })
  (() => Response.json({ data: 'session content' }))
```

### Identifying the payer

After the handler verifies payment, the `Authorization` header is still on the request. Parse it with `Credential.deserialize` to read the payer's identity from the `source` field—a DID such as `did:pkh:eip155:1:0x...`.

```ts twoslash [app/api/premium/route.ts]
import { Credential } from 'mppx'
import { Mppx, tempo } from 'mppx/nextjs'

const mppx = Mppx.create({ methods: [tempo.charge()] })

export const GET =
  mppx.charge({ amount: '1' })
  ((request) => {
    const credential = Credential.deserialize(request.headers.get('Authorization')!)
    const payer = credential.source // "did:pkh:eip155:1:0x..."
    return Response.json({ payer })
  })
```

## x402-compatible clients

Next.js route handlers, including routes deployed on Vercel, can serve MPP and x402 clients from the same endpoint when you register [`evm.charge`](/payment-methods/evm/charge) with `x402.facilitator`.

```ts [app/api/paid/route.ts]
import { Mppx, evm } from 'mppx/nextjs'

const mppx = Mppx.create({
  methods: [
    evm.charge({
      currency: evm.assets.baseSepolia.USDC,
      recipient: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
      x402: {
        facilitator: 'https://x402.org/facilitator',
      },
    }),
  ],
  secretKey: process.env.MPP_SECRET_KEY ?? 'local-dev-secret',
})

export const GET =
  mppx.evm.charge({ amount: '0.01', description: 'Premium API access' })
  (() => Response.json({ data: 'paid content' }))
```

See [build a client for MPP and x402](/guides/use-mpp-with-x402#build-a-client-for-mpp-and-x402) for the client setup.
