WebSocket API
Stream real-time prediction market data over one persistent connection. Subscribe to price updates, arbitrage, +EV signals, orderbook changes, and market lifecycle events — no polling required.
Quick Start
Connect with your API key (query string or first-frame auth), then send subscribe messages for the channels you need. Messages arrive as JSON with a consistent envelope (see below).
import asyncio, json, websockets, os async def main(): uri = "wss://ws.predictionhunt.com?api_key=" + os.environ["PREDICTION_HUNT_API_KEY"] async with websockets.connect(uri) as ws: await ws.send(json.dumps({ "action": "subscribe", "channel": "prices", "market_ids": ["12345", "67890"] })) async for message in ws: data = json.loads(message) print(data.get("channel"), data.get("type"), data) asyncio.run(main())
Want to test messages interactively? Use the WebSocket Playground.
Connection URL
Production endpoint: wss://ws.predictionhunt.com. Health check (HTTP): GET /health on the same port.
- Authenticate — Query parameter or auth message.
- Subscribe with
market_idsand/orgroup_idsper channel rules. - Receive streaming updates and optional snapshot messages after subscribe.
{"action":"heartbeat"} and receive {"type":"pong"}.Control Messages (Send / Receive)
Unlike APIs that use subscription IDs (sid), Prediction Hunt uses a single JSON stream per connection. Client sends action messages; the server replies with type.
Client → server
auth—api_key(first message only if not using query auth)subscribe—channel, optionalmarket_ids,group_idsunsubscribe— same fields; omit ids to drop the entire channel subscriptionheartbeat— application-level ping
Server → client
subscribed,unsubscribederror,warning(see error table)pong- Data payloads:
channel,type,ts,data
{"type": "subscribed","channel": "prices","market_ids": ["12345"],"group_ids": null}
{"type": "error","code": "CHANNEL_FORBIDDEN","message": "Your tier does not have access to the arb channel.","channel": "arb"}
Channels
Each channel has its own subscription rules and payload types. Follow the links for requirements, subscribe examples, and field reference.
Bid/ask/last and volume.
Cross-platform arb opportunities.
+EV signals per match group.
Depth and top-of-book updates.
Polymarket whale-flow smart money alerts.
Polymarket whale-flow fade finder alerts.
Creations, resolutions, group events.
Tier Limits
| Tier | Channels | Connections | Subs / conn | Subs / channel |
|---|---|---|---|---|
| Free | — | 0 | — | — |
| Dev | prices, smart_money, fade_finder | 3 | 50 | 25 |
| Pro | All | 10 | 200 | 100 |
| Enterprise | All | 50 | 1000 | 500 |
Inbound messages are rate-limited to 10 per second per connection. Pricing · api@predictionhunt.com for Enterprise.
Data Envelope
Streaming updates use one JSON object per message. The data object repeats the payload fields from Redis (including a nested type for some channels).
{"channel": "prices","type": "price_update","ts": 1712847600.123,"data": { }}
After subscribe, prices, orderbook, smart_money, and fade_finder send cached snapshots as the same message types as live updates. Unresolved market_ids or group_ids produce a warning with code UNKNOWN_ID.
Error and Warning Codes
| Code | Kind | Meaning |
|---|---|---|
| AUTH_FAILED | error | Invalid, inactive, expired API key, or authentication timeout. |
| AUTH_REQUIRED | error | First message after connect was not auth (when using post-connect auth). |
| ALREADY_AUTHENTICATED | error | Sent auth message after the connection was already authenticated. |
| CHANNEL_FORBIDDEN | error | Your API key tier cannot subscribe to this channel. |
| CONNECTION_LIMIT | error | Too many concurrent WebSocket connections for your tier. |
| INVALID_MESSAGE | error | Malformed JSON or invalid action / validation error. |
| RATE_LIMITED | error | Too many inbound messages per second (10/sec). |
| SUBSCRIPTION_LIMIT | error | Exceeded per-connection or per-channel subscription caps. |
| TIER_FORBIDDEN | error | Your tier has no WebSocket access (e.g. free tier). |
| UNKNOWN_CHANNEL | error | Subscribe referenced a channel name that does not exist. |
| UNKNOWN_ID | warning | Some market_ids or group_ids could not be resolved when subscribing; snapshots may be skipped for those ids. |
Connection Lifecycle
- Open WebSocket with valid API key (query or first-frame auth).
- Send
subscribefor each channel scope you need. - Process
subscribed, then data messages and optionalwarning. - On disconnect, reconnect with exponential backoff; resubscribe after connect.
Best Practices
- Subscribe only to markets and groups you need — reduces load and noise.
- Handle
errorandwarningwithout crashing; reconnect on auth failures. - Keep API keys server-side; never embed them in public client apps.
- For orderbook, merge snapshot and incremental updates in order (see channel docs).
Ready to stream?
Upgrade for real-time access
WebSocket channels are available on Dev, Pro, and Enterprise tiers. Get instant price feeds, smart money alerts, fade finder alerts, arb alerts, +EV signals, and more — delivered the moment they happen.