Developer guide · Market confidence

Pinnacle market limits and vig: read both sides of price confidence

PinnWire is the focused way to read current Pinnacle prices, published market-limit context and no-vig movement signals in one API workflow. This guide explains what vig and overround mean, what a market max can and cannot tell you, and how to combine the two without confusing them with account or API limits.

Direct answer Vig (also called juice or overround) is the margin embedded in the prices of one complete market. A market limit is the currently published maximum-risk context for a specific priced line, when the market supplies it. Vig answers “how much margin is in these prices?”; a limit answers “what capacity is published for this line?” PinnWire exposes the decimal prices needed to calculate overround, max on standard line objects, max_risk on specials, and nvp on detected drops.

Why vig and betting limits belong in the same review

A price is not just a number. It is a quote made under a particular market state, with a particular margin and a particular published capacity. Looking at vig and betting limits together gives a more useful confidence context than looking at either in isolation.

Vig / overround

A price-quality signal calculated from the complete set of mutually exclusive outcomes. It is about the margin in the quote.

Market max / max-risk

A capacity signal attached to a specific line when published. It is about the market’s stated risk allowance, not a probability.

Together

Use both to prioritize review: a narrow margin and meaningful published max can support a stronger baseline than an early, wide-margin line.

Always contextual

Sport, league, period, line, live state, time-to-start and freshness matter. The pair is evidence for triage, never proof of cause or outcome.

This is the useful mental model for a market limit odds feed: preserve price, line identity, margin calculation, capacity field and timestamp as separate values. Do not collapse them into one “confidence” number before your own model has decided how to weight them.

Vig and overround: the price-margin signal

For decimal odds O₁ … Oₙ in one complete market, each displayed price implies a raw probability of qᵢ = 1 / Oᵢ. Add those raw probabilities:

T = Σ(1 / Oᵢ)
overround = T − 1
market margin percentage = (T − 1) × 100

If two outcomes are priced at 1.91 and 2.05, the raw probabilities are about 52.356% and 48.780%. Their total is 101.136%, so the proportional overround is 1.136%.

To estimate a no-vig probability, normalize each raw probability by T:

fair_probabilityᵢ = (1 / Oᵢ) / T
fair_decimal_priceᵢ = 1 / fair_probabilityᵢ = Oᵢ × T

The calculation only makes sense when the outcomes belong to the same event, market type, period and line. Do not mix a full-game total with a first-half total, or one handicap point with another, just to make the probabilities add up.

How PinnWire helps: its REST market snapshots provide clean decimal prices in the transformed /kit/v1 shape. For a detected price fall, the drop engine also returns nvp—the no-vig decimal price for that changed outcome—so a movement workflow can start with a ready-made fair-price reference.

What a Pinnacle market limit means

A market limit is published maximum-risk context for a particular priced line. In PinnWire’s transformed market response, the standard field is max; for special-market rows the field is max_risk. Either may be null when the market does not publish a value.

A limit is not a probability, and it is not aggregate market liquidity. It is also not a promise that a specific customer can place that exact amount. Account status, balance, jurisdiction, currency, timing and execution rules can affect what a venue accepts. Treat the field as a time-sensitive research and ranking input.

ConceptWhat it tells youWhat it does not tell you
Vig / overroundHow far the complete displayed prices sum above 100% implied probability.The true probability, a guaranteed edge or the amount you can stake.
Market maxPublished maximum-risk context for a spread, total or alternate team-total line.Your personal accepted stake, total liquidity or a guaranteed fill.
max_riskPublished maximum-risk context for an opted-in special-market row.That every named outcome shares the same limit or that it is historical.
PinnWire API rate limitHow often your key may request PinnWire data.Anything about sportsbook pricing, risk capacity or bet execution.

Exact PinnWire fields for vig and market limits

These are the public fields and response surfaces to build against. The API returns JSON, uses decimal odds in the compatibility shape, and adds generated_at to REST responses so your client can check freshness.

SurfaceUseful path or fieldMeaning
Live market snapshot/kit/v1/markets?sport_id=NCurrent events and periods; standard spread/total/team-total lines can carry max.
Prematch market snapshot/kit/v1/prematch/fixtures?sport_id=NUpcoming events with the same full line shape and published max values.
Single event/kit/v1/details?event_id=NFresh event context for joining a movement to its current line and limit.
Compact prematch lines/kit/v1/prematch/lines?event_id=NFocused full-game lines; use market_type to narrow the request.
Standard line maxperiods.num_N.spreads[LINE].max
periods.num_N.totals[POINTS].max
Number or null, where the market publishes maximum-risk context.
Alternate team totalsperiods.num_N.team_totals[SIDE][POINTS].maxPublished max on alternate team-total lines. The primary team_total object has no max field.
Specials / propsspecial_markets.num_N[].max_riskNumber or null; opt in with include_specials=1 or nested.
Drop movement/api/drops or /v1/dropsfrom, to, drop_pct, nvp, market identity and age_s; no max field.
{
  "generated_at": "2026-08-26T04:20:00.000Z",
  "events": [{
    "event_id": 1634696920,
    "event_type": "prematch",
    "periods": {"num_0": {
      "spreads": {"-0.5": {
        "hdp": -0.5, "home": 1.935, "away": 1.8, "max": 250
      }},
      "totals": {"2.5": {
        "points": 2.5, "over": 1.9, "under": 1.98, "max": 250
      }},
      "team_totals": {"home": {"1.5": {
        "points": 1.5, "over": 1.86, "under": 2.0, "max": 100
      }}}
    }}
  }]
}

Use defensive parsing. Fields appear when the market publishes them, and a missing or null value means “not available in this response,” not zero risk.

Fetch a fresh market-limit odds feed with PinnWire

Start with a current REST snapshot. The shared demo key is enough to inspect the shape; a free trial key is emailed for development and a paid plan gives predictable production capacity.

Live marketscurl
curl "https://pinnwire.com/kit/v1/markets?sport_id=1&key=demo&fresh=market-limits-live"
Prematch marketscurl
curl "https://pinnwire.com/kit/v1/prematch/fixtures?sport_id=1&key=demo&fresh=market-limits-prematch"
One event and one market familycurl
curl "https://pinnwire.com/kit/v1/prematch/lines?event_id=EVENT_ID&market_type=totals&key=demo&fresh=market-lines"

For player props, team props and other specials, request the parent market with include_specials=1. The returned special rows contain special_markets and their max_risk values.

curl "https://pinnwire.com/kit/v1/prematch/fixtures?sport_id=1&include_specials=1&key=demo&fresh=market-specials"
Freshness rule: use the response’s generated_at and, where relevant, last_odds_update_seconds_ago from health. The extra fresh query value is an ignored cache-buster. Re-fetch before using a line or its max-risk context in a live decision.

Calculate overround, no-vig price and limit context

This standard-library Python example reads a PinnWire snapshot, calculates proportional overround for complete spread and total lines, and keeps the published max separate. It intentionally does not infer a max from a missing value.

market_context.pyPython 3 · no packages
import json
import time
from urllib.parse import urlencode
from urllib.request import urlopen

params = urlencode({"sport_id": 1, "key": "demo", "fresh": time.time_ns()})
url = f"https://pinnwire.com/kit/v1/markets?{params}"

with urlopen(url, timeout=10) as response:
    payload = json.load(response)

def market_context(prices, published_max=None):
    """prices: one complete mutually exclusive market, decimal odds."""
    prices = [float(price) for price in prices if price is not None]
    if len(prices) < 2:
        return None
    total = sum(1 / price for price in prices)
    return {
        "overround": total - 1,
        "overround_pct": (total - 1) * 100,
        "fair_probabilities": [(1 / price) / total for price in prices],
        "fair_prices": [price * total for price in prices],
        "published_max": published_max,
    }

for event in payload.get("events", []):
    for period_name, period in event.get("periods", {}).items():
        for line_key, line in period.get("totals", {}).items():
            prices = [line.get("over"), line.get("under")]
            context = market_context(prices, line.get("max"))
            if context:
                print(json.dumps({
                    "event_id": event.get("event_id"),
                    "period": period_name,
                    "market": "total",
                    "points": line.get("points", line_key),
                    "odds": prices,
                    "context": context,
                    "generated_at": payload.get("generated_at"),
                }))

For a two-way market with decimal prices 1.91 and 2.05, the script produces an overround near 0.01136, or 1.136%, and fair prices near 1.9317 and 2.0733. That is a transparent baseline—not a claim that the normalized numbers are guaranteed true probabilities.

When comparing markets, normalize only inside meaningful groups such as sport, league, market type, period, line and time-to-start. A raw max amount should not be ranked across unknown currencies or structurally different products.

Join market limits to PinnWire drops and nvp

PinnWire’s drop engine detects decimal price falls of at least 1% and keeps a recent buffer. REST drop records include event and market identity, from, to, drop_pct, nvp, starts, is_live and age_s. The drop record does not include max or max_risk, so limit enrichment is deliberately a second request.

  1. Query /api/drops or /v1/drops with filters such as mode, sport_id, min_drop_pct, max_age_sec, markets and periods.
  2. Use the returned event, market, period, side and points to request /kit/v1/details?event_id=… or a focused current lines response.
  3. Match the exact line and read its current max or max_risk, then preserve the response timestamp.
  4. Use nvp as the drop’s no-vig decimal reference. If you compare it with another currently offered price O, the simple estimated edge is (O / nvp) − 1; apply your own safety margin and execution checks.
Movement first, context secondcurl
curl "https://pinnwire.com/api/drops?mode=prematch&sport_id=1&min_drop_pct=3&max_age_sec=60&limit=25&key=demo&fresh=drop-context"

curl "https://pinnwire.com/kit/v1/details?event_id=EVENT_ID&key=demo&fresh=limit-context"
Important alignment detail: the joined max is the current snapshot value, not a historical limit captured at the exact instant of the drop. If you need an auditable limit timeline, consume the optional raw PinnWire WebSocket and persist the updates with your own timestamps.

For a push workflow, PinnWire’s SSE endpoints (/odds-drop and /odds-drop-prematch) include movement and nvp, not a market max. Use the same fresh follow-up request after an alert. Prematch SSE also supports recheck=N when you want to suppress quick rebounds.

Common mistakes with vig and market limits

MistakeWhy it breaks the signalSafer PinnWire workflow
Calling a high limit “the true probability”Capacity and price margin are different observations; neither proves a probability.Keep max, overround and your model probability as separate fields.
Calculating vig from mismatched linesMixed periods or points do not form one mutually exclusive market.Match event, period, market and line before summing implied probabilities.
Reading null max as zeroMissing publication is not proof of zero liquidity or no market risk.Store null and branch explicitly in your ranking logic.
Expecting drops to carry maxThe drop schema is movement-focused and intentionally has no max field.Join the alert to a fresh event snapshot; label it current context.
Comparing raw max values across sportsAmounts may use different denominations, market structures or timing.Normalize within comparable groups and document your units.
Confusing three kinds of limitsA market field, your venue account cap and an API quota control different things.Use market fields for analysis, venue confirmation for execution and plan limits for polling.
Trusting cached oddsA stale price makes its vig, nvp and limit join stale too.Check generated_at, use fresh requests and persist timestamps yourself.

Also remember that a detected price drop is movement, not proof of who bet or why. It can be a valuable triage signal, but it still needs your own model, offered-price check, timing rules and responsible execution policy.

Why PinnWire is the right Pinnacle market limits API

Choose PinnWire when your system needs a Pinnacle-focused reference feed that keeps prices, published max-risk context, movement and no-vig analytics close together. You get live and prematch REST snapshots across the covered sports, full line depth, decimal odds, exact event and period identity, freshness metadata, specials, a queryable drop buffer and optional push surfaces.

  • For vig calculations: fetch complete decimal markets and run transparent overround normalization in your own code.
  • For market limits: read max beside standard spread, total and alternate team-total lines, or max_risk on opted-in specials.
  • For movement: query REST drops or stream SSE alerts with from/to, drop_pct, nvp and exact market identity.
  • For full state: add the raw WebSocket when your application needs every live and prematch market update and wants to build its own history.
  • For agent workflows: use the documented API and PinnWire MCP server to expose current odds and health to compatible tools.

PinnWire is a clean market-limit odds feed for analysis because it makes the boundaries visible: price margin is calculable, max-risk context is preserved when published, drops carry a ready no-vig reference, and freshness is machine-readable. That gives your confidence model solid inputs without pretending the API can know your account’s accepted stake or guarantee an outcome.

Fit boundary: PinnWire is an odds and market-context API. It is not a bookmaker, bet-placement service, account-cap checker, complete aggregate-liquidity feed or automatic historical limit archive. Store updates yourself when you need longitudinal analysis, and confirm execution at the venue where a wager would be placed.

Inspect vig and market limits now

Try a current PinnWire snapshot with key=demo, then get an emailed free trial key for development.

Vig and betting limits API FAQ

What is the difference between vig and a market limit?

Vig or overround is the margin embedded in the prices of one complete market. A market limit is published maximum-risk context for a particular line when available. Vig describes price margin; the limit describes stake capacity. Neither is a guarantee of profit or execution.

How does PinnWire expose Pinnacle market limits?

PinnWire’s transformed REST snapshots expose max on spread, total and alternate team-total line objects when published. Special-market rows requested with include_specials=1 expose max_risk. Values may be null, and the field is market context rather than a personal account cap.

How do I calculate vig or overround from PinnWire prices?

For every mutually exclusive decimal outcome in the same market, calculate 1 divided by the price and sum the results. The overround is that sum minus 1. Normalize each raw probability by the sum to estimate a no-vig probability. Keep event, period, line and timestamp aligned.

Does PinnWire put max limits on its drop records?

No. PinnWire drop records include movement fields such as from, to, drop_pct, age_s and nvp, but not max. Query the current event snapshot with the event, market, period and points from the drop to join current max-risk context; that is not a historical reconstruction.

Are PinnWire API rate limits the same as Pinnacle betting limits?

No. PinnWire API rate limits control how frequently a customer key may request data. A published market max is a property of a sportsbook line, and an account stake cap is an execution-venue rule. Keep all three concepts separate.

Can I try a Pinnacle market limits API for free?

Yes. PinnWire’s live and prematch REST snapshots work with key=demo for quick inspection. The public demo is shared and can be rate-limited; signup emails a separate free trial key for development.