Pinnacle odds developer guide · Updated August 26, 2026

Set the right minimum odds drop filter

A minimum odds drop filter decides which Pinnacle price falls deserve your application's attention. PinnWire gives you the exact control in both places developers need it: min_drop_pct for REST queries and min_drop for pushed SSE alerts.

Short answer: start with 5%, then tune from observed volume. PinnWire defaults to a 5% minimum for REST and SSE. Use 1 or 2 when your model needs earlier, more sensitive movement detection; use 35 for a workable general alert stream; use a higher value when review capacity matters more than coverage. The value means percent, not a decimal ratio: min_drop=5 means a drop of at least 5%.

What a minimum odds drop filter actually measures

PinnWire compares successive decimal prices for the same event, market, outcome and points value. It records a fall when the new decimal price is lower and the proportional change reaches at least 1%. The percentage is:

drop_pct = ((from_price - to_price) / from_price) * 100

For example, a price moving from 2.40 to 2.28 has a 5% drop: ((2.40 - 2.28) / 2.40) × 100 = 5. A filter of 5 includes that record; a filter of 5.1 excludes it. PinnWire's drop records and API responses use decimal prices, so this is the same calculation your application can reproduce from from and to.

Important unit rule: use 5 for five percent, not 0.05. Fractional percentage points are valid, so 2.5 means a minimum 2.5% fall.

Choose the PinnWire surface for your filter

REST · min_drop_pct

Query a recent buffer

Ask for detected drops whenever your worker runs. Add an upper cap, age, sport, market, period and live-only filter to make the result set precise.

SSE · min_drop

Push qualifying alerts

Keep a long-lived live or prematch connection and receive only drops at or above your threshold. This avoids frequent polling for alert workflows.

RAW WEBSOCKET

Observe every update

When a threshold would hide important reprices, the optional raw WebSocket is the full market-update surface. Apply your own change policy after maintaining local state.

For most alerting systems, PinnWire's server-side REST or SSE threshold is the cleanest first filter. It reduces work before data reaches your process, while the raw WebSocket remains available for applications that truly need every market update rather than detected drops.

Try a minimum filter with PinnWire now

The public demo key lets you inspect REST drops without signup. It is a shared allowance, so use a free emailed trial key for repeated development and production-like tests.

REST: filter the recent drops buffer

curl "https://pinnwire.com/api/drops?mode=live&min_drop_pct=3&max_drop_pct=12&max_age_sec=900&markets=moneyline,spread,total&limit=25&key=demo&fresh=min-filter-guide"

This asks PinnWire for live drops from the last 15 minutes that are at least 3% and no more than 12%. The fresh value is an optional cache-buster; PinnWire returns generated_at so a consumer can verify response freshness. The endpoint is also available as /v1/drops.

{
  "event_id": 1629725918,
  "sport_name": "Soccer",
  "market": "spread",
  "side": "home",
  "period": 0,
  "points": -0.5,
  "from": 2.37,
  "to": 2.25,
  "drop_pct": 5.06,
  "nvp": 2.21,
  "is_live": true,
  "age_s": 12
}

REST maps the engine's prices to the compact from and to fields. The drop record also carries event identity, market context, recency and nvp, the no-vig price calculated at detection time.

SSE: push alerts above a threshold

curl -N "https://pinnwire.com/odds-drop?key=YOUR_KEY&min_drop=3"

# Prematch, with a 30-second stability recheck
curl -N "https://pinnwire.com/odds-drop-prematch?key=YOUR_KEY&min_drop=3&recheck=30"

/odds-drop is the live stream; /odds-drop-prematch is prematch only. The server applies min_drop per connection, defaults it to 5%, clamps it to a 1% floor, and has no upper cap. The prematch-only recheck holds a candidate, reads its current price again, and suppresses the event if it bounced back below your threshold.

SSE access: drop streams are available on PinnWire's Stream, Pro + Drops and Scale plans. REST drops are the fallback for keys without SSE access. The optional raw WebSocket is a separate, higher-volume surface.

REST threshold semantics: default, cap and filters

GET /api/drops and its /v1/drops alias query a rolling buffer of roughly three hours. The REST default is min_drop_pct=5. PinnWire applies the minimum first, then optional filters such as max_drop_pct. The upper value is a result filter, not a second detection engine: max_drop_pct=10 excludes a 12% record from this response but does not prevent PinnWire from recording it.

ParameterMeaningExample
modelive (default) or prematchmode=prematch
min_drop_pctMinimum percentage fall; default 5min_drop_pct=2.5
max_drop_pctOptional maximum percentage fallmax_drop_pct=10
max_age_secKeep only records newer than this agemax_age_sec=600
sport_idRestrict to one sportsport_id=1
marketsCSV: moneyline, spread, total, team_totalmarkets=spread,total
periodsCSV of period numbers; 0 is full gameperiods=0,1
livelive=1 excludes events not yet startedlive=1
limitMaximum returned records; default 500limit=100

A REST threshold below 1% will not reveal sub-1% changes because the drop engine only records falls at or above 1%. Treat 1% as PinnWire's practical complete-record threshold. The percentage filter itself accepts fractional values, which is useful when tuning alert volume around a measured workload.

How threshold choice changes alert volume

The lower the minimum, the more qualifying movement your application must inspect. The higher the minimum, the quieter the stream becomes, but smaller incremental reprices disappear from the alert path. There is no universally correct minimum: configure the filter around the speed of the market, the number of events you monitor, and what an alert causes downstream.

Starting rangeBest fitTradeoff
1–2%High-sensitivity monitoring, rapid model refreshes, broad live scansMore alerts and more short-lived movement to validate
3–5%General steam or dropping-odds alertingBalanced coverage and review load; 5% is PinnWire's default
6–10%+Quiet notification channels or workflows focused on larger fallsFewer alerts, with a greater chance of missing gradual movement

Use the same threshold in your alert policy and your metrics. If the client silently applies a second local threshold, your observed count will not explain the server's count. Keep the chosen value beside each alert record so later analysis can distinguish a 2% scan from a 7% scan.

Choose the threshold by mode, sport and market

Live markets can reprice quickly, so a 1–3% threshold may be useful when the application can validate each event immediately. Prematch prices can move more slowly and may benefit from a 3–5% starting point plus the SSE recheck option when brief bounces should not notify the operator. These are starting policies, not claims about what any move means.

Do not use one global rule without measuring your own feed. Separate settings by:

  • Mode: keep live and prematch counts separate; prematch SSE can use recheck=N.
  • Sport: use sport_id to keep a high-volume sport from dominating a shared alert queue.
  • Market: filter moneyline, spread, total or team_total explicitly when your model only understands some markets.
  • Period: use periods=0 for full game or include the periods your strategy can normalize.
  • Age: pair the percentage with max_age_sec when a stale drop is not actionable.
A drop is not a reason by itself. PinnWire gives you the measured fall, market identity, timing and no-vig context. News, limits, liquidity, risk management or ordinary repricing can all contribute to movement; the alert is an input for your checks, not a guaranteed betting signal.

Implement server-side filtering in code

Keep the threshold in configuration, send it to PinnWire, and log the value with each response. This small Node example uses REST for a 3% live scan with a 12% cap:

const key = process.env.PINNWIRE_KEY;
const query = new URLSearchParams({
  mode: "live",
  min_drop_pct: "3",
  max_drop_pct: "12",
  max_age_sec: "900",
  markets: "moneyline,spread,total",
  limit: "100",
  key,
  fresh: String(Date.now())
});

const response = await fetch(`https://pinnwire.com/api/drops?${query}`);
if (!response.ok) throw new Error(`PinnWire drops HTTP ${response.status}`);
const body = await response.json();
for (const drop of body.drops) {
  console.log(drop.drop_pct, drop.from, drop.to, drop.event_id, drop.market);
}

For a push workflow, parse SSE data: frames as JSON arrays. SSE names the prices from_price and to_price, while REST maps them to from and to. Preserve both the raw event fields and your configured threshold so a later review can reproduce why the alert passed.

const stream = await fetch(
  "https://pinnwire.com/odds-drop?key=YOUR_KEY&min_drop=3"
);
// Read text/event-stream lines; ignore keep-alive comments such as :ka.
// Each data frame is a JSON array of PinnWire drop records.

Use the drop record as analytical context

PinnWire's REST drop record includes from, to, drop_pct, event and market identity, starts, is_live, age_s and nvp. nvp is a no-vig decimal price calculated from the outcomes observed at detection time; its reciprocal is a fair-probability estimate for that market snapshot. It is useful context for a model, not ground truth.

// A simple fair-price comparison after a drop alert
const available = 2.30;
const nvp = 2.21;
const estimatedEdge = available / nvp - 1;
console.log(`${(estimatedEdge * 100).toFixed(2)}%`);

Use the exact event, period, market, points and side when joining a drop to a current odds snapshot. A percentage alone is not enough to identify a line. Check generated_at on the response and age_s on records when deciding whether an alert is still actionable.

Production checklist for min_drop odds alerts

  • Start at min_drop_pct=5 or min_drop=5, then tune from measured counts.
  • Use 1 as the practical lower bound for recorded PinnWire drops; values below it cannot recover unrecorded sub-1% moves.
  • Keep the REST filter server-side with min_drop_pct; add max_drop_pct when an upper band matters.
  • Use SSE min_drop for push delivery; remember SSE has no server-side upper cap.
  • Use mode=live or mode=prematch deliberately and keep their metrics separate.
  • For prematch SSE, use recheck=N when bounced-back prices should be suppressed.
  • Filter sport, market, period and age before sending an alert to a human or an automated workflow.
  • Persist records yourself for long-term history: PinnWire's recent drop buffer is roughly three hours, not an archive.
  • Treat movement and nvp as market-data inputs; do not turn a threshold match into an automatic guarantee.

Minimum odds drop filter FAQ

What is a minimum odds drop filter?

It keeps only detected decreases at or above a chosen percentage. PinnWire uses min_drop_pct for REST and min_drop for SSE; both are percentage points, so 5 means a minimum 5% fall.

What is the default Pinnacle odds drop percentage?

PinnWire defaults to 5% on the REST drops endpoint and on both SSE streams. The engine records detectable falls from 1% upward, making 1% the practical minimum for the complete recorded-drop set.

Can I use a fractional minimum?

Yes. REST accepts fractional min_drop_pct values and SSE accepts fractional min_drop values. 2.5 means 2.5%, not 0.025%.

Can I set a maximum too?

REST supports max_drop_pct as an upper result filter. SSE has no upper-cap query parameter, so discard records above your desired maximum in the client if needed.

Does a larger drop prove sharp money or a winning bet?

No. A larger percentage is a larger observed price fall, not proof of its cause or future profitability. Use PinnWire movement with your own event, news, model and risk checks.

Does PinnWire provide historical drops?

PinnWire provides a rolling recent-drops buffer of roughly three hours. Store REST results or SSE frames yourself when you need a longer timeline, opening-line study or backtest.

Build your minimum odds drop filter with PinnWire. Test the REST threshold with key=demo, then request a free emailed trial key for your own allowance. Use min_drop_pct for queryable scans, min_drop for focused SSE alerts, and keep the raw WebSocket for workflows that need every update.