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

> ## Agent Instructions
> API requests use the base URL https://api.unusualwhales.com and require a bearer token in the `Authorization` header (`Authorization: Bearer <API_KEY>`). Create and manage API tokens at https://unusualwhales.com/dashboard/api.
> For live market data inside an AI tool, use the Unusual Whales MCP server at https://unusualwhales.com/public-api/mcp.
> Instructions for agents using Unusual Whales tools: https://unusualwhales.com/skill.md

# Periscope

> Receive live periscope market-maker greek exposures (gamma/charm/vanna) per strike & expiry for index tickers (SPX, VIX, XSP, NANOS). Not available on the enterprise and enterprise startup plans.

**NOTE:**
This is the documentation for websocket channels `periscope` and `periscope:<TICKER>`.
Websocket access for personal use is only available through the [Advanced plan](https://unusualwhales.com/pricing?product=api).
These channels are not available on the enterprise and enterprise startup plans; joining them returns an error.

You can find fully-functional examples that stream data from many channels here:

* Python: [https://github.com/unusual-whales/api-examples/tree/main/examples/ws-multi-channel-multi-output](https://github.com/unusual-whales/api-examples/tree/main/examples/ws-multi-channel-multi-output)
* Javascript: [https://github.com/unusual-whales/api-examples/tree/main/examples/ws-multi-channel-multi-output-nodejs](https://github.com/unusual-whales/api-examples/tree/main/examples/ws-multi-channel-multi-output-nodejs)

Connect to the websocket URI:

`wss://api.unusualwhales.com/socket?token=<YOUR_API_TOKEN>`

then `join` the channel you wish to stream: `periscope` for every index ticker at once,
or `periscope:SPX` for a single ticker.

Payload format:

Format for `periscope:<TICKER>`:

```
[
  "periscope:SPX",
  {
    "ticker": "SPX",
    "timestamp": 1726670396000,
    "total_rows": 11987,
    "has_more": true,
    "rows": [
      {
        "strike": "5200",
        "expiry": "2026-07-02",
        "gamma": 1234.5,
        "charm": -12.3,
        "vanna": 4.5
      },
      {
        "strike": "5225",
        "expiry": "2026-07-02",
        "gamma": 987.6,
        "charm": -10.1,
        "vanna": 3.2
      }
    ]
  }
]
```

The global `periscope` channel streams the same envelope frames for every index ticker,
tagged `periscope` (the `ticker` field distinguishes them):

```
[
  "periscope",
  {
    "ticker": "SPX",
    "timestamp": 1726670396000,
    "total_rows": 11987,
    "has_more": true,
    "rows": [
      {
        "strike": "5200",
        "expiry": "2026-07-02",
        "gamma": 1234.5,
        "charm": -12.3,
        "vanna": 4.5
      }
    ]
  }
]
```

Each frame carries a batch of up to 1024 strike/expiry rows. A full snapshot spans
several frames; all frames of one snapshot share the same `timestamp`, and a new
`timestamp` starts the next snapshot (snapshots are published about once a
minute). `has_more` is `true` on every frame but the last one of a snapshot, so
the frame with `"has_more": false` closes the board. Sum the `rows` lengths across
frames with the same `timestamp` and compare against `total_rows` to verify you
received the complete snapshot.

| Field | Type | Description |
| - | - | - |
| `ticker` | string | Index ticker (SPX, VIX, XSP, NANOS). |
| `timestamp` | int (ms) | Snapshot time, unix epoch milliseconds. Shared by every frame of the snapshot. |
| `total_rows` | int | Row count of the whole snapshot. |
| `has_more` | bool | More frames of this snapshot follow; `false` on the last frame. |
| `rows` | array | Up to 1024 rows per frame. |
| `rows[].strike` | decimal string | Strike price. |
| `rows[].expiry` | date string `YYYY-MM-DD` | Contract expiration. |
| `rows[].gamma`, `rows[].charm`, `rows[].vanna` | float | Market-maker greek exposure at this strike & expiry. |
