Examples

Worked examples across languages and use cases

Full end-to-end snippets — not just single calls — for the integrations developers build most often: live scores, real-time feeds, odds comparison, historical analysis and webhooks.

Which One Do I Need?

Pick a pattern by use case

All five examples call the same underlying API — the difference is how data reaches your application.

Use caseExampleBest for
Show live scores on a website or appLive ScoreboardLow to medium traffic, simplest to build
Sub-second updates, many concurrent viewersReal-Time FeedTrading desks, high-frequency widgets
Compare prices across bookmakersOdds ComparisonOdds aggregation, pricing tools
Analyze past seasons at scaleHistorical BacktestResearch, modeling, reports
React to match events the instant they happenWebhook ListenerEvent-driven backends, notifications
00Prerequisites

Before you start

Every example below assumes the same two things.

1 A free Orbistats API key
2 Node.js 18+ or Python 3.9+ installed
i Every snippet also works as a plain HTTP request with a Bearer token — the SDK just removes boilerplate around auth, retries and pagination. See SDKs for install instructions.
01Example — Live Scoreboard

Poll live matches every few seconds

A minimal loop that keeps a scoreboard in sync with in-play matches — the simplest way to show live scores.

const orbistats = require('@orbistats/sdk');
const client = new orbistats.Client(process.env.ORBISTATS_API_KEY);

async function refreshScoreboard() {
  try {
    const live = await client.football.matchesLive();
    renderScoreboard(live.data);
  } catch (err) {
    console.error('Failed to fetch live matches:', err.message);
  }
}

refreshScoreboard();
setInterval(refreshScoreboard, 5000);
import os, time
from orbistats import Client

client = Client(api_key=os.environ["ORBISTATS_API_KEY"])

def refresh_scoreboard():
  try:
    live = client.football.matches_live()
    render_scoreboard(live["data"])
  except Exception as exc:
    print(f"Failed to fetch live matches: {exc}")

while True:
  refresh_scoreboard()
  time.sleep(5)
  • Polling every 5 seconds is frequent enough for a live board and well under the free-tier rate limit.
  • The try/except block means one failed request never crashes the loop.
  • matchesLive() only returns fixtures currently in play, so there's no client-side filtering to do.
For sub-second updates or many concurrent boards, skip polling entirely and use the Real-Time Feed example below instead.
02Example — Real-Time Feed

Stream updates instead of polling

One persistent WebSocket connection replaces thousands of polling requests and delivers updates the instant they happen.

const WebSocket = require('ws');

const socket = new WebSocket('wss://stream.orbistats.com/v1/football?apikey=YOUR_API_KEY');

socket.on('open', () => console.log('Connected to live feed'));

socket.on('message', (raw) => {
  const event = JSON.parse(raw);
  if (event.type === 'score_update') {
    updateScoreboard(event.fixture_id, event.score);
  }
});

socket.on('close', () => console.log('Disconnected — reconnect logic goes here'));
import asyncio, json, websockets

async def listen():
  uri = "wss://stream.orbistats.com/v1/football?apikey=YOUR_API_KEY"
  async with websockets.connect(uri) as ws:
    async for raw in ws:
      event = json.loads(raw)
      if event["type"] == "score_update":
        update_scoreboard(event["fixture_id"], event["score"])

asyncio.run(listen())
  • Always handle the close/error event and reconnect with exponential backoff in production.
  • The feed carries score updates, match events and odds changes on the same stream — filter by event.type client-side.
  • See the WebSocket API reference for the full list of event types.
03Example — Odds Comparison

Find the best available line

Normalized odds make it trivial to compare bookmakers directly, without unit conversion.

odds = client.football.odds(match_id=884213)
markets = odds["data"]["markets"]["1X2"]

best_home = max(markets, key=lambda m: m["home"])
print(f"Best home price: {best_home['home']} at {best_home['bookmaker']}")
const odds = await client.football.odds({ matchId: 884213 });
const markets = odds.data.markets['1X2'];

const bestHome = markets.reduce((a, b) => (a.home > b.home ? a : b));
console.log(`Best home price: ${bestHome.home} at ${bestHome.bookmaker}`);
  • Odds are normalized to decimal format across every connected bookmaker, so no conversion is needed before comparing.
  • Every market entry is tagged with a bookmaker name, so you can always trace where a price came from.
  • Combine this with the Webhook Listener below to react the moment a line moves, instead of re-polling.
04Example — Historical Backtest

Pull multi-season data into pandas

Historical Data returns the same schema as live fixtures, so backtests reuse the same parsing code.

import pandas as pd

results = client.football.historical(season="2019-2025")
df = pd.DataFrame(results["data"])

df["over_2_5"] = (df["home_goals"] + df["away_goals"]) > 2.5
print(df.groupby("competition")["over_2_5"].mean())
  • The historical schema mirrors live fixtures field-for-field, so the same parsing code works for both.
  • Results are paginated — for multi-season pulls, loop through pagination.total_pages rather than assuming one response covers everything.
  • This pattern is what powers our own research reports — good for a notebook, a trading model, or a write-up of your own.
05Example — Webhook Listener

Receive match events as they happen

Register an endpoint once in the dashboard, then let Orbistats push events to you — no polling loop to maintain.

const express = require('express');
const app = express();
app.use(express.json());

app.post('/webhooks/orbistats', (req, res) => {
  const event = req.body;

  if (event.event === 'fixture.finished') {
    console.log(`${event.fixture_id} finished: ${event.final_score.home}-${event.final_score.away}`);
  }

  res.sendStatus(200); // acknowledge quickly — Orbistats retries on non-2xx
});

app.listen(3000);
from flask import Flask, request

app = Flask(__name__)

@app.route("/webhooks/orbistats", methods=["POST"])
def orbistats_webhook():
  event = request.get_json()

  if event["event"] == "fixture.finished":
    print(f"{event['fixture_id']} finished: {event['final_score']}")

  return "", 200 # acknowledge quickly — Orbistats retries on non-2xx
  • Respond with a 2xx status within a few seconds. Slow or failing endpoints get retried, then temporarily paused.
  • Choose which event types to receive from the dashboard, not in code.
  • Verify the signature header on production endpoints so only genuine Orbistats requests are processed.
Full payload shapes, event types and signature verification live in the Webhooks reference.
06FAQs

Common questions

Should I use polling or WebSockets for live scores?

Polling every few seconds is simple and fine for low to medium traffic. For sub-second updates or many concurrent viewers, a persistent WebSocket connection is far more efficient.

Do these examples work without an SDK?

Yes. Every example also works with plain HTTP requests and a Bearer token — the SDK just removes boilerplate around auth, retries and pagination.

How do I test a webhook endpoint locally?

Use a tunneling tool such as ngrok to expose your local server, then register the temporary public URL as your webhook endpoint in the dashboard.

Can I combine these examples, like odds comparison with webhooks?

Yes — a common pattern is to trigger the odds comparison logic from an odds.changed webhook instead of polling, reacting the moment a price moves.

07Next Steps

Take it further

See Also

Related pages

Explore more of the developer platform.

Get Started

Start free. Upgrade when you need enterprise SLAs.

Self-serve API keys for developers today — dedicated infrastructure, custom feeds and SLAs when you're ready.