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

# Events Stream

> Stream real-time Polymarket event rows with filter or ids mode and configurable cadence.

<Note>
  **Room ID:** `polymarket_events_stream` \
  **Endpoint:** `wss://api.struct.to/ws` \
  **Rate:** 0.025 credits per message
</Note>

Low-latency push feed of `PolymarketEvent` rows — same shape that `GET /polymarket/events` returns. The server maintains an in-memory cache of **open** events only, refreshed via a slow full poll plus a fast 500ms newest-first poll, and merged live from the `prediction_event_metrics` and `prediction_trades` Kafka streams with per-timeframe block/timestamp ordering.

No initial snapshot is pushed on subscribe. Clients seed local state from `GET /polymarket/events` and then apply deltas from this stream.

<Tip>
  **Related guide:** [Building a live trending feed](/guides/real-time-trending-events-and-markets) seeds from the events list and pushes deltas through this stream.
</Tip>

## Subscription model

Each client has up to **8 active slots per room** (4 cadences × 2 modes). Re-subscribing to the same `(interval_ms, mode)` pair replaces the previous subscription. Unsubscribe one slot with `action: "unsubscribe"` plus `interval_ms` and `mode`, or clear everything with `action: "unsubscribe_all"`.

* **Cadence (`interval_ms`):** `500`, `1000`, `3000`, or `10000`. Each cadence is a separate flush bucket.
* **Filter mode:** evaluated in-memory on every flush against rows that actually changed since the last tick. Same validation as the REST list endpoint.
* **Ids mode:** filter by explicit `event_slugs` and/or `event_ids`. Max **500 ids** per subscription.

Updates fire only when a cache row is dirtied by (a) a fresh Kafka metric snapshot with `latest_block >= cached`, (b) a confirmed trade with `block >= cached`, (c) a slow-poll field diff, or (d) the fast newest-first poll discovering a brand-new event. Quiet events produce zero messages.

## Subscribe

### Message fields

| Field         | Type                                                | Required                    | Description                                   |
| ------------- | --------------------------------------------------- | --------------------------- | --------------------------------------------- |
| `action`      | `"subscribe" \| "unsubscribe" \| "unsubscribe_all"` | Yes                         | Slot lifecycle action.                        |
| `interval_ms` | `500 \| 1000 \| 3000 \| 10000`                      | For subscribe / unsubscribe | Flush cadence. Defaults to `1000` if omitted. |
| `mode`        | `"filter" \| "ids"`                                 | No                          | Subscription mode. Defaults to `filter`.      |
| `filter`      | `EventsStreamFilter`                                | `mode=filter` only          | Filter body; all fields optional.             |
| `event_slugs` | `string[]`                                          | `mode=ids` only             | Event slugs to watch.                         |
| `event_ids`   | `string[]`                                          | `mode=ids` only             | Event ids to watch.                           |

### Filter fields (`mode=filter`)

`search` is a case-insensitive substring match on `title` (3–100 chars). All other fields follow the same validation as the REST list endpoint (timeframe, list size caps).

### Example — filter mode

```json theme={null}
{
  "type": "join_room",
  "payload": {
    "room_id": "polymarket_events_stream"
  }
}
```

```json theme={null}
{
  "type": "room_message",
  "payload": {
    "room_id": "polymarket_events_stream",
    "message": {
      "action": "subscribe",
      "interval_ms": 1000,
      "mode": "filter",
      "filter": {
        "search": "election",
        "timeframe": "24h",
        "min_volume": 10000
      }
    }
  }
}
```

### Example — ids mode

```json theme={null}
{
  "type": "room_message",
  "payload": {
    "room_id": "polymarket_events_stream",
    "message": {
      "action": "subscribe",
      "interval_ms": 500,
      "mode": "ids",
      "event_slugs": ["us-election-2028"],
      "event_ids": ["12345"]
    }
  }
}
```

### Unsubscribe one slot

```json theme={null}
{
  "type": "room_message",
  "payload": {
    "room_id": "polymarket_events_stream",
    "message": {
      "action": "unsubscribe",
      "interval_ms": 500,
      "mode": "ids"
    }
  }
}
```

### Response

```json theme={null}
{
  "type": "events_stream_subscribe_response",
  "room_id": "polymarket_events_stream",
  "data": {
    "mode": "ids",
    "interval_ms": 500,
    "event_slugs": ["us-election-2028"],
    "rejected": [],
    "error": null
  }
}
```

## Events

### `events_stream_update`

Server-pushed event fired only for rows that changed AND matched this subscription since the last flush tick. `data` contains **full** `PolymarketEvent` rows — not deltas — so clients should merge by `id`.

#### Envelope

| Field         | Type                           | Description                                              |
| ------------- | ------------------------------ | -------------------------------------------------------- |
| `type`        | `"events_stream_update"`       | Envelope discriminator.                                  |
| `room_id`     | `"polymarket_events_stream"`   | Room identifier.                                         |
| `mode`        | `"filter" \| "ids"`            | The mode this subscription was created with.             |
| `interval_ms` | `500 \| 1000 \| 3000 \| 10000` | The cadence slot this event is flushed under.            |
| `data`        | `PolymarketEvent[]`            | Full event rows, same shape as `GET /polymarket/events`. |

#### `PolymarketEvent`

| Field                | Type                                        | Description                                                             |
| -------------------- | ------------------------------------------- | ----------------------------------------------------------------------- |
| `id`                 | `string`                                    | Event ID.                                                               |
| `event_slug`         | `string \| null`                            | URL-safe event slug.                                                    |
| `title`              | `string \| null`                            | Human-readable title.                                                   |
| `ticker`             | `string \| null`                            | Short ticker, when present.                                             |
| `description`        | `string \| null`                            | Long description.                                                       |
| `resolution_source`  | `string \| null`                            | Resolution source URL.                                                  |
| `category`           | `string \| null`                            | Primary category label.                                                 |
| `image_url`          | `string \| null`                            | CDN image URL.                                                          |
| `market_count`       | `integer`                                   | Number of child markets.                                                |
| `created_time`       | `integer \| null`                           | Unix seconds.                                                           |
| `closed_time`        | `integer \| null`                           | Unix seconds.                                                           |
| `start_time`         | `integer \| null`                           | Unix seconds.                                                           |
| `end_time`           | `integer \| null`                           | Unix seconds.                                                           |
| `neg_risk`           | `boolean`                                   | Whether this event uses the neg-risk market.                            |
| `neg_risk_market_id` | `string \| null`                            | Neg-risk market ID, when applicable.                                    |
| `game_status`        | `string \| null`                            | Sports-event game status.                                               |
| `show_market_images` | `boolean`                                   | Whether child market images should be shown.                            |
| `status`             | `string \| null`                            | `"open"` or `"closed"`.                                                 |
| `metrics`            | `Record<Timeframe, SimpleTimeframeMetrics>` | Keyed by timeframe (`1m`, `5m`, `30m`, `1h`, `6h`, `24h`, `7d`, `30d`). |
| `tags`               | `PolymarketTag[]`                           | Event tags.                                                             |
| `markets`            | `EventMarket[]`                             | Child markets with enriched outcomes.                                   |
| `series`             | `PolymarketSeries \| null`                  | Parent series, when present.                                            |

#### `SimpleTimeframeMetrics`

| Field            | Type      | Description                            |
| ---------------- | --------- | -------------------------------------- |
| `volume`         | `number`  | USD volume within the window.          |
| `fees`           | `number`  | USD fees within the window.            |
| `txns`           | `integer` | Trade count within the window.         |
| `unique_traders` | `integer` | Unique wallet count within the window. |

#### `PolymarketTag`

| Field   | Type             | Description    |
| ------- | ---------------- | -------------- |
| `id`    | `string`         | Tag ID.        |
| `label` | `string`         | Display label. |
| `slug`  | `string \| null` | URL-safe slug. |

#### `EventMarket`

| Field                   | Type                         | Description                                |
| ----------------------- | ---------------------------- | ------------------------------------------ |
| `condition_id`          | `string`                     | 0x-prefixed condition ID.                  |
| `id`                    | `string \| null`             | Market ID.                                 |
| `title`                 | `string \| null`             | Market title.                              |
| `question`              | `string`                     | Market question.                           |
| `market_slug`           | `string`                     | URL-safe market slug.                      |
| `status`                | `string`                     | Market status.                             |
| `created_time`          | `integer \| null`            | Unix seconds.                              |
| `end_time`              | `integer \| null`            | Unix seconds.                              |
| `volume`                | `number \| null`             | Lifetime USD volume.                       |
| `liquidity_usd`         | `number \| null`             | Current USD liquidity.                     |
| `volume_24hr`           | `number \| null`             | 24h USD volume.                            |
| `image_url`             | `string \| null`             | CDN image URL.                             |
| `market_maker_address`  | `string \| null`             | Market maker contract.                     |
| `creator`               | `string \| null`             | Wallet address of creator.                 |
| `category`              | `string \| null`             | Category label.                            |
| `accepting_orders`      | `boolean \| null`            | Whether CLOB is accepting new orders.      |
| `uma_resolution_status` | `string \| null`             | UMA oracle resolution status.              |
| `clob_rewards`          | `ClobReward[]`               | Active reward configs.                     |
| `outcomes`              | `EventMarketOutcome[]`       | Market outcomes.                           |
| `winning_outcome`       | `EventMarketOutcome \| null` | Resolved winning outcome, when applicable. |

#### `EventMarketOutcome`

| Field           | Type              | Description                                 |
| --------------- | ----------------- | ------------------------------------------- |
| `name`          | `string`          | Outcome label (e.g. `"Yes"`).               |
| `price`         | `number \| null`  | Latest price (0 – 1).                       |
| `position_id`   | `string \| null`  | ERC-1155 outcome token ID (decimal string). |
| `outcome_index` | `integer \| null` | 0-indexed outcome position.                 |

#### `PolymarketSeries`

| Field           | Type              | Description                              |
| --------------- | ----------------- | ---------------------------------------- |
| `id`            | `string`          | Series ID.                               |
| `slug`          | `string \| null`  | URL-safe slug.                           |
| `ticker`        | `string \| null`  | Ticker, when present.                    |
| `title`         | `string \| null`  | Display title.                           |
| `description`   | `string \| null`  | Long description.                        |
| `series_type`   | `string \| null`  | Series type discriminator.               |
| `recurrence`    | `string \| null`  | Recurrence cadence (e.g. `"daily"`).     |
| `layout`        | `string \| null`  | UI layout hint.                          |
| `image_url`     | `string \| null`  | CDN image URL.                           |
| `icon_url`      | `string \| null`  | CDN icon URL.                            |
| `active`        | `boolean`         | Whether the series is currently active.  |
| `closed`        | `boolean`         | Whether the series is closed.            |
| `archived`      | `boolean`         | Whether archived.                        |
| `featured`      | `boolean`         | Whether featured in discovery surfaces.  |
| `restricted`    | `boolean`         | Whether the series is region-restricted. |
| `pyth_token_id` | `string \| null`  | Pyth price feed ID, when applicable.     |
| `cg_asset_name` | `string \| null`  | CoinGecko asset name, when applicable.   |
| `start_date`    | `integer \| null` | Unix seconds.                            |
| `event_count`   | `integer`         | Number of child events.                  |

See the [Markets Stream](/websockets/rooms/markets-stream) room for the `ClobReward` shape — it is shared across both stream rooms.

#### Example

```json theme={null}
{
  "type": "events_stream_update",
  "room_id": "polymarket_events_stream",
  "mode": "ids",
  "interval_ms": 500,
  "data": [
    {
      "id": "12345",
      "event_slug": "us-election-2028",
      "title": "US Presidential Election 2028",
      "ticker": "PRES28",
      "description": "Who will win the 2028 US presidential election?",
      "resolution_source": "https://example.com/resolution",
      "category": "politics",
      "image_url": "https://cdn.struct.to/events/us-election-2028.png",
      "market_count": 8,
      "created_time": 1743400000,
      "closed_time": null,
      "start_time": 1743500000,
      "end_time": 1893456000,
      "neg_risk": true,
      "neg_risk_market_id": "0xneg...",
      "game_status": null,
      "show_market_images": true,
      "status": "open",
      "metrics": {
        "24h": { "volume": 125000.5, "fees": 250.0, "txns": 340, "unique_traders": 85 },
        "7d": { "volume": 810000.0, "fees": 1620.0, "txns": 2210, "unique_traders": 540 }
      },
      "tags": [{ "id": "42", "label": "Politics", "slug": "politics" }],
      "markets": [
        {
          "condition_id": "0xabc123...",
          "id": "m_1",
          "title": "Candidate A wins",
          "question": "Will Candidate A win the 2028 election?",
          "market_slug": "candidate-a-wins-2028",
          "status": "open",
          "created_time": 1743400000,
          "end_time": 1893456000,
          "volume": 42000.0,
          "liquidity_usd": 15000.0,
          "volume_24hr": 3200.0,
          "image_url": "https://cdn.struct.to/markets/candidate-a.png",
          "market_maker_address": "0xmm...",
          "creator": "0xcreator...",
          "category": "politics",
          "accepting_orders": true,
          "uma_resolution_status": null,
          "clob_rewards": [],
          "outcomes": [
            { "name": "Yes", "price": 0.42, "position_id": "12345678901234567", "outcome_index": 0 },
            { "name": "No",  "price": 0.58, "position_id": "98765432109876543", "outcome_index": 1 }
          ],
          "winning_outcome": null
        }
      ],
      "series": null
    }
  ]
}
```
