Prediction Hunt/ API
WebSockets / Overview

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).

python
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.

  1. Authenticate Query parameter or auth message.
  2. Subscribe with market_ids and/or group_ids per channel rules.
  3. Receive streaming updates and optional snapshot messages after subscribe.
Keep-alive: The server sends WebSocket ping frames every 30 seconds. Clients should respond with pong automatically. You may also send {"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, optional market_ids, group_ids
  • unsubscribe — same fields; omit ids to drop the entire channel subscription
  • heartbeat — application-level ping

Server → client

  • subscribed, unsubscribed
  • error, warning (see error table)
  • pong
  • Data payloads: channel, type, ts, data
subscribed
json
{
"type": "subscribed",
"channel": "prices",
"market_ids": ["12345"],
"group_ids": null
}
error
json
{
"type": "error",
"code": "CHANNEL_FORBIDDEN",
"message": "Your tier does not have access to the arb channel.",
"channel": "arb"
}

Channels

Tier Limits

TierChannelsConnectionsSubs / connSubs / channel
Free0
Devprices, smart_money, fade_finder35025
ProAll10200100
EnterpriseAll501000500

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).

server → client (shape)
json
{
"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

CodeKindMeaning
AUTH_FAILEDerrorInvalid, inactive, expired API key, or authentication timeout.
AUTH_REQUIREDerrorFirst message after connect was not auth (when using post-connect auth).
ALREADY_AUTHENTICATEDerrorSent auth message after the connection was already authenticated.
CHANNEL_FORBIDDENerrorYour API key tier cannot subscribe to this channel.
CONNECTION_LIMITerrorToo many concurrent WebSocket connections for your tier.
INVALID_MESSAGEerrorMalformed JSON or invalid action / validation error.
RATE_LIMITEDerrorToo many inbound messages per second (10/sec).
SUBSCRIPTION_LIMITerrorExceeded per-connection or per-channel subscription caps.
TIER_FORBIDDENerrorYour tier has no WebSocket access (e.g. free tier).
UNKNOWN_CHANNELerrorSubscribe referenced a channel name that does not exist.
UNKNOWN_IDwarningSome market_ids or group_ids could not be resolved when subscribing; snapshots may be skipped for those ids.

Connection Lifecycle

  1. Open WebSocket with valid API key (query or first-frame auth).
  2. Send subscribe for each channel scope you need.
  3. Process subscribed, then data messages and optional warning.
  4. On disconnect, reconnect with exponential backoff; resubscribe after connect.

Best Practices

  • Subscribe only to markets and groups you need — reduces load and noise.
  • Handle error and warning without 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.