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

# Chainlink Spot and TWAP Prices

> Choose Chainlink spot, 30-second TWAP, 60-second TWAP, or both TWAP streams.

polynode offers Chainlink spot prices plus 30-second and 60-second
time-weighted average prices (TWAP) through the existing `chainlink` WebSocket
subscription.

The current default delivers both TWAP windows. Select spot or one TWAP window
explicitly when that is all your application needs.

## Choose spot

Add `price_source: "spot"`:

```json theme={null}
{
  "action": "subscribe",
  "type": "chainlink",
  "filters": {
    "feeds": ["BTC/USD"],
    "price_source": "spot"
  }
}
```

The acknowledgement confirms the selection:

```json theme={null}
{
  "type": "subscribed",
  "subscription_type": "chainlink",
  "price_source": "spot",
  "twap_windows": null
}
```

## Choose TWAP

Use `twap_windows` to select a lookback:

| Price selection | Filter                     | Acknowledgement `price_source` |
| --------------- | -------------------------- | ------------------------------ |
| 30-second TWAP  | `"twap_windows": [30]`     | `twap30`                       |
| 60-second TWAP  | `"twap_windows": [60]`     | `twap60`                       |
| Both TWAPs      | `"twap_windows": [30, 60]` | `both`                         |

For example, subscribe to both windows for BTC/USD and ETH/USD:

```json theme={null}
{
  "action": "subscribe",
  "type": "chainlink",
  "filters": {
    "feeds": ["BTC/USD", "ETH/USD"],
    "twap_windows": [30, 60]
  }
}
```

`30` and `60` are lookback windows, not update rates. Read
`twap_window_seconds` on each event instead of inferring the window from event
timing.

## Follow the current default

Omit both selectors to follow the current default:

```json theme={null}
{"action": "subscribe", "type": "chainlink"}
```

The acknowledgement returns `price_source: "follow_main"` and
`twap_windows: null`. The current default sends both the 30-second and
60-second TWAP streams.

## Selection rules

* `price_source` accepts `"spot"`.
* `twap_windows` accepts `[30]`, `[60]`, or `[30, 60]`.
* Do not combine `price_source: "spot"` with `twap_windows`.
* Omit `feeds` to receive every available pair.
* Spot and TWAP subscriptions begin with the next update. They do not include
  a snapshot, history, or replay.

## Identify each event

Every event keeps the existing `price_feed` shape and adds two fields that
identify the price type:

```json theme={null}
{
  "type": "price_feed",
  "feed": "BTC/USD",
  "timestamp": 1785178800,
  "is_twap": true,
  "twap_window_seconds": 30,
  "data": {
    "feed": "BTC/USD",
    "price": 65000.5,
    "bid": 65000.5,
    "ask": 65000.5,
    "timestamp": 1785178800,
    "is_twap": true,
    "twap_window_seconds": 30
  }
}
```

For spot events, `is_twap` is `false` and `twap_window_seconds` is `null`. For
TWAP events, `is_twap` is `true` and `twap_window_seconds` is `30` or `60`.

When both windows are selected, the two events for one feed are separate price
observations. Key application state by `feed` and `twap_window_seconds`, and
include `timestamp` when deduplicating delivery.

Existing clients can keep their WebSocket URL, API key, subscription type, and
existing JSON fields unchanged. Add a selector only when the application needs
spot or one exact TWAP window.
