Overview
Struct’s websocket API streams real-time Polymarket data directly to your application without polling REST. Connect once, subscribe to any number of rooms, and receive live updates for trades, prices, metrics, positions, PnL, order books, and more. Websockets are ideal for trading UIs, dashboards, and agents that need low-latency access to what’s happening on Polymarket right now. Every metric stream is backed by the same pre-computed materialised rows the REST API serves, so push values are consistent with what you’d pull on demand.Endpoints
There are two websocket endpoints:
This guide covers the Rooms endpoint. See Alerts for the alerts endpoint.
Authentication
Authenticate by appending your API key as a query parameter:token parameter. See Authentication for both flows.
Compression
High-throughput sockets can opt into zstd compression, negotiated once at the WebSocket upgrade with theX-Ws-Compression: zstd header or the ?compression=zstd query fallback. When enabled, room envelopes arrive as binary frames of zstd-compressed JSON. See Compression for decode examples and client support.
Your first connection
1
Create an account
Sign up at struct.to/dashboard and create an organisation.
2
Generate an API key
Open the API Keys page in your dashboard and create a new key. Copy the value somewhere safe; you won’t be able to view it again. See Authentication for key types, JWT public keys, and rotation.
3
Open a connection
Use any WebSocket client to connect. The example below connects, subscribes to the Trades room for a specific market, and logs messages as they arrive.
4
Receive events
Messages arrive as JSON with a
type field (the event name) and a message payload. See the individual room pages for the events each room emits.Connection lifecycle
A typical session follows the same sequence for every room:Message protocol
All messages sent and received are JSON. Client messages use atype and payload envelope:
Joining and subscribing
Subscribing to a room is a two-step flow:- Join the room with
join_room. - Configure the subscription by sending a
room_messagewithaction: "subscribe"and any filters.
subscribe message. The new filters replace the previous ones. Subscribe server-side rather than filter client-side: server-side filtering is free, while client-side filtering still bills you for the message.
Unsubscribing
To stop receiving messages from a room, sendunsubscribe_all followed by leave_room:
Keepalive
Send a ping every 30 seconds to keep the connection alive:{ "type": "pong" }, which you can safely ignore. The TypeScript SDK handles ping/pong automatically.
Firehose subscriptions
Most rooms acceptsubscribe_all: true on the subscribe message to receive every update on that stream instead of a targeted subset:
condition_ids, traders, wallets, and so on) are ignored while it’s set, while secondary filters like timeframes still apply. See Firehose for the per-room behaviour table and billing guidance.
Available rooms
Every room emits its own event type with a typed filter and payload. Click a room for the full schema.
Per-message pricing is on WebSocket Pricing.
Reconnection
Subscriptions live only for the lifetime of the connection. If the socket drops, you must reconnect and resubscribe. Use exponential backoff with jitter so transient outages don’t turn into thundering-herd reconnects.Connection limits
Each plan has a cap on concurrent connections across your organisation. A single connection can subscribe to many rooms, so you rarely need more than a handful of sockets in practice.
See Rate Limits for filter limits and the full per-key throughput matrix.
Next steps
- Browse the Rooms section for every available stream and its filters.
- Review WebSocket Pricing for per-message rates.
- Check out Alerts for webhook-style events over the same protocol.
- Read Best Practices for cost and resilience patterns.