Skip to content

Sports Channel

This WebSocket streams score changes, period transitions, and game status updates for active matches. Subscribe by game ID to follow specific contests. No authentication is needed.

wss://api.openfish.fun/ws/sports

After opening the connection, send a JSON message with the game IDs you want to track:

{
"channel": "live-score",
"games": ["game-123", "game-456"]
}
FieldTypeDescription
channelstringMust be "live-score" for score subscriptions
gamesstring[]List of game ID strings to subscribe to

The server confirms which games you are now following:

{
"type": "subscribed",
"games": ["game-123", "game-456"]
}

Additional subscription messages extend your existing set rather than replacing it:

{
"channel": "live-score",
"games": ["game-789"]
}

Response:

{
"type": "subscribed",
"games": ["game-123", "game-456", "game-789"]
}

Whenever the state of a tracked game changes, the server delivers an update:

{
"gameId": "game-123",
"homeScore": 2,
"awayScore": 1,
"clock": "65:00",
"period": "2H",
"status": "LIVE",
"timestamp": 1700000000
}
FieldTypeDescription
gameIdstringUnique game identifier
homeScorenumberCurrent home team score
awayScorenumberCurrent away team score
clockstringGame clock or elapsed time
periodstringCurrent period (e.g., 1H, 2H, Q3, FT)
statusstringGame status (see table below)
timestampnumberUnix timestamp in seconds
StatusDescription
PREGame has not started yet
LIVEGame currently in progress
HALFHalftime or intermission break
FINALGame completed
PeriodDescription
1H, 2HFirst half, second half
Q1, Q2, Q3, Q4Quarters (basketball, American football)
HTHalftime
FTFull time (match ended in regulation)
OTOvertime

The server sends WebSocket PING frames every 10 seconds. Your client must respond with PONG to keep the connection alive.

use openfish_client_sdk::ws::SportsSocket;
use futures_util::StreamExt;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let mut ws = SportsSocket::connect("wss://api.openfish.fun/ws/sports").await?;
// Subscribe to specific games
ws.subscribe_games(&["game-123", "game-456"]).await?;
while let Some(update) = ws.next().await {
println!(
"[{}] {} vs {} : {}-{} ({} {})",
update.game_id,
"Home",
"Away",
update.home_score,
update.away_score,
update.period,
update.status,
);
if update.status == "FINAL" {
println!("Game {} has ended.", update.game_id);
}
}
Ok(())
}

Score updates from this channel pair naturally with prediction market data, enabling automated strategies that react to in-game developments:

  1. Use the Gamma API to find sports-related events and extract game IDs.
  2. Subscribe to the sports WebSocket for live score updates.
  3. Subscribe to the market WebSocket for the corresponding token’s order book.
  4. React to score changes by placing or adjusting orders.
use openfish_client_sdk::ws::{SportsSocket, MarketSocket};
use futures_util::StreamExt;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let mut sports = SportsSocket::connect("wss://api.openfish.fun/ws/sports").await?;
let mut market = MarketSocket::connect(
"wss://api.openfish.fun/ws/market?asset_id=71321045..."
).await?;
sports.subscribe_games(&["game-123"]).await?;
tokio::select! {
Some(score) = sports.next() => {
println!("Score update: {}-{}", score.home_score, score.away_score);
// Adjust trading strategy based on score...
}
Some(book) = market.next() => {
println!("Book update received");
// Update local order book...
}
}
Ok(())
}