Skip to main content
A trending feed is a list ranked by recent activity (volume, trade count, unique traders) that updates as activity changes. Struct exposes the data in two layers: REST listings to seed initial state, and the corresponding stream rooms to push deltas. Polymarket data is split into two surfaces, events (multi-market questions) and markets (single conditions), so this recipe covers both side by side.

When to use this

  • Discovery surfaces: homepage rails, “what’s hot now” widgets, category browsers.
  • Live leaderboards ranked by 24h volume, trade count, or unique traders.
  • Any UI where a row’s metrics dictate ranking and the ranking itself shifts in real time.

Choose your surface

Both stream rooms push full rows (not deltas) for whichever rows changed since the last flush tick, so client merging is by primary key (id for events, condition_id for markets) and re-ranking happens on each tick.

Step 1: seed from REST

Both row shapes carry a metrics map keyed by timeframe (1m, 5m, 30m, 1h, 6h, 24h, 7d, 30d) with volume, fees, txns, and unique_traders per window. Pick the timeframe that matches the rail’s framing and sort by it client-side.

Step 2: subscribe to deltas

Both stream rooms accept the same filters as their REST list counterparts and push every matching row that changed.
See Events Stream and Markets Stream for the full payload schemas.

Step 3: re-rank on each tick

Keep an in-memory map keyed by primary key, merge each pushed row in place, then re-sort. Quiet rows produce zero messages, so re-ranking is bounded by how many rows actually shifted.

Choosing a cadence

Each stream room offers four flush slots: interval_ms of 500, 1000, 3000, or 10000. Pick 1000 for an interactive trending rail, 3000 for a sidebar widget, 10000 for a low-traffic dashboard. Each (interval_ms, mode) pair is its own slot; up to 8 slots per room.

Common combinations

Follow-on

If trending also needs to highlight markets paying CLOB rewards, the Markets Stream row carries a clob_rewards[] array and a total_daily_rate summary field per row.
Last modified on April 28, 2026