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

> ## Agent Instructions
> The Exa API is served at https://api.exa.ai. Authenticate with `Authorization: Bearer $EXA_API_KEY` (or `x-api-key: $EXA_API_KEY`); create keys at https://dashboard.exa.ai/api-keys.
> Prefer the official SDKs, `exa-py` (`pip install exa-py`) and `exa-js` (`npm install exa-js`); both read `EXA_API_KEY` from the environment.
> Tool-using agents can call Exa without writing code through the hosted MCP server at https://mcp.exa.ai/mcp, or install the Exa agent skill with `npx skills add exa-labs/agent-skills` (skill file: https://exa.ai/docs/skill.md).
> The OpenAPI specs at https://exa.ai/docs/exa-spec.yaml and https://exa.ai/docs/team-management-spec.yaml are the source of truth for request and response schemas.

# Pay with MPP (Tempo)

> Call Exa's Search and Contents APIs without an API key by paying per request with USDC.e on Tempo.

## What is MPP?

MPP (Machine Payments Protocol) is an open, HTTP-native payment standard built on the `402 Payment Required` status code. It lets clients pay for API access per-request using multiple payment methods, including stablecoins on [Tempo](https://tempo.xyz), with no accounts, API keys, or subscriptions needed. The examples on this page use Tempo; Exa currently settles MPP payments in USDC.e on Tempo mainnet.

Exa supports MPP on two endpoints: **`/search`** and **`/contents`**. When you send a request without an API key or payment credential, Exa responds with `402` and a `WWW-Authenticate: Payment` challenge describing the price and how to pay. Your client signs a payment, retries the request with an `Authorization: Payment` credential, and receives the results once the payment settles on-chain.

This is ideal for **AI agents** that need to autonomously pay for web search without pre-provisioned credentials.

<Info>
  MPP and API key access are independent. If your request includes an `x-api-key` header, the normal API key billing flow is used and MPP is bypassed entirely.
</Info>

## Supported endpoints

| Endpoint | Method | Description |
| - | - | - |
| `/search` | POST | Web search with all search types (`instant`, `auto`, `fast`, `deep`, `deep-lite`, `deep-reasoning`) |
| `/contents` | POST | Content retrieval by URL or document ID |

Other Exa endpoints do not accept MPP payments *yet*.

## Get started

You need a Tempo-compatible wallet funded with USDC.e. Export your wallet's private key before running an example:

```bash theme={null}
export WALLET_PRIVATE_KEY="0x..."
```

### Install the client

<CodeGroup>
  ```bash TypeScript theme={null}
  npm install mppx viem
  ```

  ```bash Python theme={null}
  pip install "pympp[tempo]"
  ```
</CodeGroup>

### Make a paid search request

Use the MPP client to sign and submit a payment for a search request:

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { Mppx, tempo } from "mppx/client";
  import { privateKeyToAccount } from "viem/accounts";

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

  const response = await mppx.fetch("https://api.exa.ai/search", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      query: "best machine learning frameworks",
      numResults: 5,
    }),
  });

  const data = await response.json();
  console.log(data.results);
  console.log("Payment receipt:", response.headers.get("Payment-Receipt"));
  ```

  ```python Python theme={null}
  import asyncio
  import os

  from mpp.client import Client
  from mpp.methods.tempo import ChargeIntent, TempoAccount, tempo


  async def main() -> None:
      account = TempoAccount.from_key(os.environ["WALLET_PRIVATE_KEY"])
      method = tempo(
          account=account,
          chain_id=4217,
          intents={"charge": ChargeIntent()},
      )

      async with Client(methods=[method]) as client:
          response = await client.post(
              "https://api.exa.ai/search",
              json={"query": "best machine learning frameworks", "numResults": 5},
          )

      data = response.json()
      for result in data["results"]:
          print(result["url"], result["title"])
      print("Payment receipt:", response.headers.get("Payment-Receipt"))


  asyncio.run(main())
  ```
</CodeGroup>

A successful run prints the search results and the `Payment-Receipt` header containing the on-chain transaction hash.

## Pay from the command line

If you prefer not to manage a raw private key, use the Tempo Wallet CLI instead. `tempo wallet login` creates or connects a Tempo wallet, authorizes a local access key, and can include free MPP Credits for new sign-ups.

### Install and authenticate

```bash theme={null}
curl -fsSL https://tempo.xyz/install | bash
tempo add wallet
tempo add request
tempo wallet login
```

On a remote host without a local browser, use `tempo wallet login --no-browser` and open the printed URL on your device to authorize the CLI.

### Check balances and credits

```bash theme={null}
tempo wallet whoami
tempo wallet whoami --credits
```

### Make a paid request

```bash theme={null}
tempo request --max-spend 1.00 https://api.exa.ai/search \
  --json '{"query": "Series A fintech companies", "numResults": 5}'
```

`tempo request` intercepts the `402 Payment Required` challenge, pays, and retries automatically.

For full CLI reference, see the [Tempo Wallet CLI docs](https://tempo.xyz/developers/docs/cli/wallet) and [`tempo request` docs](https://tempo.xyz/developers/docs/cli/request).

## Gas fees

Exa sponsors the Tempo network fee and pays it in USDC.e. Your wallet only needs enough USDC.e for the API charge; it does not need pathUSD or another gas-token balance. You do not configure a fee payer. Exa's payment challenge and the MPP SDK handle sponsorship automatically.

## Pricing

MPP uses the same bundled pricing as API key billing. Exa calculates the price from the request parameters before processing the request.

### Search

| Search type | Price for up to 10 results |
| - | - |
| `instant` | \$0.004 per request |
| `auto`, `fast` | \$0.007 per request |
| `deep-lite`, `deep` | \$0.012 per request |
| `deep-reasoning` | \$0.015 per request |

Adding `contents.summary` costs another **\$0.001 per result**.

<Warning>
  MPP search requests are capped at 10 results. If `numResults` is greater than 10, Exa uses 10 and prices the request for 10 results. If you need more, use [API key billing](/docs/search/quickstart).
</Warning>

### Contents

Each requested content type costs \$0.001 per URL:

| Content type | Price per URL |
| - | - |
| `text` | \$0.001 |
| `highlights` | \$0.001 |
| `summary` | \$0.001 |

If you do not request `text`, `highlights`, or `summary`, Exa enables `text` by default.

### Pricing examples

| Request | Price |
| - | - |
| `/search` with `type: "auto"` | \$0.007 |
| `/search` with 3 results and `contents.summary` | \$0.010 |
| `/search` with `type: "deep"` | \$0.012 |
| `/contents` for 2 URLs with `text: true` | \$0.002 |
| `/contents` for 1 URL with `text` and `summary` | \$0.002 |

## How the payment flow works

The SDK automates this flow, but you can inspect it directly over HTTP:

1. Send a request without an API key or payment credential. Exa returns `402` with a `WWW-Authenticate: Payment` challenge containing the price, token, recipient, network, and sponsorship details.
2. Sign the challenge and retry with `Authorization: Payment <credential>`.
3. Exa processes the request while settling the payment. After settlement confirms, Exa returns the results with a `Payment-Receipt` header. If settlement fails, Exa returns `402` with a fresh challenge and no results.

### Inspect a payment challenge

You can inspect the price and payment details without a wallet:

```bash theme={null}
curl -s -D - -X POST "https://api.exa.ai/search" \
  -H "Content-Type: application/json" \
  -d '{"query": "test query", "numResults": 3}'
```

Look for the `WWW-Authenticate: Payment` header in the `402` response. Unpaid discovery requests are rate-limited, so use this for debugging rather than polling.

## Payment reference

Exa accepts MPP payments in USDC.e on Tempo mainnet.

| Network | Identifier | Token | Asset |
| - | - | - | - |
| Tempo mainnet | `eip155:4217` | USDC.e | `0x20c000000000000000000000b9537d11c60e8b50` |

USDC.e has 6 decimals. The challenge expresses prices in atomic units, so `7000` is \$0.007 and `1000000` is \$1.00.

<Note>
  Exa supports MPP and [x402](/docs/integrations/payments/x402/quickstart) on the same endpoints. An unauthenticated `402` response can include both the MPP `WWW-Authenticate: Payment` challenge and the x402 `PAYMENT-REQUIRED` header. Use the headers for the payment protocol your client supports.
</Note>

### Headers

| Header | Direction | Description |
| - | - | - |
| `Authorization: Payment <credential>` | Request | MPP payment credential |
| `WWW-Authenticate: Payment` | `402` response | Price and payment instructions for the request |
| `Payment-Receipt` | Successful response | Settlement receipt, including the on-chain transaction hash |

### Errors

| Status | Description |
| - | - |
| `402` | The payment credential is missing or invalid; the response includes a fresh challenge |
| `402` | The payment amount does not match the request price, or settlement failed |
| `429` | This IP sent too many unpaid discovery requests |
| `429` | This wallet exceeded the paid-request rate limit |

### Rate limits

MPP rate limits are shared with x402 and are separate from API key limits:

| Limit | Threshold | Window |
| - | - | - |
| Unpaid discovery requests per IP | 5 requests | 60 seconds |
| Paid requests per wallet | 10 requests | 1 second |

## FAQ

<AccordionGroup>
  <Accordion title="Can I use MPP and an API key together?">
    If your request includes an `x-api-key` header, the API key flow takes priority and MPP is bypassed. They don't stack. It's one or the other per request.
  </Accordion>

  <Accordion title="What happens if settlement fails after my request was processed?">
    Your response is blocked. You receive a `402` with a fresh `WWW-Authenticate: Payment` challenge so your client can retry. No results are returned until settlement succeeds.
  </Accordion>

  <Accordion title="Which wallets are supported?">
    Any Tempo-compatible EVM wallet the client SDK can sign with — a `viem` account with `mppx` (TypeScript), or an `eth-account` key with `pympp` (Python). For AI agents, use a wallet with a USDC.e balance on Tempo to cover request prices.
  </Accordion>
</AccordionGroup>

## Resources

* [MPP protocol docs](https://mpp.dev/protocol): protocol details and authentication format
* [mppx documentation](https://mpp.dev/sdk/typescript): MPP TypeScript SDK reference
* [pympp documentation](https://mpp.dev/sdk/python): MPP Python SDK reference
* [Tempo](https://tempo.xyz): Tempo network documentation
* [Pay with x402](/docs/integrations/payments/x402/quickstart): pay for the same endpoints with x402
* [Exa Search API guide](/docs/search/quickstart): full search parameter reference
* [Exa Contents API guide](/docs/contents/quickstart): full contents parameter reference
