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

# Try the API without a key

> Call every CabalSpy REST endpoint and WebSocket stream without signing up, on the public demo: 20 requests per IP per day, data delayed 15 minutes.

Every endpoint and every stream can be tried without an account or API key. The public demo is meant for reading the docs, testing a request and letting AI agents explore the API. It is not meant for production.

<Warning>
  The demo is only for trying CabalSpy out. To build on it you need an API key, passed as shown on [API Key](/api-key) and in every endpoint's examples. [Get a free key](https://apidashboard.cabalspy.xyz/register).
</Warning>

The **Try it** button on every endpoint page uses the demo automatically: leave the `api_key` field empty and press Send.

## Two ways in

<CodeGroup>
  ```bash No key at all theme={null}
  curl "https://demo-api.cabalspy.xyz/v1/wallets?blockchain=solana&type=kol"
  ```

  ```bash Demo key on the normal API theme={null}
  curl "https://api.cabalspy.xyz/v1/wallets?blockchain=solana&type=kol&api_key=demo"
  ```
</CodeGroup>

Both are the same demo with the same limits. `demo-api.cabalspy.xyz` adds the demo key for you, so a link or an example request works as it is. The key `demo` works anywhere a normal key does: in the SDKs, the MCP server and WebSocket connections.

## Limits

| | Demo | Free test key |
| - | - | - |
| Requests | 20 per IP per day | 1,000 per month |
| Data | Delayed 15 minutes | Real time |
| Rows per list | At most 5 | Full |
| WebSocket | 1 connection per IP, 3 subscriptions, 30 minutes | Full |
| Signup | None | Free account |

The 20 requests are shared between REST and WebSocket; opening a WebSocket connection counts as one request. The counter resets at 00:00 UTC. IPv6 addresses are counted per /64 network.

Events younger than 15 minutes are left out of every answer, so the newest trade you see is about 15 minutes old. Totals and profiles are current, but lists stop at 5 rows and pagination always reports `has_more: false`.

## How a demo answer looks

Every demo answer carries a `demo` block and the header `X-CabalSpy-Demo: true`, so you, your code and an AI agent can always tell demo data from live data.

```json theme={null}
{
  "success": true,
  "data": { "...": "..." },
  "demo": {
    "notice": "Public demo: events delayed 15 minutes, at most 5 rows, 20 requests per IP per day.",
    "remaining_today": 19,
    "upgrade": {
      "test_key": "https://apidashboard.cabalspy.xyz/",
      "pay_per_call": "https://www.cabalspy.xyz/x402/",
      "docs": "https://docs.cabalspy.xyz"
    }
  }
}
```

The header `X-Demo-Remaining` carries the same count as `remaining_today`.

When the 20 requests are used up, the API answers with HTTP 429:

```json theme={null}
{
  "success": false,
  "error": {
    "code": "demo_limit_reached",
    "message": "The demo allows 20 requests per IP per day. Get a free test key for 1,000 real-time requests a month.",
    "resets_in_seconds": 42753
  },
  "demo": true
}
```

## WebSocket

```javascript theme={null}
const ws = new WebSocket("wss://demo-api.cabalspy.xyz/ws");
// or: new WebSocket("wss://stream.cabalspy.xyz?apiKey=demo")

ws.onopen = () => {
  ws.send(JSON.stringify({ op: "subscribe", stream: "tx", blockchain: "solana", type: "kol", token: "*" }));
};
ws.onmessage = (e) => console.log(JSON.parse(e.data));
```

The welcome message carries a `demo` block. Replies such as `subscribed` arrive at once; trade and stream events arrive 15 minutes after they happened. The connection closes after 30 minutes. A second demo connection from the same IP is refused while the first is open.

## SDKs and the MCP server

<CodeGroup>
  ```ts TypeScript theme={null}
  import { CabalSpy } from 'cabalspy'; // 0.3.0 or later

  const client = CabalSpy.demo();
  const board = await client.wallets.leaderboard({ blockchain: 'solana', type: 'kol', period: '7d' });
  console.log(client.lastDemo?.remaining_today);
  ```

  ```python Python theme={null}
  from cabalspy import CabalSpy  # 0.3.0 or later

  client = CabalSpy.demo()
  board = client.wallets.leaderboard(blockchain="solana", type="kol", period="7d")
  print(client.last_demo["remaining_today"])
  ```

  ```rust Rust theme={null}
  use cabalspy::CabalSpy; // 0.2 or later

  let client = CabalSpy::demo()?;
  ```
</CodeGroup>

The SDKs raise a dedicated error when the demo budget is spent (`DemoLimitError` in TypeScript and Python, `Error::DemoLimit` in Rust) and do not retry it, because the budget only resets the next day.

The [MCP server](/mcp-server) uses the demo automatically when you connect without a key, so an assistant can answer its first questions before anyone signs up.

## When the demo is not enough

<CardGroup cols={2}>
  <Card title="Free test key" icon="key" href="/api-key">
    1,000 real-time requests a month, full lists, every stream. Free account, no credit card.
  </Card>

  <Card title="Pay per request" icon="coins" href="/x402">
    AI agents pay per call in USDC with x402. No account, no key.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.