Developer guide · Market selection

Market filter odds API: filter Pinnacle odds by market

PinnWire gives you exact control over Pinnacle market depth. Filter dropping-odds records to moneyline, spread, total or team_total, narrow them by period and freshness, then read the complete line structure from current live or prematch snapshots.

Direct answer To filter Pinnacle odds by market in PinnWire, add a comma-separated markets parameter to GET /api/drops or GET /v1/drops. The exact values are moneyline, spread, total and team_total. Add periods=0,1, sport_id, drop thresholds and age limits to make a precise alert query. For one prematch event's compact current lines, use market_type=money_line|spreads|totals|team_total on /kit/v1/prematch/lines.

What a market filter should do

A useful market filter odds API lets your application ask for only the prices it can interpret or act on. A soccer alert service may need full-match moneylines and spreads. A totals model may need only over/under lines. A live dashboard may need every market in the current book but only period 0. The filter belongs close to the data request, before your application spends time grouping or rendering irrelevant records.

Market family

Choose moneyline, spread, total or team_total for drop records.

Period

Keep full-match and in-play periods separate with periods=0,1 or the period list your model supports.

Movement

Set min_drop_pct, an optional max_drop_pct and max_age_sec to control signal quality.

Depth

Use current snapshots when you need all published alternate lines, including spread points, totals points and team-total points.

PinnWire keeps those concerns explicit. The drop endpoint filters detected movement. The market snapshot endpoints expose the current book. That makes it straightforward to detect a relevant move and then fetch the full line depth for the same event and period.

Exact market filter values

The markets CSV parameter on the drop endpoints uses four canonical lower-case tokens. Separate multiple values with commas and do not add spaces unless your URL encoder handles them.

markets tokenMeaningTypical outcomes or line fields
moneylineMatch winner / moneylinehome, away, optional draw
spreadHandicap or spreadSigned points/hdp, home and away
totalGame totalpoints, over, under
team_totalOne team's totalHome or away side, points, over, under
# Two market families
markets=moneyline,spread

# All four supported families
markets=moneyline,spread,total,team_total
Use the token that the endpoint documents. Drop filters use singular spread and total. The transformed snapshot uses plural object names spreads and totals. They represent the same market families, but your query must use the exact spelling for that surface.

Moneyline, spread, total and team-total API shapes

PinnWire's /kit/v1 responses use decimal prices inside periods.num_N. The market name tells you what the price means; the line or points value is part of the selection identity.

Snapshot fieldShapeKeep in your key
money_line{ home, away, draw? }event, period, outcome
spreads{ "<hdp>": { hdp, home, away, max } }event, period, signed hdp
totals{ "<points>": { points, over, under, max } }event, period, points, side
team_total{ home: {points, over, under}, away: {…} }event, period, team side, points

Moneyline: two-way and three-way are not interchangeable

A moneyline object may contain home and away only, or those two outcomes plus draw. Preserve the presence or absence of draw in your model. A two-way market and a three-way market have different outcome sets and should not be mixed when calculating probabilities, comparing prices or joining a drop to a line.

Spreads: preserve the signed line

Each spread line includes a signed home-perspective hdp and paired home and away decimal prices. A price without its handicap is not a complete selection. Iterate all keys in spreads because alternate lines can be available at the same event and period.

Totals and team totals: points are identity

A game total pairs one points value with over and under. A team total does the same separately for home and away. Keep points and side together: over 2.5 is a different selection from over 3.5, and a home team total is different from a game total.

{
  "periods": {
    "num_0": {
      "number": 0,
      "money_line": { "home": 1.91, "draw": 3.55, "away": 4.20 },
      "spreads": { "-0.5": { "hdp": -0.5, "home": 2.02, "away": 1.84 } },
      "totals": { "2.5": { "points": 2.5, "over": 1.95, "under": 1.91 } },
      "team_total": { "home": { "points": 1.5, "over": 1.86, "under": 2.00 } }
    }
  }
}

Build a filtered dropping-odds request

Use GET /api/drops (or its /v1/drops alias) when you want detected price falls rather than the entire current market book. The public demo key works for a quick REST check.

curl · prematch spread and total dropsREST buffer
curl "https://pinnwire.com/api/drops?mode=prematch&sport_id=1&markets=spread,total&periods=0,1&min_drop_pct=2&max_age_sec=900&limit=100&key=demo&fresh=market-filter-1"

This asks for soccer (sport_id=1) prematch drops in the spread or total families, only in periods 0 and 1, at least 2%, no older than 15 minutes, with at most 100 records. fresh is a harmless cache-buster; PinnWire still proves response freshness with generated_at.

{
  "total": 1,
  "generated_at": "2026-08-26T09:30:00.000Z",
  "drops": [{
    "event_id": 1634696920,
    "sport_name": "Soccer",
    "market": "spread",
    "side": "home",
    "period": 0,
    "points": -0.5,
    "from": 2.05,
    "to": 1.96,
    "drop_pct": 4.39,
    "nvp": 2.01,
    "age_s": 42,
    "is_live": false
  }]
}

REST drop output uses market for the canonical market type and side for the outcome. It also includes movement context such as from, to, drop_pct, period, points, age_s and nvp when available.

Add period, age and movement filters

Market selection becomes much more useful when it is paired with time and movement constraints. These are the exact /api/drops parameters:

ParameterExampleWhat it does
modelive or prematchSelects the live or prematch drop buffer; default is live.
sport_id1Restricts to one sport. Soccer is 1, tennis 2, basketball 3; see the full sport list.
marketsmoneyline,totalCSV subset of the four canonical market tokens.
periods0,1,2CSV period numbers. Period 0 is full match; later numbers are published sport-specific periods.
min_drop_pct2.5Minimum percentage fall; default is 5. Detected records begin at 1%.
max_drop_pct12Optional upper cap to remove unusually large moves from a band.
max_age_sec900Returns only drops newer than the given number of seconds.
live1Excludes drops whose event has not started.
limit100Maximum records returned; default is 500.

periods is a numeric filter, not a market filter. Common keys are num_0 full match, num_1 first half or set, num_2 second half or set, num_3num_4 quarters or sets and num_5 extra time. Availability varies by sport and event, so iterate what is present rather than assuming every period exists.

Do not silently widen a query. If a model supports only full-match totals, pass markets=total&periods=0. Do not fetch all markets and later infer period 0 from a missing or reordered object.

Use market_type for compact prematch lines

The compact prematch endpoint is a different filter surface. Use GET /kit/v1/prematch/lines?event_id=N after you know the event, and optionally select one full-game market with market_type.

market_type valueReturned key in linesUse for
money_linemoney_lineCurrent winner prices
spreadsspreadsCurrent handicap lines
totalstotalsCurrent game over/under lines
team_totalteam_totalCurrent home/away team totals
curl "https://pinnwire.com/kit/v1/prematch/lines?event_id=1634696920&market_type=totals&key=demo&fresh=lines-1"

{
  "event_id": 1634696920,
  "home": "Home FC",
  "away": "Away FC",
  "lines": {
    "totals": [
      { "points": 2.5, "over": 1.95, "under": 1.91, "max": 250 }
    ]
  }
}

This endpoint is intentionally compact: it returns active full-game lines and does not include the period tree. Use full market snapshots when your application needs period-by-period depth; use the compact endpoint for a ticker, event card or one known prematch fixture.

Important naming difference: /api/drops?markets=moneyline,spread,total,team_total and /kit/v1/prematch/lines?market_type=money_line|spreads|totals|team_total are both correct. Do not copy the plural snapshot names into the drop filter or the singular drop names into market_type.

Handle specials and props separately

Player props, team props, exact scores and futures are separate special-market records. They are not folded into the ordinary fixture market objects by default. Request them deliberately from /kit/v1/markets or /kit/v1/prematch/fixtures:

# Add specials as flat event rows
curl "https://pinnwire.com/kit/v1/prematch/fixtures?sport_id=1&include_specials=1&key=demo&fresh=specials-flat"

# Attach each special to its parent fixture when available
curl "https://pinnwire.com/kit/v1/prematch/fixtures?sport_id=1&include_specials=nested&key=demo&fresh=specials-nested"

With include_specials=1, specials are extra rows. With include_specials=nested, they appear under a parent event's specials array when the parent is present. A special can also be fetched directly by its event_id through /kit/v1/details.

Specials use special_markets.num_N, where each market has named prices, optional points and max_risk. A special's detected drop can still have the canonical market type needed by the markets filter; named participant context appears in participant_name when available.

Keep the special flag and drop filter distinct. include_specials controls whether special records enter a fixture response. markets controls which detected drop market types remain in the drop response. One does not turn on the other.

Normalize API names in your own code

A canonical internal enum prevents a common integration bug: mixing endpoint vocabulary with display labels. Keep one internal value, then translate only at the request or response boundary.

Internal valueDrop query tokenSnapshot fieldCompact market_typeSSE display label
moneylinemoneylinemoney_linemoney_lineMoneyline
spreadspreadspreadsspreadsSpread
totaltotaltotalstotalsTotal
team_totalteam_totalteam_totalteam_totalTeam Total

REST drops return the canonical token as market. SSE drop frames use wire-oriented fields such as sect, outcome, from_price and to_price. SSE currently exposes min_drop and, for prematch, recheck; it does not accept the REST markets or periods query filters. If a push stream must be narrowed to one market, filter its frames in your consumer using the mapping above, or poll the REST buffer for server-side market and period selection.

Runnable JavaScript: query a market-filtered drop feed

This Node.js 18+ example uses URLSearchParams, so the commas and cache-buster are encoded safely. It preserves the API's market and period fields for downstream joins.

market-filter.mjsNode.js 18+
const params = new URLSearchParams({
  mode: "prematch",
  sport_id: "1",
  markets: "moneyline,spread,total",
  periods: "0,1",
  min_drop_pct: "2",
  max_drop_pct: "12",
  max_age_sec: "900",
  limit: "100",
  key: "demo",
  fresh: `market-filter-${Date.now()}`
});

const response = await fetch(`https://pinnwire.com/api/drops?${params}`);
const payload = await response.json();
if (!response.ok) throw new Error(payload.message || payload.error || response.status);

console.log("response generated", payload.generated_at);
for (const drop of payload.drops ?? []) {
  // market is moneyline | spread | total | team_total
  // Keep period + points with the price movement.
  console.log({
    event: drop.event_id,
    market: drop.market,
    period: drop.period,
    points: drop.points,
    side: drop.side,
    from: drop.from,
    to: drop.to,
    drop_pct: drop.drop_pct
  });
}

For production, use a personal key rather than the shared demo allowance, check generated_at before presenting data as current, and treat a 429 as a rate-limit response instead of silently retrying in a tight loop. PinnWire's API docs describe plan limits, error messages and the freshness fields.

Why PinnWire fits market-depth workflows

Choose PinnWire when your application needs a clear Pinnacle reference, complete line depth and precise drop selection in one focused API. You get current live and prematch snapshots, decimal prices, periods, alternate spread and total lines, team totals, a recent drop buffer and optional push surfaces as your workflow grows.

Research screen

Use REST snapshots to display all published moneyline, spread, total and team-total lines without throwing away alternate points.

Drop monitor

Use markets, periods, thresholds and age limits to send only the movement your model understands.

Prematch ticker

Use /kit/v1/prematch/lines plus market_type for a compact one-event response.

Higher-volume pipeline

Move to the optional raw WebSocket when your own book needs every subscribed market update.

PinnWire is read-only Pinnacle odds data, not a bookmaker, settlement system or historical archive. Store responses you are permitted to retain when your application needs a longer history. For detected movement, see the dropping-odds API guide; for a broader integration reference, start with market shapes in the docs.

Market filter API questions

How do I filter Pinnacle odds by market in an API?

With PinnWire, use the markets CSV parameter on GET /api/drops or /v1/drops: moneyline, spread, total and team_total. For a compact prematch event view, GET /kit/v1/prematch/lines accepts market_type=money_line, spreads, totals or team_total.

What market filter values does PinnWire support?

The dropping-odds market filter accepts the canonical tokens moneyline, spread, total and team_total, separated by commas. They correspond to the money_line, spreads, totals and team_total objects in transformed event snapshots.

Can I filter PinnWire drops by period as well as market?

Yes. Add periods as a comma-separated list of numbers to /api/drops or /v1/drops. Period 0 is full match, period 1 is commonly the first half or set, period 2 the second half or set, and later numbers depend on the sport and its published periods.

How are moneyline, spread and total markets shaped?

PinnWire returns decimal moneyline outcomes as home, away and optional draw; spreads as signed hdp lines with home and away prices; totals as points with over and under prices. Team totals have home and away sides, each with points, over and under.

How do specials work with a PinnWire market filter?

Specials such as player props are separate from ordinary fixture rows. Request them with include_specials=1 for flat rows or include_specials=nested to attach them to a parent event. Their drop records can still be selected by the canonical markets filter and identify named participants when available.

Can I test market-filtered Pinnacle odds for free?

Yes. Use key=demo for a quick REST request. The public demo is shared and limited, so a free personal trial key emailed by PinnWire is the better choice for development.

Filter the Pinnacle markets your app actually needs

Try the market-filtered REST API with key=demo, then use a free trial key for your integration.