Skip to main content

pinnodds

Python client for the pinnodds Pinnacle odds API.

Pinnacle retired its public API in July 2025. pinnodds is an independent service that carries the same market data — live and prematch — as REST snapshots and as Server-Sent Event streams of odds drops.

pip install pinnodds

Python 3.8+. One dependency (requests).

Usage

from pinnodds import Client, SPORTS

api = Client("YOUR_KEY")

board = api.markets(sport_id=SPORTS["soccer"])
print(len(board["events"]), "live events")

Drop alerts arrive as an ordinary iterator, so a monitoring loop is three lines:

for d in api.stream_drops(min_drop=5):
    print(f'{d["home"]} v {d["away"]}  {d["sect"]} {d["outcome"]}  '
          f'{d["from_price"]} -> {d["to_price"]}')

The generator reconnects by itself when the network blips and re-raises anything that reconnecting cannot fix — a bad key, or a plan without SSE. The opening {"type": "connected"} handshake is filtered out, so every item you get is a real alert. Get a key at pinnodds.com; no card and no Pinnacle account needed.

The stream and the buffer return different shapes

An SSE alert names the market in sect ("Moneyline"), the moving selection in outcome ("Home"), the prices in from_price/to_price, and the event in id. A drops() row is the enriched form: market ("moneyline"), designation ("home"), from/to, event_id, and a precomputed drop_pct.

SSE alerts carry no drop_pct, so derive it when you need one:

pct = (1 - d["to_price"] / d["from_price"]) * 100

What they carry instead is limit (Pinnacle's max stake on that selection), nvp (the no-vig fair price) and price_x/price_y/price_z for the rest of the market at alert time.

Endpoints

api.markets(sport_id=1)                        # live board
api.markets(sport_id=1, event_type="prematch") # prematch board
api.markets(sport_id=1, since=last_version)    # only what changed
api.markets(sport_id=1, include_specials=True) # + props, futures, outrights
api.details(event_id)
api.prematch_fixtures(sport_id=1)
api.prematch_markets(event_id)
api.prematch_lines(event_id, market_type="total")
api.drops(sport_id=1, min_drop_pct=5)          # recent buffer, no open connection
api.health()
api.ping()                                     # no auth

Feed since the last value from the previous response to pull a delta instead of the whole board. Prematch versions churn quickly, so a cursor more than a few minutes old will return most of the board anyway.

Errors

from pinnodds import AuthError, RateLimitError, PinnoddsError

try:
    api.markets(sport_id=1)
except AuthError:
    ...                       # bad key, or the plan lacks this surface
except RateLimitError as e:
    time.sleep(e.retry_after or 1)
except PinnoddsError as e:
    print(e.status, e.payload)

AuthError and RateLimitError both subclass PinnoddsError, so catching the base class catches everything this library raises.

Details worth knowing

Every line Pinnacle prices comes through, quarter lines included — soccer totals at 1.75 / 2.25 / 2.75 / 3.25 and quarter-ball handicaps at -0.75 / -1.25 / -1.75 / -2.25, not just the halves. Depth is the same on every plan; plans differ in rate limit and push access, not in what you can see.

Specials are opt-in. Pass include_specials=True and props, handicap variants, futures and outrights arrive as their own event rows, each carrying a special that describes it ("3-Way Handicap Gornik Zabrze +1"), a special_category ("Team Props", "Futures", "Relegation"), its odds under special_markets, and a parent_id pointing at the fixture — so correlating them needs no name matching. They're off by default because they dominate the payload: soccer prematch is ~1,500 events without the flag and ~12,400 with it.

drops() sends max_age_sec=3600 unless you override it. Omitting the parameter makes the endpoint return an empty list no matter what else you filter on, so the client supplies it rather than handing you a silent zero-row result.

Links

Not affiliated with, endorsed by, or connected to Pinnacle.

MIT

Metadata

Release files for pinnodds 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pinnodds 0.1.0
File Size Uploaded
pinnodds-0.1.0.tar.gz 10.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pinnodds 0.1.0
File Interpreter ABI Platform
pinnodds-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 19.2 kB

Release files / pinnodds-0.1.0.tar.gz

Download URL pinnodds-0.1.0.tar.gz
Size 10.3 kB
Tags Source
SHA-256 checksum
How to use checksums
d6ec28c79f99f78bb088621ecb4f4fc5987baf5e27a08d769adee510af17557c
BLAKE2b-256 checksum
How to use checksums
d7c7d07d967936ee50978c5bd446883d765d05871be21f704cc58e8122b2b3d1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.5

Release files / pinnodds-0.1.0-py3-none-any.whl

Download URL pinnodds-0.1.0-py3-none-any.whl
Size 9.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5218fbb35f8432dadab663ee0fd729e312abf93442e2c88205aa5972c61bb496
BLAKE2b-256 checksum
How to use checksums
9b900e5f1b12e5ec7669cacd0d4a997a239fbcfb39360f8cd8400fb9de218076
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.5

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page