# MPP (/integrations/pay-per-use/mpp)

<!-- agent-signals: reading_time_min: 5 · est_tokens: 1751 · updated: 2026-09-06 -->
Related: [x402](/integrations/pay-per-use/x402.md)



# Pay for AgentMail per request over MPP

MPP (Machine Payments Protocol) is an open standard from Stripe and Tempo that lets machines pay for HTTP requests. An agent whose wallet holds USDC.e on the Tempo blockchain buys each AgentMail call with a signed payment, so it needs no API key and no plan.

## Do this

Fund first: the agent needs Node.js, an EVM private key it controls, and a USDC.e balance on Tempo held by that key's address. Onramp with fiat through Tempo Wallet or bridge from another chain, per [https://docs.tempo.xyz/guide/getting-funds](https://docs.tempo.xyz/guide/getting-funds). USDC bridged over Stargate appears on Tempo as USDC.e. A few dollars covers this path, the inbox create costs $2.00 and every other call here is free.

```bash
npm install agentmail mppx viem
export TEMPO_PRIVATE_KEY="0x..."
```

```typescript
import { privateKeyToAccount } from "viem/accounts";
import { Mppx, tempo } from "mppx/client";
import { AgentMailClient } from "agentmail";

const account = privateKeyToAccount(process.env.TEMPO_PRIVATE_KEY as `0x${string}`);
const mppx = Mppx.create({ methods: [tempo({ account })] });

const client = new AgentMailClient({ mppx });

// Free call. Proves the challenge and credential loop end to end.
const inboxes = await client.inboxes.list();
console.log(inboxes.count); // 0 on a fresh wallet

// Paid call, $2.00 in USDC.e from the wallet.
const inbox = await client.inboxes.create({ displayName: "Support agent" });
console.log(inbox.inboxId);

// Free connection, tied to the same wallet.
const socket = await client.websockets.connect();
socket.on("message", (event) => {
  if (event.type === "subscribed") {
    console.log("Subscribed to", event.inboxIds);
  } else if (event.type === "event" && event.eventType === "message.received") {
    console.log("New email from", event.message.from);
  }
});
socket.sendSubscribe({ type: "subscribe", inboxIds: [inbox.inboxId] });
```

## SDK

```bash
npm install agentmail mppx viem
```

* Create the payer: `Mppx.create({ methods: [tempo({ account })] })` with an account from `privateKeyToAccount` in `viem/accounts`.
* Route every request through it: `new AgentMailClient({ mppx })`.
* List inboxes, free: `client.inboxes.list()`.
* Create an inbox, $2.00: `client.inboxes.create({ displayName: "Support agent" })`. Pass `username` to pick the part before `@agentmail.to`.
* Receive events, free: `client.websockets.connect()`, then `socket.sendSubscribe({ type: "subscribe", inboxIds: [...] })`.

More SDK surface: `/integrations/sdks-and-cli`.

## Facts

* With `mppx` set, API requests go to `https://mpp.api.agentmail.to` and WebSocket connections to `wss://mpp.ws.agentmail.to`. Paths, methods, and responses match the regular API. Only the host and the authentication change.
* AgentMail charges MPP requests in USDC.e, a bridged form of USDC, on the Tempo blockchain, chain id `4217`.
* Prices: create an inbox $2.00. Send an email (send, reply, forward, or send a draft) $0.01. Create a draft, webhook, pod, or inbound-control entry $0.01. Add a custom domain $10.00. Everything else, including reads and WebSocket connections, is free.
* The price of a request is the `amount` in its challenge, in the currency's 6-decimal units, so `2000000` is $2.00. The client reads it before it pays and pays exactly what the challenge asks.
* The challenge arrives on the first `402` response in a `WWW-Authenticate: Payment` header. Its base64 `request` parameter decodes to `amount`, `currency` (`0x20C000000000000000000000b9537d11c60E8b50`, the USDC.e token address on Tempo), `methodDetails.chainId` `4217`, and `recipient` (`0x6e3184C204e596dED89E8A5693B602097F4Ab687`, AgentMail's wallet).
* Each request gets its own challenge. A challenge expires five minutes after it is issued.
* Free requests run the same challenge and credential loop with an `amount` of `0`. The zero-amount credential is still signed by the wallet, and the signature is how AgentMail knows which wallet is calling.
* The inbox belongs to the wallet that paid for it. An agent run with the same key everywhere sees the same inboxes.
* The SDK completes the challenge and credential exchange itself, for free requests and WebSocket connects too. Manual challenge handling is only needed when calling the API without the SDK.
* `username` on create is optional. Omit `username` and AgentMail generates one.

## Not supported

* Wallets on chains like Base or Solana cannot pay over MPP. Use x402 instead: `/integrations/pay-per-use/x402`.
* No API keys and no plans on the MPP hosts. An application that holds an AgentMail API key should follow `/quickstart` on the regular API instead.
* The direction is agent pays AgentMail. This page defines no flow where AgentMail pays the agent's wallet.
* The paying client is TypeScript on Node.js. The page shows no client in any other language.

## Errors

| Error                                   | Status | Cause                                                                                                                   | Fix                                                                                               |
| --------------------------------------- | ------ | ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| `Proof signature does not match source` | 402    | The payment credential failed verification on the Tempo chain, usually because the key has not yet held funds on Tempo. | Fund the key's address with USDC.e on Tempo, then rerun with the same key in `TEMPO_PRIVATE_KEY`. |
| `Ownership required`                    | 403    | The request touches an inbox owned by a different wallet.                                                               | Sign with the key that paid for the inbox.                                                        |
| `already_exists` or `resource_taken`    | 403    | The requested `username` is taken, by the calling wallet or by another.                                                 | Pick one of the up to three available alternatives in `suggestions`, or omit `username`.          |

## Verify

Run the free list call with the paying client:

```typescript
console.log((await client.inboxes.list()).count);
```

A printed count, `0` on a fresh wallet, means the client completed a full challenge and credential exchange with AgentMail. A `402` even on this free call means the payment credential failed verification on the Tempo chain.

## Related

* `/integrations/pay-per-use/x402` - pay per request from a Base, Polygon, Avalanche C-Chain, X Layer, or Solana wallet instead.
* `/core/send` - everything the agent can do when sending from the inbox it bought.
* `/advanced/websockets` - all the events the agent can receive over the connection.
* `/quickstart` - authenticate with an API key and pay through a plan instead.
