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

# MPP Payments

> Access the Zerion API per-request using USDC on Tempo — no API key required.

MPP ([Machine Payments Protocol](https://mpp.dev)) is an open protocol for pay-per-request HTTP access. Instead of an API key, you pay a small amount of USDC on Tempo for each request — ideal for AI agents that need onchain data without managing subscriptions or key rotation.

This is an alternative authorization method for the same Zerion API. Endpoints, JSON:API responses, query parameters, and filters all behave exactly as in the rest of the docs — only the way you prove access changes.

Zerion also supports [x402](./x402), a sibling protocol that settles on Base or Solana. See [Authentication](/authentication) for an overview of all access methods.

## Quickstart with the Zerion CLI

The easiest way to use MPP is with the [Zerion CLI](./zerion-cli), which handles the payment handshake, wallet signing, and retries automatically.

Set an EVM private key for a wallet that holds USDC on Tempo, then make a request with `--mpp`:

```bash theme={null}
export WALLET_PRIVATE_KEY="0x..."
zerion-cli wallet portfolio 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 --mpp
```

<Tip>
  Set `ZERION_MPP=true` to enable MPP globally for analytics commands instead of passing `--mpp` on every call. If you already use `WALLET_PRIVATE_KEY` for x402, the same key works for MPP — or set `TEMPO_PRIVATE_KEY` to use a different wallet for Tempo.
</Tip>

## Direct integration

If you're not using the CLI, use one of the [official MPP SDKs](https://mpp.dev/sdk) (TypeScript, Python, Go, Rust) to handle payment construction and retries. You'll need a wallet with USDC on Tempo and its EVM private key.

## Example

```ts theme={null}
import { privateKeyToAccount } from 'viem/accounts'
import { Mppx, tempo } from 'mppx/client'

Mppx.create({
  methods: [tempo({ account: privateKeyToAccount(process.env.WALLET_PRIVATE_KEY) })],
})

// Global fetch now handles 402 automatically
const res = await fetch(
  'https://api.zerion.io/v1/wallets/0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045/portfolio'
)
const data = await res.json()
```

## How it works

```
  Client                     Zerion API
    |                             |
    |  1. GET /v1/wallets/...     |
    | --------------------------> |
    |                             |
    |  2. 402 Payment Required    |
    | <-------------------------- |
    |     WWW-Authenticate:       |
    |     Payment <challenge>     |
    |                             |
    |  3. GET /v1/wallets/...     |
    |     Authorization:          |
    |     Payment <credential>    |
    | --------------------------> |
    |                             |
    |  4. 200 OK                  |
    |     Payment-Receipt: ...    |
    | <-------------------------- |
    |                             |
```

1. Client sends a request to an API endpoint
2. Server returns `402` with a `WWW-Authenticate: Payment` challenge describing where and how much to pay
3. Client signs a USDC transfer on Tempo and retries with an `Authorization: Payment` header
4. Zerion verifies the credential with the MPP facilitator and returns the response

## Rate limits

None — pay per request, no per-second or monthly quota.

## Error handling

* `402 Payment required` — no or invalid payment credential. Inspect the `WWW-Authenticate: Payment` response header for a fresh challenge and retry.
* `402 MPP payment rejected` — the facilitator rejected the credential. The `detail` field contains the reason (e.g. insufficient funds, expired authorization).
