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
Setaffiliate_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:
YYYY-MM-DD with a completed date inside your plan’s 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.
If you already have the event ID, retrieve a single completed game with:
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.
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.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.
Verified examples
These event IDs and values were verified on September 8, 2026. You can retrieve them withGET /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.
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.
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.
Check status and re-read before locking
For NFL and NBA, act onscore.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, 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 orgame_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 to select regular-season and playoff IDs deliberately. Excluding preseason does not replace validation for All-Star or other exhibition games.