
# Enabling agents to discover and pay for your API

## Overview

GOAL: Help a user at any stage (from zero to production API) make their API discoverable, payable, and wallet-authorized for agents.

This prompt is designed for coding agents. It should gather context, pick the correct implementation path, and execute with minimal back-and-forth.

## Important Context
- Open protocols like x402 and MPP enable agents to authorize and pay for API calls.
- x402 is part of the Linux Foundation and was originally created by Coinbase.
- MPP (Machine Payments Protocol) was created by Stripe and Tempo.
- An API can support both or only one of the protocols (through `@agentcash/router` or official SDKs).
- AgentCash is the interface through which many agents discover and invoke these paid APIs.
- AgentCash is created by Merit Systems, the creators of x402scan.com and mppscan.com, popular tools for discovering and exploring agentic commerce activity.
- `@agentcash/discovery` can be used to validate OpenAPI discovery and payment metadata before registration.

Primary docs:
- x402 docs: `https://docs.x402.org/`
- MPP docs: `https://mpp.dev/docs`
- AgentCash suggested frameworks (greenfield + proxy patterns): `https://agentcash.dev/docs/suggested-frameworks`
- AgentCash server discovery guide: `https://agentcash.dev/docs/discovery`
- **@agentcash/router troubleshooting + implementation guide: `https://agentcash.dev/agentcash-router.md`** — fetch this before writing router code
- x402scan registration: `https://www.x402scan.com/resources/register`
- mppscan registration: `https://www.mppscan.com/register`

## Agent operating mode

Before implementing, classify the user into one of these stages:

1. `GREENFIELD`: no API yet, building net-new for agents.
2. `EXISTING_API`: production API exists and should be wrapped with payments/auth.
3. `HAS_X402`: x402 support exists; wants discovery and/or MPP expansion.
4. `HAS_MPP`: MPP support exists; wants discovery and/or x402 expansion.
5. `HAS_BOTH`: both protocols exist; needs discovery hardening and registration.

If unclear, ask exactly these questions first:
- Do you already have a running API origin?
- Which protocol(s) are live now (`x402`, `MPP`, both, neither)?
- Do you want paid routes, identity-only routes, or both?
- Are you willing to add a proxy layer in front of your existing backend?

## Decision tree workflow

Use this decision tree exactly. Follow the first matching branch.

```text
START
 ├─ Q1: Does the user already have a running API?
 │   ├─ NO  -> BRANCH A (GREENFIELD)
 │   └─ YES -> Q2
 │
 ├─ Q2: Which payment protocol is already implemented?
 │   ├─ NONE  -> BRANCH B (EXISTING API, NO PAYMENTS YET)
 │   ├─ X402  -> Q3
 │   ├─ MPP   -> Q4
 │   └─ BOTH  -> BRANCH E (DISCOVERY + REGISTRATION HARDENING)
 │
 ├─ Q3: User has x402. Do they want MPP too?
 │   ├─ YES -> BRANCH C (EXPAND X402 -> BOTH)
 │   └─ NO  -> BRANCH E (DISCOVERY + REGISTRATION HARDENING)
 │
 └─ Q4: User has MPP. Do they want x402 too?
     ├─ YES -> BRANCH D (EXPAND MPP -> BOTH)
     └─ NO  -> BRANCH E (DISCOVERY + REGISTRATION HARDENING)
```

When asking the user questions, tailor the presumed knowledge level based on their context. For example, for greenfield users, you can assume they don't know about x402 or MPP and you should focus on the capabilities these tools (x402, MPP, AgentCash) provide, and how they can be used to monetize their API and be found by agents.

Do not mention the specific branch names, just focus on the capabilities and the paths to get there.

## Branch playbooks

### Branch A: Greenfield (no API yet)

Recommended path:
1. Scaffold a new API service (commonly Next.js route handlers).
2. Use `@agentcash/router` from day one.
3. Build one minimal paid route first, then add auth-only routes if needed.
4. Emit `/openapi.json` with full schemas and payment metadata.
5. Validate with `@agentcash/discovery`.
6. Register on `x402scan` and/or `mppscan`.

Why this path:
- Lowest integration complexity.
- Native support for both protocols without later migration.

### Branch B: Existing API, no payment protocol yet

Recommended path:
1. Create a thin proxy in front of production API.
2. Put `x402`/`MPP` verification, wallet identity, rate limiting, and discovery in proxy.
3. Keep production backend unchanged; call it with internal API key from proxy.
4. Start with one protocol or both depending on requirement:
   - single protocol: official SDK or router
   - dual protocol: use `@agentcash/router`
5. Publish discovery from proxy origin (`/openapi.json`), not the private upstream.

Why this path:
- Fastest way to monetize existing APIs without risky backend rewrites.

### Branch C: Already x402, expand to both

Recommended path:
1. Add MPP compatibility on payable operations.
2. Normalize OpenAPI `x-payment-info.protocols` to include both protocol objects.
3. Re-run discovery validation and runtime 402 checks.
4. Register/update listing in both ecosystems.

Implementation note:
- If dual-protocol support is uneven across routes, prioritize top revenue routes first.

### Branch D: Already MPP, expand to both

Recommended path:
1. Add x402 support on payable operations.
2. Normalize OpenAPI `x-payment-info.protocols` to include both protocol objects.
3. Re-run discovery validation and runtime 402 checks.
4. Register/update listing in both ecosystems.

### Branch E: Discovery + registration hardening (already monetized)

Recommended path:
1. Validate `GET /openapi.json` shape and completeness.
2. Validate every payable operation has:
   - `x-payment-info`
   - `responses.402`
   - request schema and response schema
3. Validate identity-only routes:
   - SIWX routes use `security` declaration and no `x-payment-info`
   - MPP identity mode uses zero-amount challenge flow
4. Run discovery checks until clean.
5. Register or refresh listing on the relevant registries.

## Implementation standards for all branches

**Before implementing the router, fetch `https://agentcash.dev/agentcash-router.md` for the condensed troubleshooting + API reference.** It covers env vars, the route builder, pricing modes (`.paid()` / `.upTo()` / `.metered()`), discovery handlers, the route barrel, critical invariants (BASE_URL, KV store, operator vs fee-payer, maxPrice), and common pitfalls. The agent should consult that document before writing any `@agentcash/router` code.

## Credential setup

Before the router can boot, the user needs several credentials. Generate what you can and guide them through the rest.

### Generating EVM wallets

The user needs two EVM wallets: an **operator wallet** (receives payments) and a **fee-payer wallet** (sponsors gas on Tempo).

**Use Node.js `crypto` module to generate private keys** — this has zero dependencies:

```bash
node -e "const c = require('crypto'); console.log('OPERATOR: 0x' + c.randomBytes(32).toString('hex')); console.log('FEE_PAYER: 0x' + c.randomBytes(32).toString('hex'))"
```

To derive the EVM address from a private key, use `viem`. **Important: `viem` is a transitive dependency of `@agentcash/router`, but it is NOT directly importable from the project root via `node -e`.** It lives inside the package manager's hoisted `node_modules` and CJS/ESM resolution often fails at the top level. Instead, use one of these approaches:

```bash
# Option 1: Use npx to run viem in an isolated context
npx -y -p viem node -e "import('viem/accounts').then(m => { const k = '0x...'; console.log(m.privateKeyToAccount(k).address); })"

# Option 2: Run from inside a workspace package that already depends on viem
pnpm --filter @my-org/my-app exec node -e "const { privateKeyToAccount } = require('viem/accounts'); console.log(privateKeyToAccount('0x...').address)"

# Option 3: Use openssl + cast (if foundry is installed)
cast wallet address --private-key 0x...
```

Once you have the addresses, set:
- `EVM_PAYEE_ADDRESS` = operator wallet address
- `MPP_OPERATOR_KEY` = operator wallet private key (address must match `EVM_PAYEE_ADDRESS`)
- `MPP_FEE_PAYER_KEY` = fee-payer wallet private key (must be a **different** address)

> **Heads up on `MPP_FEE_PAYER_KEY`:** this variable is **optional**. When set, the proxy sponsors agents' Tempo gas — and the fee-payer address must hold native Tempo gas before any traffic, or every paid call fails with a generic `Payment verification failed.` (the underlying error `insufficient funds for gas` only appears in the router's `onAlert`/`onError` plugin hooks, not the HTTP response). If you do not want to subsidize agent gas, **omit `MPP_FEE_PAYER_KEY` entirely** — clients then pay their own gas from the same wallet they pay USDC from. For most paid-API operators this is the right default.

### Generating MPP_SECRET_KEY

```bash
openssl rand -hex 32
```

This must persist across deploys. Rotating it invalidates outstanding 402 challenges.

### Getting CDP API keys (required for x402)

CDP (Coinbase Developer Platform) credentials let the x402 facilitator verify on-chain payments on Base.

1. Sign up or sign in at `https://portal.cdp.coinbase.com/`
2. Create a project (any name)
3. Go to **API Keys** → **Create API Key**
4. Select key type: **Server** (not Client)
5. Copy the Key ID → `CDP_API_KEY_ID`
6. Copy the Secret → `CDP_API_KEY_SECRET`

Docs: `https://docs.cdp.coinbase.com/get-started/docs/authentication`

If the user doesn't have a Coinbase account, they can create one for free. CDP keys are free to generate and have generous rate limits for x402 verification.

### Getting Tempo / MPP credentials

MPP (Machine Payments Protocol) uses Tempo for on-chain settlement. Two variables are needed:

**`MPP_CURRENCY`**: The Tempo token contract for pricing. For USD-denominated APIs, use Tempo USDC:
```
0x20c000000000000000000000b9537d11c60e8b50
```
This is also exported as `TEMPO_USDC_ADDRESS` from `@agentcash/router`.

**`TEMPO_RPC_URL`**: An authenticated Tempo JSON-RPC endpoint. The public `https://rpc.tempo.xyz` returns 401 — you need authenticated access.
- Get RPC access at `https://tempo.xyz` or contact the Tempo team
- MPP docs and onboarding: `https://mpp.dev/docs`
- Tempo developer docs: `https://docs.tempo.xyz`

If the user doesn't have Tempo RPC access yet, they can skip MPP and launch with x402 only. The router works with just x402 — MPP can be added later by setting `MPP_SECRET_KEY`, `MPP_CURRENCY`, and `TEMPO_RPC_URL`.

### KV store (required for serverless production)

SIWX nonces, entitlements, and MPP replay protection require persistent key-value storage across serverless cold starts. Without it, these features break silently.

**Vercel KV** (if deploying on Vercel):
1. Go to your Vercel dashboard → **Storage** → **Create** → **KV**
2. Or provision via CLI: `vercel storage create kv`
3. Link to your project and pull env vars: `vercel env pull`
4. This sets `KV_REST_API_URL` + `KV_REST_API_TOKEN` automatically
- Docs: `https://vercel.com/docs/storage/vercel-kv`

**Upstash Redis** (any platform):
1. Sign up at `https://console.upstash.com/`
2. Create a Redis database (free tier available)
3. Copy the REST URL → `KV_REST_API_URL`
4. Copy the REST token → `KV_REST_API_TOKEN`
- Docs: `https://upstash.com/docs/redis/overall/getstarted`

Not needed for local development — the router uses an in-memory fallback that works fine for single-instance dev servers.

### Deploying on Vercel

A few Vercel-specific gotchas worth flagging up front:

- **`BASE_URL` is needed at build time, not just runtime.** `next build` calls into route handlers to collect static pages (`/.well-known/x402`, `/openapi.json`), and `createRouterFromEnv` validates env eagerly — so a missing `BASE_URL` fails the build, not the first request. Set it before the first deploy.
- **Use the canonical short alias for `BASE_URL`, not the deployment URL.** Vercel assigns two domains: a per-deployment URL (`<project>-<hash>-<scope>.vercel.app`) and a stable production alias (`<project>.vercel.app` for personal scope, or the custom domain you've attached). `BASE_URL` must equal whichever URL agents will hit — otherwise the 402 realm and MPP memo prefix won't match and payments are rejected. If the first deploy used the wrong value, run `vercel env rm BASE_URL production && vercel env add BASE_URL production && vercel deploy --prod` to fix.
- **`KV_REST_API_URL` + `KV_REST_API_TOKEN` are optional, recommended for production hardening.** Without them the router falls back to an in-memory KV store — fine for local dev and low-volume testing, but it doesn't share state across serverless instances, so SIWX nonce protection and MPP tx-hash replay protection can race. The build prints `[router] No KV_REST_API_URL/KV_REST_API_TOKEN set in production — using the in-memory KV store` as a heads-up. Add them when you're ready to harden — there's no rush for early prototypes.

## Starting from scratch

Recommended default: `@agentcash/router` with Next.js route handlers. Fetch `https://agentcash.dev/agentcash-router.md` for the API reference and gotchas.

## Integrating with an existing API

Recommended default: a proxy service that wraps existing endpoints with `x402`, `MPP`, or both. If the proxy uses `@agentcash/router`, fetch `https://agentcash.dev/agentcash-router.md` first.

## Protocol selection

### x402 only

- Use official x402 SDKs or `@agentcash/router`.

### MPP only

- Use official MPP SDK (`mppx`) or `@agentcash/router`.
- **Realm must match the public origin.** On custom domains or reverse proxies, do not rely on auto-detected deployment hosts like `VERCEL_URL`; set `MPP_REALM` or pass `realm` explicitly, e.g. `Mppx.create({ realm: "api.example.com", ... })`.

### Both x402 + MPP

- Use `@agentcash/router`.

## Publishing a discovery specification

Implement AgentCash discovery for this server and make it pass.

Discovery strategy:
Your API should expose an OpenAPI document at `/openapi.json`, which abides by OpenAPI and includes AgentCash discovery fields.
Use `@agentcash/discovery` to validate.

Validation commands:
npx -y @agentcash/discovery@latest discover "$TARGET_URL"
npx -y @agentcash/discovery@latest check "$TARGET_URL"


This will yield warnings regarding the discovery document and how it can be improved.

Schema guidance (important):
- Each invocable route should expose an input schema.
- In OpenAPI, define requestBody.content["application/json"].schema.
- This is required for reliable agent invocation and robust listing behavior.
- Add high-level guidance in info.x-guidance for agent-friendly discovery. This document should explain to an agent how to use your API at a high level.

OpenAPI payable operation must include ALL:
- `x-payment-info` with:
  - `protocols`: protocol objects, for example `[{ "x402": {} }, { "mpp": { "method": "", "intent": "", "currency": "" } }]`
  - `price` object:
    - fixed: `{ price: { mode: "fixed", currency: "USD", amount: "<amount>" } }`
    - dynamic: `{ price: { mode: "dynamic", currency: "USD", min: "<min>", max: "<max>" } }`
  - Legacy flat format still works: `{ pricingMode: "fixed", price: "<amount>" }`
  - IMPORTANT: fixed pricing should use `amount` (not `value`)
- `responses`: `{ "402": { "description": "Payment Required" } }`

Identity-only (authorized, not paid) endpoints:
- For x402 ecosystems: declare `siwx` in `components.securitySchemes` and reference it on each identity-gated operation via `security: [{ "siwx": [] }]`.
- Do not add `x-payment-info` to SIWX-only routes.
- For MPP identity mode: use zero-amount pricing challenges per MPP identity guidance.

Minimal valid example:
{
  "openapi": "3.1.0",
  "info": {
    "title": "My API",
    "version": "1.0.0",
    "description": "example demo server",
    "x-guidance": "Use POST /api/search for neural web search. Accepts a JSON body with a 'query' field."
  },
  "x-discovery": {
    "ownershipProofs": ["<proof-1>"]
  },
  "paths": {
    "/api/search": {
      "post": {
        "operationId": "search",
        "summary": "Search - Neural search across the web",
        "tags": ["Search"],
        "x-payment-info": {
          "price": { "mode": "fixed", "currency": "USD", "amount": "0.010000" },
          "protocols": [{ "x402": {} }, { "mpp": { "method": "", "intent": "", "currency": "" } }]
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "query": { "type": "string", "minLength": 1, "description": "The query string for the search" }
                },
                "required": ["query"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "results": { "type": "array", "items": { "type": "object" } }
                  },
                  "required": ["results"]
                }
              }
            }
          },
          "402": { "description": "Payment Required" }
        }
      }
    }
  }
}

## Completion Checklist

1. Correct branch selected from the decision tree.
2. Protocol implementation complete for target branch.
3. `/openapi.json` published and valid.
4. `discover` and `check` commands run without blocking errors.
5. Registry registration links provided or completed:
   - `https://www.x402scan.com/resources/register`
   - `https://www.mppscan.com/register`
6. User receives final handoff with:
   - implemented architecture
   - supported protocols
   - validation output summary
   - next recommended step (e.g., add second protocol, add SIWX routes, tighten rate limits)
