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

# Router quickstart

> Ship a pay-per-call API in one click with the Vercel template, from scratch on any runtime, or inside an existing app.

export const PromptAccordion = ({prompt, label = 'Paste into your coding agent'}) => {
  const [open, setOpen] = useState(false);
  const [copied, setCopied] = useState(false);
  return <div className="prompt-accordion" style={{
    marginBottom: '1.25rem'
  }}>
      <div onClick={() => setOpen(!open)} style={{
    display: 'flex',
    alignItems: 'center',
    gap: 8,
    padding: '14px 16px',
    cursor: 'pointer',
    userSelect: 'none'
  }}>
        <span className="prompt-accordion-icon" style={{
    fontSize: 12,
    transform: open ? 'rotate(90deg)' : 'rotate(0deg)',
    transition: 'transform 0.15s'
  }}>
          ▶
        </span>
        <svg className="prompt-accordion-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
          <polyline points="4 17 10 11 4 5" />
          <line x1="12" y1="19" x2="20" y2="19" />
        </svg>
        <span className="prompt-accordion-label" style={{
    fontSize: 14
  }}>
          {label}
        </span>
        <button onClick={async e => {
    e.stopPropagation();
    try {
      await navigator.clipboard.writeText(prompt);
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    } catch {}
  }} style={{
    marginLeft: 'auto',
    display: 'inline-flex',
    alignItems: 'center',
    background: '#309637',
    color: '#fff',
    border: 'none',
    borderRadius: 6,
    padding: '6px',
    cursor: 'pointer'
  }}>
          {copied ? <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
              <polyline points="20 6 9 17 4 12" />
            </svg> : <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
              <rect x="9" y="9" width="13" height="13" rx="2" ry="2" />
              <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" />
            </svg>}
        </button>
      </div>
      {open && <pre className="prompt-accordion-expanded" style={{
    margin: 0,
    padding: '0 16px 16px',
    whiteSpace: 'pre-wrap',
    wordBreak: 'break-word',
    fontSize: 13,
    lineHeight: 1.6
  }}>
          {prompt}
        </pre>}
    </div>;
};

<PromptAccordion prompt="Read https://agentcash.dev/merchants.md and follow the guide to make my API discoverable and payable by agents. You can refereence https://agentcash.dev/router/overview and the AgentCash Router docs, then build me a pay-per-call API on x402 and MPP using @agentcash/router. Do everything automatically. Only ask me if you need input you can't determine yourself." />

<Accordion title="One-click deploy with the Vercel template">
  The [Vercel template](https://github.com/merit-systems/agentcash-router/tree/main/examples/vercel-deploy) is a standalone Next.js app that clones into your GitHub and deploys a working pay-per-call API. The demo is a fortune teller that exercises every pricing mode.

  <Steps>
    <Step title="Click deploy">
      <a style={{ display: "inline-block", width: "fit-content", textDecoration: "none", borderBottom: "none" }} href="https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2FMerit-Systems%2Fagentcash-router%2Ftree%2Fmain%2Fexamples%2Fvercel-deploy&project-name=agentcash-fortune-demo&repository-name=agentcash-fortune-demo&demo-title=AgentCash%20Router%20Fortune%20Demo&demo-description=Pay-per-call%20fortune%20API%20on%20x402%20and%20MPP&demo-url=https%3A%2F%2Fagentcash.dev&env=EVM_PAYEE_ADDRESS%2CCDP_API_KEY_ID%2CCDP_API_KEY_SECRET&envDescription=Wallet%20that%20receives%20payments%20%2B%20Coinbase%20Developer%20Platform%20API%20keys%20for%20the%20default%20x402%20facilitator.%20Create%20keys%20in%20the%20generous%20CDP%20free%20tier%3A%20https%3A%2F%2Fportal.cdp.coinbase.com%2Fprojects%2Fapi-keys&envLink=https%3A%2F%2Fgithub.com%2FMerit-Systems%2Fagentcash-router%2Fblob%2Fmain%2Fexamples%2Fvercel-deploy%2FREADME.md%23environment-variables">
        <img noZoom style={{ display: "block", margin: 0 }} alt="Deploy with Vercel" src="https://vercel.com/button" />
      </a>

      Vercel clones only the template directory into a fresh repo in your GitHub account.
    </Step>

    <Step title="Set three environment variables">
      The deploy flow prompts for them inline:

      * `EVM_PAYEE_ADDRESS`: the `0x…` wallet that receives payments.
      * `CDP_API_KEY_ID` and `CDP_API_KEY_SECRET`: [Coinbase Developer Platform](https://portal.cdp.coinbase.com/projects/api-keys) credentials for the default x402 facilitator. The CDP free tier is enough.

      `BASE_URL` is auto-derived from Vercel's system env vars, so there is no manual step.
    </Step>

    <Step title="Call it">
      The landing page at your deployment's root lists every endpoint with a copy-pasteable command:

      ```bash theme={null}
      npx agentcash fetch https://<your-domain>/api/fortune -m POST
      ```
    </Step>
  </Steps>

  <Tip>
    Add Upstash Redis / Vercel KV from the Vercel Storage tab before production traffic. Without it, SIWX entitlement and replay state is per-Lambda-instance and pay-once-then-replay routes break at scale. See [Configuration](/router/configuration#kv-store).
  </Tip>

  To make it your own, replace the routes in `app/api/fortune/*` with your endpoints, add each new route file to `lib/routes.ts`, and update the title and `guidance` in `lib/router.ts`. Push to GitHub and Vercel redeploys.
</Accordion>

## Minimal server from scratch

The router runs on any fetch runtime, including Next.js, Hono, Bun, and Node. Below is a complete server in one file, using Hono on Node:

<Steps>
  <Step title="Create the project">
    ```bash theme={null}
    mkdir my-api && cd my-api
    npm init -y
    npm i @agentcash/router hono @hono/node-server zod
    npm i -D tsx
    ```
  </Step>

  <Step title="Write the server">
    ```typescript server.ts theme={null}
    import { serve } from '@hono/node-server';
    import { Hono } from 'hono';
    import { createRouterFromEnv } from '@agentcash/router';
    import { z } from 'zod';

    const router = createRouterFromEnv({
      title: 'Quote API',
      description: 'Pay-per-call quotes.',
      guidance: 'GET /api/health is free. POST /api/quote with { topic } returns a quote for $0.001.',
    });

    router
      .route('quote')
      .paid('0.001')
      .body(z.object({ topic: z.string() }))
      .description('Random quote for a topic')
      .handler(async ({ body }) => ({ quote: pickQuote(body.topic) }));

    router
      .route({ path: 'health', method: 'GET' })
      .unprotected()
      .handler(async () => ({ ok: true }));

    const app = new Hono();
    app.route('/', router.hono());
    serve({ fetch: app.fetch, port: 3000 });
    ```
  </Step>

  <Step title="Set the environment and run">
    ```bash theme={null}
    export BASE_URL=http://localhost:3000   # 402 realm + OpenAPI server URL
    export EVM_PAYEE_ADDRESS=0x...          # receives payments
    export CDP_API_KEY_ID=...               # Coinbase Developer Platform key
    export CDP_API_KEY_SECRET=...           #   (free tier: portal.cdp.coinbase.com)

    npx tsx server.ts                       # http://localhost:3000
    ```

    Routes serve at `/api/*`, and discovery (`/openapi.json`, `/llms.txt`) works immediately.
  </Step>

  <Step title="Deploy anywhere">
    The server is a plain Node process: deploy it to Fly, Railway, a VPS, or any container host. Set `BASE_URL` to your public origin (it's the 402 realm and OpenAPI server URL, so it must match the domain agents call), and add an Upstash KV for production. See [Configuration](/router/configuration#kv-store).
  </Step>
</Steps>

The runnable version of this server lives at [`examples/hono`](https://github.com/merit-systems/agentcash-router/tree/main/examples/hono). Bun, Deno, and Cloudflare Workers work the same way via `router.fetch`. See [Hosting](/router/hosting).

## Add to an existing app (Next.js)

<Steps>
  <Step title="Install">
    ```bash theme={null}
    pnpm add @agentcash/router zod
    ```

    `zod` (v4) is a peer dependency.
  </Step>

  <Step title="Create the router">
    `createRouterFromEnv` reads config from `process.env` and validates every value up front. Set `EVM_PAYEE_ADDRESS`, `CDP_API_KEY_ID`, and `CDP_API_KEY_SECRET` (plus `BASE_URL` outside Vercel).

    ```typescript lib/router.ts theme={null}
    import { createRouterFromEnv } from '@agentcash/router';

    export const router = createRouterFromEnv({
      title: 'My API',
      description: 'Pay-per-call search.',
      guidance: 'POST /search with { q: string }. Returns top 10 results.',
    });
    ```
  </Step>

  <Step title="Register routes">
    One side-effect module registers every route:

    ```typescript lib/routes.ts theme={null}
    import { z } from 'zod';
    import { router } from './router';

    router
      .route('search')
      .paid('0.01')
      .body(z.object({ q: z.string() }))
      .handler(async ({ body }) => search(body.q));
    ```
  </Step>

  <Step title="Serve it">
    <CodeGroup>
      ```typescript Next.js catch-all theme={null}
      // app/api/[[...route]]/route.ts
      import '@/lib/routes'; // side-effect import: registers all routes
      import { router } from '@/lib/router';
      import { nextHandlers } from '@agentcash/router/next';

      export const { GET, POST, PUT, PATCH, DELETE } = nextHandlers(router);
      ```

      ```typescript Hono / Bun / Node theme={null}
      import { serve } from '@hono/node-server';
      import './routes';
      import { router } from './router';

      serve({ fetch: router.fetch, port: 3000 });
      ```
    </CodeGroup>

    On Next.js, add the root discovery aliases with two one-line route files. See [Hosting](/router/hosting#discovery-endpoints).
  </Step>
</Steps>

## Test the 402 flow

An unpaid request gets a `402` whose challenge lives in headers:

```bash theme={null}
curl -i -X POST https://api.example.com/api/search \
  -H 'content-type: application/json' -d '{"q":"hello"}'
```

Pay it with any x402 or MPP client:

```bash theme={null}
# AgentCash CLI: auto-negotiates x402 or MPP
npx agentcash fetch https://api.example.com/api/search -m POST -b '{"q":"hello"}'

# mppx CLI: MPP reference client
npx mppx https://api.example.com/api/search -J '{"q":"hello"}'
```
