Sports scores API: live scores and results

Sports scores API with live scores, the game clock and final results on the same event ids as the odds, for scoreboards, live screens and bet grading.

PreciseAPI’s sports scores API shares event ids with the odds, so a game card or a grading job joins prices and results without matching team names. /v1/scores returns live scores, the game clock and recent finals for 1 credit per call.

A sports scores API is the other half of an odds product. A live screen needs the score and clock next to each price, and a bet tracker needs the final result to settle what was placed. PreciseAPI serves scores on the same event ids as the odds, so a game card, a model's training set or a grading job joins prices and results without matching team names. This page covers /v1/scores, the event endpoints, grading bets in your own code and with the grade_bet MCP tool, and what the score data does not include.

Sports scores API: /v1/scores

/v1/scores returns events with their status, score and game clock. By default it lists games that are live or recently finished; status takes scheduled, live, final, postponed and cancelled, comma-separated, and league takes one or more league ids. limit defaults to 200 and goes up to 500. Each call costs 1 credit, whatever the number of games.

curl "https://api.preciseapi.com/v1/scores?league=nhl&status=live" \
  -H "Authorization: Bearer $PRECISEAPI_KEY"
{
  "data": [
    {
      "id": "evt_27a3vzijsnp",
      "league": "nhl",
      "sport": "hockey",
      "competition": "National Hockey League",
      "start_time": "2026-10-14T22:03:23.850Z",
      "status": "live",
      "home": { "id": "nhl_det", "name": "Detroit Red Wings", "abbr": "DET" },
      "away": { "id": "nhl_car", "name": "Carolina Hurricanes", "abbr": "CAR" },
      "score": { "home": 0, "away": 3 },
      "clock": { "period": 2, "display": "P2 3:52" }
    }
  ],
  "meta": { "request_id": "req_…", "count": 1, "credits_used": 1, "credits_remaining": 149870, "generated_at": "2026-10-14T23:33:43.548Z" }
}

The event object is the same one the odds endpoints return, so id joins straight to /v1/odds, /v1/best-lines and /v1/history. score is null whenever no score is known; it is never a placeholder 0–0. clock is set only while a game is live.

Status lifecycle

Events move from scheduled to live to final, and the id never changes along the way. If no source reports a result, a game is marked final once it has run past its sport's usual length and no source has quoted it for 10 minutes, and in any case 12 hours after the start. A game that is postponed or cancelled gets that status instead. start_time_tbd flags a placeholder kickoff, and when a game reached the feed under more than one id, the others are listed in alternate_ids and keep resolving to it.

Live scores API for game screens

For a scoreboard or a live odds screen, poll /v1/scores for the leagues you show. At 1 credit a call, polling one league every 30 seconds uses 2,880 credits a day, within Edge's 150,000 a month for a few leagues, and Sharp and Syndicate are unlimited. Live scores are on every paid plan, including Edge and Sharp, even though in-play odds are not: on those plans live games drop out of odds responses while their scores keep updating.

On Syndicate, the WebSocket stream pushes an event message whenever a game's status, score, clock or kickoff changes, next to the price deltas, so a live screen doesn't need to poll at all. The live odds API page covers in-play prices, and WebSocket odds API docs cover the message types.

Two event endpoints sit beside it. /v1/events (1 credit) lists scheduled and live games, with date_from and date_to for a schedule. /v1/events/{id} (1 credit) returns one game with its score, the sources pricing it and the market keys available.

Scores and odds on one game card

Because the ids match, a game card is a join on id. This fetches live scores and the best moneyline for the same league, 4 credits per refresh, and prints them together:

const headers = { Authorization: `Bearer ${process.env.PRECISEAPI_KEY}` };
const get = (path) => fetch(`https://api.preciseapi.com/v1/${path}`, { headers }).then((r) => r.json());

const [scores, lines] = await Promise.all([
  get('scores?league=nba&status=live'),
  get('best-lines?league=nba&markets=moneyline'),
]);
const moneyline = new Map(lines.data.map((e) => [e.id, e.markets.find((m) => m.key === 'moneyline')]));

for (const e of scores.data) {
  const ml = moneyline.get(e.id);
  const best = ml ? ml.outcomes.map((o) => `${o.name} ${o.best_price}`).join(' / ') : 'no in-play prices';
  console.log(`${e.away.abbr} ${e.score?.away ?? '-'} @ ${e.home.abbr} ${e.score?.home ?? '-'}  ${e.clock?.display ?? ''}  ${best}`);
}

On Syndicate the prices are in-play. On Edge and Sharp, /v1/best-lines leaves games in progress out, so each live game prints its score without prices.

A results API for finished games

Finished games stay queryable through /v1/scores for four hours. That makes it a results API for settling and archiving, not a historical results database: if you need last season's finals, PreciseAPI doesn't have them. The reliable pattern is a job that runs every few minutes, asks for status=final,postponed,cancelled, and writes each new result into your own storage along with the event id.

Bet settlement API logic in your own code

Grading a full-game moneyline bet, point spread or over/under needs only the final score and the bet's line. This Python function settles moneylines, spreads and totals the way most books do:

import os
import requests

def grade(event, market, side, line=None):
    """Full-game moneyline, spread or total: won, lost, push, void, pending or no_score."""
    if event["status"] in ("cancelled", "postponed"):
        return "void"
    if event["status"] != "final":
        return "pending"
    if not event["score"]:
        return "no_score"  # settle by hand
    home, away = event["score"]["home"], event["score"]["away"]
    if market == "moneyline":
        winner = "home" if home > away else "away" if away > home else "draw"
        if winner == side:
            return "won"
        return "push" if winner == "draw" and event["league"] != "soccer" else "lost"
    if market == "spread":
        margin = (home - away if side == "home" else away - home) + line
    else:  # total
        margin = (home + away - line) * (1 if side == "over" else -1)
    return "won" if margin > 0 else "lost" if margin < 0 else "push"

resp = requests.get(
    "https://api.preciseapi.com/v1/scores",
    params={"league": "nba", "status": "final,postponed,cancelled"},
    headers={"Authorization": f"Bearer {os.environ['PRECISEAPI_KEY']}"},
    timeout=10,
)
results = {e["id"]: e for e in resp.json()["data"]}

bet = {"event_id": "evt_1iazqk4srnb", "market": "spread", "side": "home", "line": -4.5}
event = results.get(bet["event_id"])
print(grade(event, bet["market"], bet["side"], bet["line"]) if event else "not final yet")

One /v1/scores call per league settles every open bet in it, which is cheaper than one /v1/events/{id} call per bet. Soccer moneylines are three-way, so a draw loses a home or away bet; in two-way sports a tied moneyline is a push.

Bet grading API: grade_bet over MCP

If you work in Claude, ChatGPT, Cursor or another AI client, the PreciseAPI MCP server can grade a bet for you. grade_bet takes an event id, a market (moneyline, spread or total), a selection (home, away, draw, over, under or a team name), the line, and optionally the price and stake. It returns won, lost, push, void or pending, a sentence explaining why, and the profit when you give a price and stake. Each call costs 1 credit.

{
  "game": { "event_id": "evt_1iazqk4srnb", "league": "nba", "away": "San Antonio Spurs", "home": "Phoenix Suns", "starts": "Wed, Nov 11, 9:00 PM EST", "start_time": "2026-11-12T02:00:00.000Z", "status": "final", "score": { "San Antonio Spurs": 104, "Phoenix Suns": 112 } },
  "bet": "Phoenix Suns -4.5 (spread, -110)",
  "final_score": "San Antonio Spurs 104, Phoenix Suns 112",
  "result": "won",
  "detail": "Phoenix Suns -4.5: Phoenix Suns 112, opponent 104, covered by +3.5.",
  "profit": 90.91,
  "note": "Graded on the full-game final score in the feed (overtime included where the sport counts it). Check your book’s own settlement rules."
}

Ask "did Phoenix −4.5 cover last night?" and the client finds the game with find_games, then calls grade_bet. To list results, find_games with status final returns recent games with their final scores, 1 credit per call. The odds API MCP guide covers setup. Like the REST data, both tools only see games that finished within the last four hours or so.

What the score data doesn't include

Be clear about the limits before you build on it:

Plans and credit costs

/v1/scores, /v1/events and /v1/events/{id} cost 1 credit each on every paid plan, and grade_bet costs 1 credit over MCP. Edge ($49.99 a month) includes 150,000 credits; Sharp ($199.99) and Syndicate ($249.99) are unlimited, and only Syndicate adds in-play odds and the stream's live event messages. The free Sandbox has 50 credits for the dashboard chat but no API access, so a sports scores API integration starts on Edge. See odds API pricing.

Frequently asked questions

Does the sports scores API include live scores on Edge?

Yes. /v1/scores returns live scores and the game clock on every paid plan. In-play odds are the part that needs Syndicate.

How long are final scores available?

About four hours after a game ends. Store results as games finish if you need them later.

Can PreciseAPI settle bets automatically?

Over MCP, grade_bet settles full-game moneyline, spread and total bets against the final score. Over REST, you grade in your own code from /v1/scores, as in the example above. Player props and period bets can't be graded from the feed.

Which leagues have scores?

Every event in the feed, across all 17 leagues, carries the same score and clock fields. A score appears once a source reports one and stays null until then, so check for null before you display or grade.

Are the event ids the same as in the odds?

Yes. Scores, events, odds, best lines and line history all use one event id, and it doesn't change when a game goes live.

What a score looks like

/v1/scores returns the event object the odds endpoints use, with status, score and clock. Status moves from scheduled to live to final, and the id never changes. score is null whenever no score is known, never a placeholder, and clock is set only while a game is live. Live scores are on every paid plan, including Edge and Sharp, where in-play odds are not. On Syndicate, the WebSocket stream also pushes score and status changes.

Grading and its limits

Finished games stay in /v1/scores for four hours, so a settlement job should store results as games end. Full-game moneylines, spreads and totals grade from the final score and the bet’s line, and over MCP the grade_bet tool returns won, lost, push, void or pending, with the profit when you give a price and stake. The feed has no box scores, player stats or period scores, so player props and first-half bets need another source of results.

Example request

GET /v1/scores?league=nhl&status=live

Endpoint

What teams build with it

Related reading

More products

Responses use the same event, market and outcome ids as every other endpoint. Prices are American odds by default, with format=decimal and format=probability for the other two, and a market whose source has stopped reporting is flagged suspended instead of being shown as live.

Every source and league is on the coverage page, and what each request costs is on the pricing page.