periods.num_N.team_total for the primary home and away lines. When alternate points are published, read periods.num_N.team_totals. Each selection is identified by the event, team side, period and points—not by a display label alone. For a compact prematch request, use /kit/v1/prematch/lines?event_id=N&market_type=team_total.
What a team total measures
A team total is an over/under market for one side's scoring output. If a football team's line is 24.5, Over 24.5 is tied to that team's final points, not the matchup's combined score. In soccer the same idea applies to goals; in baseball it can apply to runs. The event's sport and published settlement rules define the unit.
That makes team-total data useful for models that forecast a single offense, compare a side's expected production with a market price, or monitor how one team's line moves independently of the game total. It is not a winner market and it is not interchangeable with a spread.
Home and away team totals are separate selections. A home over and an away over must never be merged.
points is part of the identity. Over 1.5 and over 2.5 are different lines, even in one period.
Each published line carries an over price and an under price in decimal format.
Full match, half, quarter, set or another period is a separate market context and can have different points.
Team total vs game total: keep the market family clear
Both markets use over/under language, but they answer different questions. A game total applies to the combined score of both teams. A team total applies to one team's score only. A reliable team total over under data pipeline keeps those records in different tables, model features or alert routes.
| Market | What the points mean | PinnWire field | Identity to preserve |
|---|---|---|---|
| Game total | Combined score of home + away | totals | event, period, points, over/under |
| Team total | Score by one team | team_total | event, period, side, points, over/under |
| Alternate team total | Score by one team at another line | team_totals | event, period, side, points, over/under |
| Spread | Margin after a handicap | spreads | event, period, signed handicap, side |
For example, a game total of 2.5 in soccer is about both teams' goals. A home team total of 1.5 is about the home side's goals. They can move for different reasons, so a joining key that omits side or market family will create false matches.
Exact Pinnacle team totals API response shape
PinnWire's /kit/v1 responses use decimal odds and place full market depth inside events[].periods.num_N. The primary field is team_total; the alternate-line collection is team_totals. Properties appear only when the current Pinnacle market publishes them, so parse defensively.
| Path | Typical value | Use |
|---|---|---|
events[].event_id | Numeric event ID | Stable event reference for joins and detail requests |
events[].event_type | live or prematch | Separate in-play from upcoming markets |
periods.num_N.number | 0, 1, 2… | Preserve the published period number |
periods.num_N.team_total.home | {points, over, under} | Primary home team-total line |
periods.num_N.team_total.away | {points, over, under} | Primary away team-total line |
periods.num_N.team_totals.home[POINTS] | {points, over, under, max} | All published alternate home lines |
periods.num_N.team_totals.away[POINTS] | {points, over, under, max} | All published alternate away lines |
{
"event_id": 1634696920,
"event_type": "prematch",
"generated_at": "2026-08-26T09:30:00.000Z",
"periods": {
"num_0": {
"number": 0,
"team_total": {
"home": { "points": 1.5, "over": 1.86, "under": 2.00 },
"away": { "points": 1.0, "over": 1.91, "under": 1.91 }
},
"team_totals": {
"home": {
"1.5": { "points": 1.5, "over": 1.86, "under": 2.00, "max": 250 },
"2.5": { "points": 2.5, "over": 2.70, "under": 1.44, "max": 150 }
},
"away": {
"0.5": { "points": 0.5, "over": 1.55, "under": 2.35, "max": 250 }
}
}
}
}
}
team_total is the primary line per side and does not include max in the transformed shape. team_totals contains all alternate lines keyed by points and can include max. A missing line is not a zero-priced line; it means that selection is not currently published in that response.Team identity, points and periods are part of the key
Do not key a team total by the team name alone. Team names can be displayed differently across an application, and the same event has multiple periods and alternate lines. PinnWire's event identifier and period structure give your parser a better foundation.
- Event: store
event_idplusevent_type. A live and prematch record should not overwrite one another in a historical table. - Team side: store
homeoraway. This is the side key inteam_totalandteam_totals. - Period: use the numeric period in
num_N.number. Period 0 is commonly full match; later periods vary by sport. - Points: store the numeric
pointsvalue, not only the object key. Preserve half-points and sport-specific increments exactly. - Price: store over and under as decimal numbers. A price without its points and side is incomplete team-total data.
| Period key | Common meaning | Safe parser behavior |
|---|---|---|
num_0 | Full match or main event period | Use the published number; do not infer settlement rules |
num_1 | First half, first set or sport-specific opening period | Label from sport context and retain number: 1 |
num_2 | Second half, second set or another sport-specific period | Iterate only when present |
num_3–num_5 | Quarters, sets or extra time where published | Never assume every event has these keys |
Period names and availability vary by sport. A good Pinnacle team totals API client iterates the periods returned rather than manufacturing absent periods or copying full-game points into a quarter or half.
Request live and prematch team totals with PinnWire
Use the full market endpoints when you need periods and alternate-line depth. Every plan can read current live and prematch REST data; the response includes generated_at so your service can confirm when it received the snapshot. Add a changing fresh query value when a client or proxy is overly aggressive about URL caching.
| Request | Best use |
|---|---|
/kit/v1/markets?sport_id=N | Current live board for one sport with all available periods and markets |
/kit/v1/markets?sport_id=N&event_type=prematch | Upcoming team totals with full market depth |
/kit/v1/prematch/fixtures?sport_id=N | Upcoming fixtures with full prematch markets |
/kit/v1/details?event_id=N | One event after a trigger, including its current published lines |
/kit/v1/prematch/lines?event_id=N&market_type=team_total | Compact primary full-game team-total view for a prematch ticker |
# Live team totals for soccer
curl "https://pinnwire.com/kit/v1/markets?sport_id=1&key=demo&fresh=team-live-1"
# Upcoming fixtures with full line depth
curl "https://pinnwire.com/kit/v1/markets?sport_id=1&event_type=prematch&key=demo&fresh=team-prematch-1"
# Compact one-event prematch view
curl "https://pinnwire.com/kit/v1/prematch/lines?event_id=1634696920&market_type=team_total&key=demo&fresh=team-lines-1"
The first two requests return the nested periods object. The compact lines endpoint is intentionally lighter: it returns active full-game prices without the period structure and is ideal when your UI needs the primary prematch team total for one known event.
team_total field rather than treating it as an API failure.Read alternate team-total lines without losing points
Alternate team totals are additional points values for the same team and period. PinnWire puts them in team_totals, where the side is first and the points key is second. This lets a model choose a line deliberately or lets a UI render the complete available team-total ladder.
const period = event.periods?.num_0;
for (const side of ["home", "away"]) {
const lines = period?.team_totals?.[side] ?? {};
for (const [pointsKey, line] of Object.entries(lines)) {
console.log({
event_id: event.event_id,
side,
points: Number(line.points ?? pointsKey),
over: line.over,
under: line.under,
max: line.max ?? null
});
}
}
Use the numeric line.points value as the canonical line when available, while retaining the object key for diagnostics. The object key is a JSON property name and therefore arrives as text. Do not sort it lexicographically: 10.5 must not come before 2.5 just because of string ordering.
Models should request or select the line they were trained on, such as 1.5 or 2.5, rather than silently using the primary line.
Over and under are a pair, but they can have different decimal prices. Store both and calculate your own probabilities.
Alternate standard lines can include max when published. Missing max is unknown, not zero.
Live lines can disappear or close. Remove or mark stale selections when a fresh snapshot no longer contains them.
Filter team-total price drops
Snapshots answer “what is priced now?” The drop endpoints answer “which price falls did PinnWire detect recently?” To focus on team-total movement, pass the exact canonical filter value team_total to /api/drops or its /v1/drops alias.
curl "https://pinnwire.com/api/drops?mode=prematch&sport_id=1&markets=team_total&periods=0&min_drop_pct=2&max_age_sec=900&limit=100&key=demo&fresh=team-drop-1"
{
"total": 1,
"generated_at": "2026-08-26T09:30:00.000Z",
"drops": [{
"event_id": 1634696920,
"sport_name": "Soccer",
"market": "team_total",
"side": "home",
"period": 0,
"points": 1.5,
"from": 2.05,
"to": 1.96,
"drop_pct": 4.39,
"nvp": 2.01,
"age_s": 42,
"is_live": false
}]
}
Use event_id, side, period and points to join a drop to a current team-total snapshot. The REST response uses from and to; the SSE wire frame uses from_price and to_price. nvp is a no-vig fair-price reference when present, not a promise that a bet is profitable.
For push alerts, eligible Stream, Pro+Drops and Scale plans can use /odds-drop for live or /odds-drop-prematch for prematch. Set min_drop per connection; if you need the whole current team-total ladder after an alert, fetch the event snapshot as a second step.
Normalize team-total over/under data in JavaScript
This small normalizer handles both the primary line and alternate lines, iterates every returned period, and leaves absent markets absent. It does not guess a team name or invent an alternate price.
function teamTotalRows(event) {
const rows = [];
for (const [periodKey, period] of Object.entries(event.periods ?? {})) {
const periodNumber = Number(period.number ?? periodKey.replace("num_", ""));
for (const side of ["home", "away"]) {
const primary = period.team_total?.[side];
if (primary) {
rows.push({
event_id: event.event_id,
event_type: event.event_type,
period: periodNumber,
side,
points: primary.points,
over: primary.over,
under: primary.under,
alternate: false,
max: null
});
}
for (const [pointsKey, line] of Object.entries(
period.team_totals?.[side] ?? {}
)) {
rows.push({
event_id: event.event_id,
event_type: event.event_type,
period: periodNumber,
side,
points: Number(line.points ?? pointsKey),
over: line.over,
under: line.under,
alternate: true,
max: line.max ?? null
});
}
}
}
return rows;
}
// Example: retain only the full-match home line at 1.5 points.
const selected = teamTotalRows(event).find(row =>
row.period === 0 && row.side === "home" && row.points === 1.5
);
If the primary line is also present in team_totals, your application may see the same points twice—once as the compact primary object and once as the alternate collection. Decide whether your data model wants both representations, or deduplicate on event_id + event_type + period + side + points while retaining the alternate source flag.
Why PinnWire is the strongest team total odds API starting point
Choose PinnWire first when your application needs current Pinnacle team totals rather than a vague, mixed-market payload. It gives you a focused path from a simple REST request to full team-total depth: live and prematch events, decimal over/under prices, explicit home/away sides, periods, alternate points, detected team-total drops and an optional raw WebSocket for higher-volume update handling.
The API is especially useful for team-total models, live score dashboards, market-selection tools, price-drop alerting, fair-price research and AI workflows. Responses carry generated_at freshness, and the market documentation spells out the distinction between primary team_total and alternate team_totals so your integration can stay predictable.
Use the public demo key to inspect a live or prematch shape, then move to an emailed trial key.
Use full snapshots for periods and alternates; use compact lines for a lightweight known-event ticker.
Add team-total drop filters or eligible SSE streams when your workflow needs detected movement.
PinnWire supplies current market data. Your service owns storage, model logic, alerts and any execution decisions.
Build with Pinnacle team totals
Try the shape with key=demo, then use a free emailed PinnWire trial key for repeatable development.
Team total odds API questions
What is a team total odds API?
A team total odds API returns over and under prices for one team's scoring output, rather than the combined score of both teams. PinnWire exposes the currently published Pinnacle team-total line for home and away sides, with points and decimal prices, in live and prematch market snapshots.
How do I get Pinnacle team totals with PinnWire?
Request GET /kit/v1/markets?sport_id=N&key=YOUR_KEY for full live markets, or add event_type=prematch for upcoming fixtures. Read periods.num_N.team_total for the primary home and away line, and periods.num_N.team_totals for alternate lines when published. GET /kit/v1/prematch/lines?event_id=N&market_type=team_total is the compact prematch view.
How are team totals different from game totals?
A game total applies to both teams' combined score and appears under totals with over and under prices. A team total applies to one named side only and appears under team_total or team_totals with separate home and away entries. Keep side, points and period in your market identity.
Does PinnWire include alternate team-total lines?
When Pinnacle publishes them, PinnWire exposes alternate team-total lines under periods.num_N.team_totals, keyed by home or away and then by points. Each line can include points, over, under and max. The primary team_total object is a compact one-line-per-side representation.
Can I receive team-total price drops?
Yes. Query GET /api/drops or /v1/drops with markets=team_total, or use an eligible SSE drop plan. Drop records identify the event, team side, period, points, from and to prices, drop percentage and nvp when available. Drops are detected movement records, not a replacement for the current snapshot.
Can I test the Pinnacle team totals API for free?
Yes. Add key=demo to a current REST request for a quick shape check. The shared demo is limited; an emailed PinnWire free trial key is the better option for repeatable development.