Skip to Content
StreamingOne Connection, Many Topics

One Connection, Many Topics

A single SharpAPI stream can cover everything you need — multiple sports, multiple leagues, multiple books, multiple events, and odds + every opportunity type — on one socket. You almost never need to open a stream per filter.

The per-key concurrent stream cap is 1 by default for every paid tier, with newer-wins displacement: a second connection from the same key kicks the older one. This page shows the patterns that make a single connection sufficient. If you genuinely need parallel sockets (multiple processes / machines), see Fleet & Multi-Process below.

Why one connection is enough

Every identity filter on the stream endpoint accepts a comma-separated list, and the channel parameter (all) merges odds and opportunity events into the same event stream. The server pre-serializes each cycle once and applies your filters per-connection, so wide filters are cheap — there’s no efficiency penalty for subscribing to “everything you care about” on one socket vs. splitting it.

FilterSingle valueMultiple values
sportsport=basketballsport=basketball,football,ice_hockey
leagueleague=nbaleague=nba,nfl,mlb,nhl
sportsbooksportsbook=draftkingssportsbook=draftkings,fanduel,pinnacle
marketmarket=moneylinemarket=moneyline,point_spread,total_points
eventevent=evt_abcevent=evt_abc,evt_def,evt_ghi
channel (SSE)channel=oddschannel=all (odds + opportunities)
channels (WS)channels=evchannels=ev,odds,arbitrage,middles,low_hold

Patterns

Multi-sport: NBA + NFL + MLB on one socket

Instead of opening three streams, pass all three leagues to one:

const es = new EventSource( 'https://api.sharpapi.io/api/v1/stream' + '?channel=all' + '&league=nba,nfl,mlb' + '&api_key=YOUR_KEY' ); es.addEventListener('odds:update', (e) => { const { odds, book } = JSON.parse(e.data); // odds[].league tells you which league this update is for for (const o of odds) routeByLeague(o); });

Odds + every opportunity type on one socket

Set channel=all (SSE) or include every opportunity type in channels= (WS):

const es = new EventSource( 'https://api.sharpapi.io/api/v1/stream?channel=all&api_key=YOUR_KEY' ); es.addEventListener('odds:update', handleOddsDelta); es.addEventListener('ev:detected', handleEV); es.addEventListener('arb:detected', handleArb); es.addEventListener('middles:detected', handleMiddle); es.addEventListener('low_hold:detected', handleLowHold);

The server tags each message with its event type — your handler dispatches by event name, exactly as if you’d opened five separate streams.

Tracking N specific events

If you want tight updates on a fixed list of events (e.g. ten games tonight), pass them all to event=:

const eventIds = [ 'nba_lal_bos_2026-04-30', 'nba_phx_dal_2026-04-30', 'nfl_kc_buf_2026-05-01', /* ... */ ].join(','); const es = new EventSource( `https://api.sharpapi.io/api/v1/stream?channel=all&event=${eventIds}&api_key=YOUR_KEY` );

This replaces the pattern of opening one /stream/events/{eventId} socket per event.

Per-book or per-market splits

Same idea for books and markets:

// Track Pinnacle sharp moves + DK/FD live prices, moneyline + spreads only: const es = new EventSource( 'https://api.sharpapi.io/api/v1/stream' + '?channel=odds' + '&sportsbook=pinnacle,draftkings,fanduel' + '&market=moneyline,point_spread' + '&api_key=YOUR_KEY' );

Dynamic re-subscription (WebSocket)

The bidirectional control of WebSocket lets you change filters mid-connection without dropping the socket. Use this when your set of “interesting” topics changes over the day (e.g. user opens / closes views in a dashboard):

const ws = new WebSocket('wss://ws.sharpapi.io?api_key=YOUR_KEY'); // Initial subscription ws.onopen = () => ws.send(JSON.stringify({ type: 'subscribe', channels: ['odds', 'ev'], filters: { sport: ['basketball'], league: ['nba'] }, })); // Later — user adds NFL to their dashboard function addNFL() { ws.send(JSON.stringify({ type: 'subscribe', filters: { sport: ['basketball', 'football'], league: ['nba', 'nfl'] }, })); }

See the WebSocket API Reference for the full subscribe-message schema.

Fleet & multi-process

The one case where a single connection genuinely doesn’t work: separate processes or machines that can’t share a socket. Examples:

  • Ten trading bots running on ten boxes, each needing its own live feed.
  • Worker pool where N workers each consume a stream independently.
  • Backend service + browser dashboard, both authenticated as the same user.

The default 1-stream cap means a second connection on the same key will displace the first (close code 4001 displaced by newer session on WS, writer teardown on SSE). The intended escape hatch is a per-key maxStreams override in Unkey metadata, sized to the fleet. This is set up on Enterprise plans — contact hello@sharpapi.io to provision a higher cap for a specific key.

For everything else — even very wide subscriptions — the patterns above let one socket cover what looks like ten separate concerns.

Server-side cost

There is no efficiency reason to split. The server’s hot path:

  1. Computes the per-cycle book diff once.
  2. Pre-serializes the unfiltered changed/removed payloads once.
  3. For each connected client, applies their filter and serializes the matching subset (or sends the pre-serialized bytes directly when the client has no content filters).

A client with league=nba,nfl,mlb,nhl costs almost the same as four clients each with one league — minus four sockets, four TLS handshakes, four sets of HTTP headers, and four connected/snapshot cycles. The single-connection pattern is also better for delta consistency: you see all updates in the order the server produced them, instead of interleaving across sockets with independent backpressure.

Migration checklist

If you’re moving from a multi-stream architecture:

  1. Combine identity filters — collect every sport, league, sportsbook, market, and event value across your old streams and join them with commas on one URL.
  2. Use channel=all (SSE) or every needed channels= value (WS) instead of one stream per event type.
  3. Dispatch in your handler — read odds[].league / odds[].sportsbook / event.event to route messages internally exactly as before.
  4. Drop your reconnect-N-times logic — one socket means one reconnect path. SSE auto-reconnects; for WS, see the reconnection pattern.
  5. Keep min_ev / min_profit thresholds — these still narrow the opportunity stream server-side and reduce bandwidth.

See also

Last updated on