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

# Agent Quickstart

> Fund one wallet with USDC on Base, run one script, and your agent is paying Otto's live x402 endpoints per call — no API key, no signup, no account.

You have an AI agent — Claude Code, Cursor, or anything that can run a Node.js script. This page gets that agent from zero to its first **paid, useful result** from Otto AI using nothing but a wallet with a little USDC on Base.

There is no signup and no API key. Otto's services speak [x402](/acp-swarm/x402), a pay-per-request standard: your agent requests an endpoint, receives `402 Payment Required`, signs a tiny USDC payment locally, retries, and gets the data. Every command on this page was run live against the production catalog before it was published.

***

## What you need

1. **Node.js 20 or later.** This guide was verified end-to-end on v22.
2. **A wallet with a few dollars of USDC on Base.** Cheap intelligence reads cost \$0.001 each, so even \$1 goes a long way. Buy USDC on any exchange and withdraw it on the **Base** network (native USDC, contract `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913`).
3. **That wallet's private key**, exported as an environment variable. It signs payment authorizations locally — it is never sent to Otto.

<Warning>
  Use a **fresh, dedicated wallet** that holds only what you plan to spend — never your main wallet's key. Any key you hand to agent tooling should be treated as disposable.
</Warning>

<Note>
  **No ETH needed.** x402 payments on Base are gasless USDC authorizations (EIP-3009) — the payment facilitator submits the on-chain transaction and pays the gas. Your wallet only needs USDC. Polygon and Solana USDC are also accepted; this guide pins Base as the simplest path.
</Note>

***

## Setup

Copy-paste, in a terminal:

```bash theme={null}
mkdir otto-agent && cd otto-agent
npm init -y
npm install @x402/axios @x402/evm axios viem
```

Give the session your payer key (`0x` + 64 hex characters — never commit it anywhere):

```bash theme={null}
export X402_PRIVATE_KEY=<YOUR_PRIVATE_KEY>
```

Create `otto.mjs`:

```javascript otto.mjs theme={null}
// otto.mjs — first paid call to Otto AI over x402
import axios from "axios";
import { wrapAxiosWithPayment, x402Client, decodePaymentResponseHeader } from "@x402/axios";
import { ExactEvmScheme } from "@x402/evm/exact/client";
import { toClientEvmSigner } from "@x402/evm";
import { privateKeyToAccount } from "viem/accounts";
import { createPublicClient, http } from "viem";
import { base } from "viem/chains";

// Your wallet. The key stays on your machine — it signs a USDC transfer
// authorization locally; it is never sent to Otto.
const account = privateKeyToAccount(process.env.X402_PRIVATE_KEY);
const publicClient = createPublicClient({ chain: base, transport: http() });

const client = new x402Client();
client.register("eip155:8453", new ExactEvmScheme(toClientEvmSigner(account, publicClient)));

const otto = wrapAxiosWithPayment(
  axios.create({ baseURL: "https://x402.ottoai.services", timeout: 60000 }),
  client,
);

// $0.001 USDC — the client sees the 402, signs the payment, retries, returns data.
const res = await otto.get("/crypto-news");
console.log(res.data);

const receipt = decodePaymentResponseHeader(
  res.headers["payment-response"] ?? res.headers["x-payment-response"],
);
console.log("\nSettled on-chain:", receipt?.transaction);
```

***

## First paid call

```bash theme={null}
node otto.mjs
```

That's it. Real output from a live run of exactly this script (abridged):

```text theme={null}
{
  status: 'success',
  data: {
    report: '## MARKET BRIEF\n' +
      '\n' +
      'Your Crypto News Brief\n' +
      '\n' +
      'Overview: The cryptocurrency market is currently characterized by robust
       stablecoin utility and increasing institutional interest, ...\n' +
      'Market Sentiment:\n' +
      'Overall Bull/Bear Score: 55\n' +
      ...
  }
}

Settled on-chain: 0x9853ee5619ee060318580f7adfbe685ab0a67f9c0f21c2a5c8e707061b84d2fe
```

What just happened:

1. Your request hit the paywall and got a `402` describing the price (\$0.001 USDC) and where to pay.
2. The client signed a USDC transfer authorization with your key — locally.
3. It retried the request with the signed payment attached.
4. Otto's facilitator settled it on Base and returned the data plus a settlement transaction hash you can check yourself on [Basescan](https://basescan.org).

Endpoints take query parameters the way you'd expect. Swap the request line for a token snapshot (also \$0.001, also verified live):

```javascript theme={null}
const res = await otto.get("/token-details?symbol=ETH");
```

***

## What else your wallet now buys

That one funded wallet is now a key to Otto's whole x402 catalog — market and token intelligence, KOL sentiment, token security scans, yield discovery, onchain analytics, web and domain intelligence, real-world data (FX, weather), AI research, image and video generation, and trade-execution services. The live endpoint list with current prices is always at:

* **Interactive explorer:** [x402.ottoai.services](https://x402.ottoai.services)
* **Machine-readable, for your agent:** [x402.ottoai.services/llm.txt](https://x402.ottoai.services/llm.txt)
* **JSON catalog:** [x402.ottoai.services/otto-x402-catalog.json](https://x402.ottoai.services/otto-x402-catalog.json)
* **Full reference with parameters and sample responses:** [x402 Storefront](/acp-swarm/x402)

<Tip>
  **Using Claude Code or Cursor?** Paste the setup above once, then tell your agent to fetch [`llm.txt`](https://x402.ottoai.services/llm.txt) and use `otto.mjs` as its template for calling any endpoint in the catalog. Not sure which endpoint fits a task? The [x402 Open Router](/acp-swarm/open-router) (`POST /meta-intelligence`, \$0.001) recommends the right one.
</Tip>

***

## Troubleshooting

The three failures new users actually hit — each reproduced live while writing this page:

| Symptom                                                                                                                      | Cause                                                                                                                                                                         | Fix                                                                                              |
| ---------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| Response is `{}`, status `402` after payment was attempted (or `decodePaymentResponseHeader` throws "not correctly encoded") | The wallet has **no USDC on Base** — the settlement reverted. The retry's `payment-required` header decodes to `invalid_payload: contract call failed: … execution reverted`. | Send USDC (native Base USDC, contract above) to the payer wallet. No ETH needed.                 |
| `Cannot read properties of undefined (reading 'slice')` on startup                                                           | `X402_PRIVATE_KEY` isn't set in this shell — `export` it again (it doesn't survive a new terminal).                                                                           | `export X402_PRIVATE_KEY=<YOUR_PRIVATE_KEY>` in the same shell you run `node` from.              |
| `invalid private key, expected hex or 32 bytes`                                                                              | The key is malformed — it must be `0x` followed by exactly 64 hex characters.                                                                                                 | Re-copy the key from your wallet's export screen; check for a missing `0x` prefix or truncation. |

Two smaller gotchas: save the script as **`.mjs`** (plain `.js` without `"type": "module"` in `package.json` breaks the `import` statements), and if a request sits until the timeout, just re-run it — a payment signature is only valid for a short window, so a stalled attempt should be retried fresh, never resumed.

Still stuck? [Getting help](/support-and-feedback/getting-help) lists the support channels.

***

## Custody, and what's coming

On this page, **you** hold the wallet: your key signs every payment locally, Otto never sees it, and every call is a discrete micro-payment you can audit on-chain. This bring-your-own-wallet rail is live today.

Separately, Otto's dApp accounts are agent-custodial today (an Otto-managed key signs); non-custodial Safe7579 accounts are in gated early access. A "fund one Safe once and Otto auto-pays your agent's calls under a capped, revocable permission" rail is part of that same gated early access — it is **not** live, and this page will link the exact steps when it is. Until then, the path above is the way in. Details: [Empire Access Layer](/account-and-settings/enterprise-agent-layer).
