Point Spread Odds Data: Lines, Prices, Alternates and Key Numbers
How point spreads are represented in odds data, the home-handicap sign convention, run lines, puck lines and handicaps, alternate spread ladders, key numbers, comparing spreads across books and separating line moves from price moves in history.
A point spread has two moving parts, the line and the price, and that makes it the first market where odds data gets genuinely tricky. Two books can disagree on the number, on the price, or on both. A spread can move by changing its number, by changing its price at the same number, or both at once. And the meaning of a half-point depends on the sport and on where the number sits.
This guide covers how spreads are represented in the PreciseAPI schema, the sign convention, how spreads differ across sports, how to work with alternate spread ladders, how to think about key numbers with data rather than folklore, how to compare spreads across books, and how to read spread history. For the one-paragraph definition, see the spread glossary entry.
How a spread is represented
A spread is a market with key: "spread", a period, a market-level line, and two outcomes, home and away, each with its own point and price:
{
"id": "mkt_14ivq762bz0",
"key": "spread",
"period": "full_game",
"line": -6.5,
"outcomes": [
{ "id": "sel_1d92w0erhd2", "name": "Kansas City Chiefs", "side": "home", "point": -6.5, "price": -110 },
{ "id": "sel_1lhzilnwepp", "name": "Buffalo Bills", "side": "away", "point": 6.5, "price": -110 }
],
"suspended": false,
"updated_at": "2026-10-16T14:02:41.118Z"
}
The sign convention
The market's line is always the home team's handicap. The home outcome's point equals line, and the away outcome's point is its negation.
line | Meaning | Home point | Away point |
|---|---|---|---|
| -6.5 | Home team favored by 6.5 | -6.5 | +6.5 |
| +3 | Home team is a 3-point underdog | +3 | -3 |
| 0 | Pick'em, no handicap | 0 | 0 |
That convention gives you one number per market to sort, compare and chart, regardless of which team is favored. If your product shows spreads from the favorite's perspective, derive it at display time: the favorite is the side with the negative point. Don't store a "favorite" field, because the favorite can change during the week.
Grading follows directly from the convention. With margin = home score - away score, the home side covers when margin + line > 0, the away side covers when it is below zero, and a whole-number line can land exactly on zero, which is a push:
export function gradeSpread(line, homeScore, awayScore) {
const x = homeScore - awayScore + line;
return x > 0 ? 'home' : x < 0 ? 'away' : 'push';
}
// gradeSpread(-6.5, 27, 20) -> 'home' (27 - 20 - 6.5 = 0.5)
// gradeSpread(-7, 27, 20) -> 'push'
Spreads across sports
The spread key is offered for 15 of the 17 leagues in the catalog: every league except PGA and UFC. It covers what each sport calls its handicap market:
| Sport | Usual name | Notes |
|---|---|---|
| Football (NFL, NCAAF, CFL) | Point spread | Key numbers matter, see below |
| Basketball (NBA, WNBA, NCAAB) | Point spread | Many half-point steps, higher scoring |
| Baseball (MLB) | Run line | Main line usually ±1.5, so moves show up in price |
| Hockey (NHL) | Puck line | Main line usually ±1.5, as above |
| Soccer | Asian handicap | Low scoring; small lines carry large price differences |
| Tennis | Game handicap | Handicap in games, not sets |
| Esports (LoL, CS2, Valorant, Dota 2, CoD) | Map handicap | Small integer-plus-half lines, often ±1.5 |
The schema is the same for all of them: line, point and price. Treat point as a number, not a string, and don't assume any particular step size; the feed reports whatever number each book hangs.
Periods
Spreads are priced per period, following each league's period list: 1h and 1q for the NFL and NBA, 1h for the other football and basketball leagues and soccer, f5 (first five innings) for MLB and 1p for the NHL. Pass the periods you want explicitly, for example periods=full_game,1h. /v1/leagues (free) returns every league's periods and market keys.
Pulling spreads
curl "https://api.preciseapi.com/v1/odds?league=nfl&markets=spread&periods=full_game,1h&books=pinnacle,circa,draftkings,fanduel" \
-H "Authorization: Bearer $PRECISEAPI_KEY"
/v1/odds costs 2 credits per request, regardless of how many events or books it returns. Use markets=main to get moneyline, spread and total together, which is usually what a game card needs. Without markets=, the endpoint returns every market for the league, alternates and props included.
Alternate spreads
Most books offer more than one spread per game. The main spread is the number they price closest to even, and the alternate spreads are a ladder of other numbers around it, each with its own price. In the feed, the ladder is a separate market, alternate_spread, offered for the football and basketball leagues: NFL, NCAAF, CFL, NBA, WNBA and NCAAB.
An alternate_spread market holds every rung as outcome pairs, each with its own point, so read the numbers from the outcomes rather than from any market-level line. Parse it into rungs keyed by the home point:
// One alternate_spread market -> [{ line, home, away }] sorted by home line
export function ladder(market) {
const rungs = new Map();
for (const o of market.outcomes) {
const line = o.side === 'home' ? o.point : -o.point; // express every rung as the home handicap
const r = rungs.get(line) ?? { line };
r[o.side] = o.price;
rungs.set(line, r);
}
return [...rungs.values()].sort((a, b) => a.line - b.line);
}
Merge the main spread market into the result and you have the book's full price curve for the game. That curve is useful well beyond display: it is the input for comparing a book's price on a number against its neighbors, for checking that prices are monotonic (a larger handicap should never be cheaper), and for pricing the half-points around key numbers.
Two things to know when you combine ladders across books. First, outcome selection ids include the point, so each rung joins to the same rung at other books automatically. Second, /v1/best-lines does not group alternate markets, so compare rungs yourself; the line shopping post has the grouping code.
Key numbers
In football, final margins cluster on a few values, most famously 3 and 7, because of how scoring works. A spread that crosses one of those numbers changes the probability of covering more than a spread that moves between two uncommon margins. The NFL odds data guide covers how this shapes the weekly line.
You don't need to take the folklore on trust. Alternate ladders let you see how each book prices the half-points directly. Here is an illustrative ladder for a home favorite whose main line is -6.5 at -110:
| Home line | Price | Implied probability | Step from previous |
|---|---|---|---|
| -4.5 | -145 | 59.18% | |
| -5.5 | -125 | 55.56% | 3.6 pts |
| -6.5 | -110 | 52.38% | 3.2 pts |
| -7.5 | +120 | 45.45% | 6.9 pts |
| -8.5 | +135 | 42.55% | 2.9 pts |
Moving from -6.5 to -7.5 crosses 7, and in this example it costs more than twice as much implied probability as the neighboring half-points. Computing the step between each rung, for every book, turns "key numbers matter" into a measurement you can compare across books and over a season.
To check the margins themselves, archive final scores. /v1/scores (1 credit) returns live and recently finished events, and finished events are retained for four hours, so store results as games end. With a season of results, a frequency table of home score - away score per league tells you exactly how much weight each margin carries in your own data.
const counts = new Map();
for (const g of finals) {
const m = Math.abs(g.score.home - g.score.away);
counts.set(m, (counts.get(m) ?? 0) + 1);
}
Basketball has much flatter margin distributions, so key numbers matter far less there. MLB and NHL spreads are mostly ±1.5 run and puck lines, where the question is the price rather than the number.
Comparing spreads across books
Books often hang different numbers on the same game, and that is the core difficulty in comparing spreads. Home -6.5 at -110 and home -7 at -102 are different bets; neither is simply "better".
/v1/best-lines handles this by grouping books by number: each line that at least two books quote becomes its own entry, with the best price per side and every book offering it. A game with books split between -6.5 and -7 returns two spread entries. In your own code, the usual presentation is two views: the best number for each side (for the home side a larger point is better, -6.5 beats -7; for the away side the same rule applies, +7 beats +6.5) and the best price at the most-quoted number. The best lines API page and the odds screen tutorial show both.
Spread history: line moves vs price moves
/v1/history returns the opening value, the current value and every timestamped change for full-game spreads (and moneylines and totals). It costs 3 credits. Each point carries t, a line (the home handicap, same convention as above) and prices in outcome order, [home, away]:
curl "https://api.preciseapi.com/v1/history?event_id=evt_0uuc6p2dsqa&book=pinnacle&market=spread" \
-H "Authorization: Bearer $PRECISEAPI_KEY"
A spread can move in two ways, and you should record them separately:
- Price move. The line stays at -6.5 and the home price goes from -110 to -120. The market leaned toward the home side without moving the number.
- Line move. The line goes from -6.5 to -7 and the prices reset toward even.
export function classifyMoves(points) {
const out = [];
for (let i = 1; i < points.length; i++) {
const a = points[i - 1];
const b = points[i];
if (b.line !== a.line) out.push({ t: b.t, type: 'line', from: a.line, to: b.line });
else if (b.prices[0] !== a.prices[0]) out.push({ t: b.t, type: 'price', line: b.line, from: a.prices[0], to: b.prices[0] });
}
return out;
}
A sequence like -6.5 -110, then -6.5 -120, then -7 -110 is one market leaning toward the home side twice. Measuring both together, for example by converting each point to a no-vig probability of covering a fixed reference number using the ladder, is the more advanced version; the CLV guide discusses comparing spreads at different numbers, and the steam move post uses line and price changes as signals. History is included on the Sandbox, Starter, Pro and Enterprise plans; see pricing.
Practical checklist
- Join on
sideand selectionid, never team names. - Store
lineas the home handicap and derive the favorite at display time. - Request periods explicitly and never compare a
1hspread with afull_gameone. - Treat
alternate_spreadas a ladder, not a list of separate markets. - Grade with three outcomes: home, away and push.
- Record line moves and price moves as different events.
The game odds API page covers spreads with moneylines and totals, and the quickstart gets a key working in minutes.
Frequently asked questions
Which team does the spread line refer to?
The home team. The market's line is the home handicap, the home outcome's point equals it, and the away outcome's point is its negation. A line of -6.5 means the home team is favored by 6.5.
Which leagues have spread and alternate spread data?
spread is offered for 15 leagues, every league in the catalog except PGA and UFC. alternate_spread is offered for NFL, NCAAF, CFL, NBA, WNBA and NCAAB.
Does /v1/best-lines compare alternate spreads?
No. It compares main markets grouped by line and skips alternate_spread and alternate_total. Request the alternate keys from /v1/odds and compare rungs by selection id, which already includes the point.
How do I tell a line move from a price move in history?
Compare the line of consecutive history points. If it changed, the number moved; if it stayed the same and prices changed, only the price moved. The prices array is in outcome order, home then away.
Are run lines and puck lines in the spread market?
Yes. MLB run lines, NHL puck lines, soccer Asian handicaps, tennis game handicaps and esports map handicaps all use the spread key with the same line, point and price fields.
Can I get first-half spreads?
Yes, for leagues that list 1h among their periods. Pass periods=1h (or periods=full_game,1h) to /v1/odds. Line history covers full-game spreads only.