> ## Documentation Index
> Fetch the complete documentation index at: https://docs.privy.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Machine Payments Protocol (MPP)

Enable agents to pay for APIs and content using MPP, an open protocol for machine-to-machine payments over HTTP. Privy's server wallets provide the signing layer, while the `mppx` SDK handles the 402 payment flow automatically.

## What is MPP?

[MPP](https://mpp.dev) (Machine Payments Protocol) is an open protocol for machine-to-machine payments over HTTP. When a resource requires payment, the server responds with `402 Payment Required` and payment details. The client signs a payment credential using the agent's wallet and retries the request. MPP supports multiple chains and payment assets—this guide uses [Tempo](https://tempo.xyz) with PathUSD as the settlement layer, but other networks and assets are supported by the protocol.

## Installation

```bash theme={"system"}
npm install @privy-io/node mppx viem
```

* `@privy-io/node` provides server-side wallet creation and signing
* `mppx` provides the MPP client that handles 402 payment flows
* `viem` provides the account interface used by Privy's viem helper and `mppx`

## Creating a Privy-backed account

MPP's `tempo.charge()` payment method expects a [viem Account](https://viem.sh/docs/accounts/local/toAccount) for signing. Use Privy's `createViemAccount` helper to create a viem account backed by a Privy wallet.

```typescript theme={"system"}
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!
});

const account = createViemAccount(privy, {
  walletId: 'insert-wallet-id',
  address: '0x0000000000000000000000000000000000000000'
});
```

<Info>
  Use `@privy-io/node` v0.20.0 or later. Earlier versions required custom Tempo transaction
  serialization logic.
</Info>

## Making MPP payments

Pass the Privy-backed account to the MPP client's `tempo.charge()` method. The client automatically handles 402 responses, signs payment credentials, and retries requests.

### Using `mppx.fetch`

```typescript {skip-check} theme={"system"}
import {PrivyClient} from '@privy-io/node';
import {createViemAccount} from '@privy-io/node/viem';
import {Mppx, tempo} from 'mppx/client';

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

async function makePayment(walletId: string, address: `0x${string}`, url: string) {
  const account = createViemAccount(privy, {
    walletId,
    address
  });

  const mppx = Mppx.create({
    polyfill: false,
    methods: [tempo.charge({account})]
  });

  const response = await mppx.fetch(url);
  const data = await response.json();
  return data;
}
```

`mppx.fetch` is a drop-in replacement for `fetch`. When a server returns `402 Payment Required`, the client reads the payment requirements, signs a credential with the Privy wallet, and retries the request automatically.

Use `tempo({account})` instead when the client should support both one-time charges and Tempo sessions.

### Using polyfill mode

Your app can also polyfill the global `fetch` so all HTTP requests handle 402 challenges automatically:

```typescript {skip-check} theme={"system"}
import {PrivyClient} from '@privy-io/node';
import {createViemAccount} from '@privy-io/node/viem';
import {Mppx, tempo} from 'mppx/client';

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

const account = createViemAccount(privy, {
  walletId: 'insert-wallet-id',
  address: '0x0000000000000000000000000000000000000000'
});

Mppx.create({
  polyfill: true,
  methods: [tempo.charge({account})]
});

// All fetch calls now handle 402 responses automatically
const response = await fetch('https://api.example.com/weather');
```

## How it works

1. **Agent requests content**: Your app calls `mppx.fetch()` or the polyfilled `fetch()`
2. **Server responds 402**: Returns payment requirements (amount, currency, recipient)
3. **MPP client signs credential**: Uses the Privy-backed account to sign a payment credential
4. **Retry with credential**: Request repeats with the signed credential attached
5. **Server verifies and settles**: Verifies the credential and settles payment on-chain (Tempo in this guide)
6. **Server delivers**: Returns content with `200 OK`

## Creating an MPP-enabled service

The `mppx/nextjs` package provides middleware for adding payment requirements to API routes:

```typescript theme={"system"}
// app/api/weather/route.ts
import {Mppx, tempo} from 'mppx/nextjs';

// MPP supports multiple chains and assets. This example uses Tempo with PathUSD.
// See https://mpp.dev for other supported networks and payment assets.
const mppx = Mppx.create({
  methods: [
    tempo.charge({
      currency: '0x20c0000000000000000000000000000000000000', // PathUSD
      recipient: process.env.MPP_RECIPIENT as `0x${string}`
    })
  ],
  secretKey: process.env.MPP_SECRET_KEY!
});

export const GET = mppx.charge({amount: '0.1'})(() =>
  Response.json({
    temperature: 72,
    condition: 'Sunny',
    location: 'San Francisco, CA'
  })
);
```

When a client calls this route without a payment credential, the middleware responds with `402 Payment Required`. With a valid credential, it verifies the payment, settles on Tempo, and returns the data.

## Full example

```typescript theme={"system"}
import {PrivyClient} from '@privy-io/node';
import {createViemAccount} from '@privy-io/node/viem';
import {Mppx, tempo} from 'mppx/client';

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

// 1. Create a wallet for the agent
const wallet = await privy.wallets().create({chain_type: 'ethereum'});

// 2. Build a viem account backed by Privy
const account = createViemAccount(privy, {
  walletId: wallet.id,
  address: wallet.address as `0x${string}`
});

// 3. Create the MPP client
const mppx = Mppx.create({
  polyfill: false,
  methods: [tempo.charge({account})]
});

// 4. Make a paid request
const response = await mppx.fetch('https://api.example.com/weather');
const weather = await response.json();
```

## Learn more

* [MPP Protocol documentation](https://mpp.dev) - Protocol specification and guides
* [mppx SDK](https://www.npmjs.com/package/mppx) - Client and server SDK for MPP
* [Privy server wallets](/recipes/agent-integrations/agentic-wallets) - Creating and managing server-side wallets
* [Full demo application](https://github.com/privy-io/examples/tree/main/privy-next-mpp-agent-demo) - Complete Next.js example
