# Periscope `GET` `https://api.unusualwhales.com/api/socket/periscope` **NOTE:** This is the documentation for websocket channels `periscope` and `periscope:`. 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=` 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:`: ``` [ "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. | ## Authentication ``` Authorization: Bearer YOUR_API_KEY ``` ## Example ### curl ```bash curl -X GET "https://api.unusualwhales.com/api/socket/periscope" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Accept: application/json" ``` ### Python ```python import http.client conn = http.client.HTTPSConnection("api.unusualwhales.com") headers = {"Authorization": "Bearer YOUR_API_KEY", "Accept": "application/json"} conn.request("GET", "/api/socket/periscope", headers=headers) response = conn.getresponse() print(response.read().decode("utf-8")) ``` ## Response Example ```json { "data": [] } ```