Skip to main content
PolyNode uses per-key rate limiting to ensure fair usage. Limits scale with your plan.

Tier limits

Firehose = a WebSocket subscription with no filters applied. It receives every event (all settlements, trades, blocks, etc.) at full throughput. Filtered subscriptions — where you specify wallets, tokens, slugs, or size thresholds — use far less bandwidth and don’t count toward your firehose limit.
FreeStarter ($50/mo)Growth ($200/mo)Enterprise ($750/mo)
Rate limit120 req/min (2 QPS)6,000 req/min (100 QPS)18,000 req/min (300 QPS)60,000 req/min (1,000 QPS)
WebSocket connections15003,000Unlimited
Firehose connections1100750Unlimited
Orderbook connections1210Unlimited
Orderbook market subsUnlimitedUnlimitedUnlimitedUnlimited
API keys131025
Snapshot size20100200500
Key generation1 per IP per dayVia dashboardVia dashboardVia dashboard
SupportCommunityEmailPriorityDedicated + Slack
Enterprise includes dedicated server infrastructure. Contact josh@quantish.live before activation.

How it works

  • Rate limits are tracked per API key using a sliding window.
  • When you exceed the limit, you’ll receive a 429 Too Many Requests response.
  • The error message includes a Unix timestamp for when you can retry.

Best practices

Use WebSocket for real-time data

Instead of polling REST endpoints, connect via WebSocket for live updates:
// Instead of polling /v1/markets every 5 seconds (12 req/min)...
// Use WebSocket (1 connection, unlimited events)
const ws = new WebSocket("wss://ws.polynode.dev/ws?key=pn_live_YOUR_KEY");
ws.send(JSON.stringify({
  action: "subscribe",
  type: "settlements",
}));

Cache metadata locally

Market metadata (question, slug, outcomes) changes infrequently. Cache it and only refresh periodically:
// Fetch full market list once
const markets = await fetch("/v1/markets?count=1000", { headers })
  .then((r) => r.json());

// Cache by token_id
const cache = new Map(markets.markets.map((m) => [m.token_id, m]));

// Use cache for lookups, refresh every 5 minutes

Batch where possible

Use /v1/markets?count=1000 instead of individual /v1/markets/:id calls to reduce requests.

Use filtered subscriptions

WebSocket subscriptions with filters reduce message volume and processing overhead:
{
  "action": "subscribe",
  "type": "settlements",
  "filters": {
    "tokens": ["specific-token-id"],
    "min_size": 100
  }
}

Expected WebSocket throughput

WebSocket subscriptions are not rate-limited by requests/min, but message volume varies significantly by subscription type:
SubscriptionTypical messages/secNotes
Firehose (no filters)50–150~0.5–1.5 Mbps uncompressed
Filtered (1 market)1–20Depends on market activity
Filtered (1 wallet)0–5Most wallets trade infrequently
Blocks only~0.5One per Polygon block (~2s)
status_update events arrive in bursts (30–80 per block). If you don’t need confirmation tracking, exclude them from your event_types filter to reduce volume.

Data endpoint limits

The wallet and market data endpoints proxy to upstream sources and have their own rate limits, separate from your per-key limit.

Standard data endpoints

These endpoints share your plan’s normal rate limit:
  • /v1/wallets/{addr}/positions
  • /v1/wallets/{addr}/trades
  • /v1/wallets/positions (multi-wallet)
  • /v1/markets/{id}/positions
  • /v1/markets/{id}/trades
Batch requests (multiple wallets) count each wallet as one request toward your limit. For example, a 5-wallet batch counts as 5 requests.

Heavy endpoints RATE LIMITED

Some data endpoints fan out many upstream requests per call and have a stricter per-key limit:
EndpointLimitWhy
/v1/markets/{id}/positions?includeTrades=true60 req/min per keyEach call fetches trade history for every position holder in the market (can be 50-100+ upstream calls)
When this limit is exceeded, you’ll receive a 429 response with:
{
  "error": "includeTrades rate limit exceeded (60/min). Retry after 1774108000."
}
If you only need position sizes and P&L, omit includeTrades to use the standard rate limit. Only add includeTrades=true when you specifically need firstTradeAt and lastTradeAt timestamps.
For real-time data, use the WebSocket stream instead of polling these endpoints.

Higher limits

Upgrade your plan at polynode.dev/pricing for higher rate limits and more WebSocket connections.