> ## Documentation Index
> Fetch the complete documentation index at: https://docs.therundown.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Scores and Results

> Read final and per-period scores, derive half scores defensively, and retrieve completed results within your plan's history and data-point limits.

Scores are part of the `score` object on event responses. Read `score.score_home` and `score.score_away` for the final totals, and `score.event_status` to determine whether play has finished. There is no separate scores or results endpoint, and individual score fields do not add a charge.

## Fetch completed results

Set `affiliate_ids=0` to omit markets and price objects (scores and status only). That scores-only filter applies to **open and completed** events alike: the response has no prices, so the two-point events+scores cost is not limited to a `hide_closed` completed slate. `hide_closed=true` only drops closed prices; it does not omit markets while prices are still open.

For a completed slate, `affiliate_ids=0` is the cheapest results sweep:

```bash theme={null} theme={null}
curl -H "X-TheRundown-Key: $THERUNDOWN_API_KEY" \
  "https://therundown.io/api/v2/sports/3/events/YYYY-MM-DD?hide_closed=true&affiliate_ids=0"
```

Replace `YYYY-MM-DD` with a completed date inside your plan's [history window](/rate-limits#history-window). Check each event's status; a past date alone does not establish that every game is final.

With `affiliate_ids=0` the response contains no markets or price objects, but still includes status, scores, per-period scores, and overtime information. Without `live_game_state`, each event then costs **two data points**: one `events` point and one `scores` point. A completed baseball slate checked on September 8, 2026 returned eleven finals and zero price objects. Check the returned prices and `X-Datapoints` for your own request. Events carrying `live_game_state` (Ultra and above) add one more `scores` point; see the [cost formula](/rate-limits#1-data-points).

If you already have the event ID, retrieve a single completed game with:

```bash theme={null} theme={null}
curl -H "X-TheRundown-Key: $THERUNDOWN_API_KEY" \
  "https://therundown.io/api/v2/events/1d5de19a415eeec1c11b42df1e0a6ec6?hide_closed=true&affiliate_ids=0"
```

This completed-game lookup costs two data points when no prices or `live_game_state` are returned. `GET /api/v2/events/{eventID}` is not restricted by the history window, so retain event IDs for older results. The event's opening-line and closing-line routes do apply an event-date gate.

<Note>
  Pass `affiliate_ids=0` to return scores and status without markets or price objects. That is the scores-only path, and it bills the two-point events+scores cost on **open games as well as completed ones**. Omitting `market_ids` still requests odds: it defaults to `1,2,3`, or `1,2,3,563` for soccer and NHL. While games are open and you still want prices, `market_ids=1` with one sportsbook `affiliate_ids` value and `main_line=true` keeps a game to roughly four data points, depending on returned prices. `live_game_state`, when present, adds another point. Verify the actual cost in `X-Datapoints`.
</Note>

## Read the period arrays

`score_home_by_period` and `score_away_by_period` contain **scores for each period, not running totals**. Index `0` is period one, index `1` is period two, and so on.

For NFL and NBA regulation finals, each side has four entries and `game_period` is `4`. Overtime is appended: one overtime gives five entries and `game_period` of `5`; a second gives six and `game_period` of `6`. `event_status_detail` reads `Final`, `Final/OT`, `Final/2OT`, and so on. Exhibition games can be exceptions, as described below.

Read each side using its own array length. Baseball arrays routinely differ: if the home team does not bat in the bottom of the ninth or the final extra inning, its array is one entry shorter. This occurred in roughly 45% of completed baseball games in a recent 60-day review completed on September 8, 2026. Football and basketball arrays were equal in length in every completed game in the twelve-month review. Those observations do not establish an equal-length guarantee; never truncate one side to match the other or fill a missing period with zero.

<Warning>
  Final totals and period arrays are independent fields. Across every NFL and NBA event that reached a final state in the twelve months reviewed on September 8, 2026, each side's period sum matched its final score. `game_period` matched the array lengths in every case except one exhibition game. **The API does not enforce this reconciliation.** Verify each side's sum against its final score and check that the periods needed for your calculation are present. If data is missing or mismatched, leave the result ungraded for review or a later read.
</Warning>

### Verified examples

These event IDs and values were verified on September 8, 2026. You can retrieve them with `GET /api/v2/events/{eventID}?hide_closed=true&affiliate_ids=0`. Final scores below are **home–away**. Completed events can change after final, so validate the response you receive.

| Game                | Event ID                           | `event_status_detail` | `game_period` | `score_home_by_period` | `score_away_by_period` | Final (home–away) |
| ------------------- | ---------------------------------- | --------------------- | ------------- | ---------------------- | ---------------------- | ----------------- |
| NFL regulation      | `196908386d1b73632d57e3d2ceb1df8e` | `Final`               | `4`           | `[0,0,0,13]`           | `[3,6,3,17]`           | 13–29             |
| NFL overtime        | `57e06d3ab5e9841fd23fd2f8fc2295b2` | `Final/OT`            | `5`           | `[0,10,0,7,0]`         | `[7,3,0,7,3]`          | 17–20             |
| NBA regulation      | `21c728154d3029ca335ff2f7aeb31901` | `Final`               | `4`           | `[23,19,30,18]`        | `[13,24,28,29]`        | 90–94             |
| NBA overtime        | `4fb0997e7946cb6a50cb64f0b4041c70` | `Final/OT`            | `5`           | `[23,23,23,32,14]`     | `[16,32,35,18,3]`      | 115–104           |
| NBA double overtime | `1d5de19a415eeec1c11b42df1e0a6ec6` | `Final/2OT`           | `6`           | `[27,17,29,28,7,7]`    | `[27,24,29,21,7,14]`   | 115–122           |

## Derive half scores

For NFL and NBA grading that includes overtime in the second half, calculate each side separately:

* **First half:** sum the first two entries, `periods[:2]`.
* **Second half including overtime:** sum period three onward, `periods[2:]`. This includes periods three and four and every overtime entry.

For the double-overtime NBA example, the home halves are `27 + 17 = 44` and `29 + 28 + 7 + 7 = 71`. The away halves are `27 + 24 = 51` and `29 + 21 + 7 + 14 = 71`. They reconcile to the final totals of `115` and `122`. Apply the overtime treatment required by the result you are grading.

This Python example requires a final NFL or NBA regular-season or playoff event, complete period arrays, matching totals, and a consistent period count. It refuses to derive a result if any check fails. The returned tuples are derived values in `(first half, second half including overtime)` order.

```python theme={null} theme={null}
import os
import requests

EVENT_ID = "1d5de19a415eeec1c11b42df1e0a6ec6"


def read_event():
    response = requests.get(
        f"https://therundown.io/api/v2/events/{EVENT_ID}",
        headers={"X-TheRundown-Key": os.environ["THERUNDOWN_API_KEY"]},
        params={"hide_closed": "true", "affiliate_ids": "0"},
    )
    response.raise_for_status()
    return response.json()["events"][0]


def half_scores(event):
    if event.get("sport_id") not in (2, 4, 24, 26):
        raise ValueError("This example supports NFL and NBA regular season/playoffs")
    score = event.get("score") or {}
    if score.get("event_status") != "STATUS_FINAL":
        raise ValueError("Wait for STATUS_FINAL")

    halves = {}
    for side in ("home", "away"):
        periods = score.get(f"score_{side}_by_period")
        total = score.get(f"score_{side}")
        if not isinstance(periods, list) or len(periods) < 4:
            raise ValueError(f"Incomplete {side} periods; leave ungraded")
        if any(type(value) is not int or value < 0 for value in periods):
            raise ValueError(f"Invalid {side} period score; leave ungraded")
        if type(total) is not int or sum(periods) != total:
            raise ValueError(f"{side} periods do not reconcile; leave ungraded")
        if score.get("game_period") != len(periods):
            raise ValueError(f"{side} period count mismatch; leave ungraded")
        halves[side] = (sum(periods[:2]), sum(periods[2:]))
    return halves


candidate = read_event()
candidate_halves = half_scores(candidate)
checked_at = candidate["score"].get("updated_at")

# Re-read and validate again before locking the result.
confirmed = read_event()
confirmed_halves = half_scores(confirmed)
if (not checked_at or confirmed["score"].get("updated_at") != checked_at
        or confirmed_halves != candidate_halves):
    raise ValueError("Score changed or timestamp is missing; review before locking")

print(confirmed_halves)  # {'home': (44, 71), 'away': (51, 71)}
```

Each read is billed separately. A matching re-read is a defensive check, not a guarantee that no later correction will occur.

## Check status and re-read before locking

For NFL and NBA, act on `score.event_status` of `STATUS_FINAL`, then validate the score fields. Use `event_status_detail` for display, including the overtime suffix. `STATUS_END_OF_REGULATION` is not final because overtime may follow.

Other sports have their own terminal statuses, including `STATUS_FINAL_AET` and `STATUS_FINAL_PEN` for soccer. Cancellation and forfeiture need separate handling; neither establishes that period arrays are complete. Postponed or suspended games are not completed results. See [Event Status Codes](/reference/event-statuses), and leave unknown statuses ungraded until you can handle them explicitly.

A small number of completed events were updated after going final in the review. Re-read the event once before locking a result and compare `score.updated_at` with the value you previously read. If it changes, validate the latest scores again before deciding what to lock. A final status does not make the score immutable.

## Exclude exhibition games when completeness matters

All-Star and preseason games can reach a final state with an empty period array or `game_period` of `0` or `1`. Regular-season and playoff games were consistent in the reviewed NFL and NBA events, but you should still run the same completeness and sum checks.

Preseason has separate sport IDs: NBA Preseason is `23` and NFL Preseason is `25`. Exclude those IDs from the sports you request if you do not grade preseason. Use the [season-specific sport list](/reference/sports#season-specific-sports) to select regular-season and playoff IDs deliberately. Excluding preseason does not replace validation for All-Star or other exhibition games.
