Metadata-Version: 2.4
Name: pinnapi
Version: 0.1.1
Summary: Real-time Pinnacle odds & drop alerts in Python — REST snapshots and SSE drop streams from pinnapi.com, the drop-in alternative to the closed Pinnacle API.
Project-URL: Homepage, https://pinnapi.com
Project-URL: Documentation, https://pinnapi.com/docs
Project-URL: API reference (LLM-friendly), https://pinnapi.com/llms-full.txt
Project-URL: Blog, https://pinnapi.com/blog
Author-email: pinnapi <info@pinnapi.com>
License: MIT
License-File: LICENSE
Keywords: arbitrage,betting,closing-line-value,dropping-odds,odds,odds-api,pinnacle,pinnacle-api,sports-betting,sse,steam-moves
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.8
Requires-Dist: requests>=2.20
Description-Content-Type: text/markdown

# pinnapi — Pinnacle odds API for Python

Real-time **Pinnacle odds and drop alerts** in Python: REST snapshots of live + prematch markets, and Server-Sent-Events streams that push every odds drop to your code in **~15–40 ms**.

```bash
pip install pinnapi
```

> **Does Pinnacle still have a public API?** No — Pinnacle closed its public API on **July 23, 2025** (only bespoke commercial/academic access remains). [pinnapi.com](https://pinnapi.com) is an independent drop-in replacement: the same familiar response shape, served from its own real-time feed. No Pinnacle account needed — your API key is your login, and a free trial key takes seconds (no card).

## Quickstart

```python
from pinnapi import Client, SPORTS

api = Client("YOUR_KEY")  # free trial key at https://pinnapi.com/

# Live soccer markets (moneyline, spreads, totals, team totals — every period)
events = api.markets(sport_id=SPORTS["soccer"])

# Prematch instead of live
fixtures = api.prematch_fixtures(sport_id=SPORTS["tennis"])

# What just dropped? (queryable buffer, no open connection needed)
recent = api.drops(mode="live", min_drop_pct=5)
```

## Real-time drop alerts (SSE)

Stream every market whose price falls past your threshold, the instant it happens — this is the feed for steam chasing, dropping-odds alerts, and arbitrage windows:

```python
# Requires a plan with SSE (Drops / Edge / Scale)
for drop in api.stream_drops(mode="live", min_drop=5):
    print(f'{drop["home"]} v {drop["away"]} · {drop["market"]} '
          f'{drop["from"]} → {drop["to"]} (▼{drop["drop_pct"]}%)')
```

`mode="prematch"` streams pre-game drops (optional `recheck=N` holds an alert N seconds and re-verifies before sending). Reconnects automatically on network hiccups; auth/plan errors raise immediately.

## Why Pinnacle's line?

Pinnacle is the market's reference price — the sharp line the rest of the market follows. When it breaks, soft books take seconds to correct; everything in between is your window. A polled aggregator hears about the move on its next cycle; this feed is **push, not poll**.

## API surface

| Method | Endpoint | What it returns |
|---|---|---|
| `markets(sport_id, event_type)` | `GET /kit/v1/markets` | Live (default) or prematch markets for a sport |
| `details(event_id)` | `GET /kit/v1/details` | One live event |
| `prematch_fixtures(sport_id)` | `GET /kit/v1/prematch/fixtures` | All prematch fixtures + markets |
| `prematch_markets(event_id)` | `GET /kit/v1/prematch/markets` | Markets for one prematch event |
| `prematch_lines(event_id)` | `GET /kit/v1/prematch/lines` | Compact line view |
| `drops(mode, ...)` | `GET /api/drops` | Recent dropping-odds buffer (filterable) |
| `stream_drops(mode, min_drop)` | SSE `/odds-drop[-prematch]` | Push stream of drop alerts |
| `health()` / `ping()` | `GET /health` / `/ping` | Service status / liveness |

**Sports** (`SPORTS` dict): soccer=1, tennis=2, basketball=3, hockey=4, football=5, baseball=6, rugby=7, mma=8, boxing=9, other=10, esports=11, golf=12.

**Errors:** `AuthError` (bad key / plan lacks the surface), `RateLimitError` (with `.retry_after` seconds), `PinnapiError` (everything else, with `.status` and `.payload`).

## Pricing & limits

Free trial: 100 REST requests/day, no card. Paid plans from **$99/mo** (SSE drop streams, 10–30 req/sec REST, raw WebSocket add-on). Full details: [pinnapi.com](https://pinnapi.com/#pricing) · [API docs](https://pinnapi.com/docs) · [LLM-friendly reference](https://pinnapi.com/llms-full.txt).

## Notes

- Real-time feed only (live + prematch) — no historical archive; buffer the stream yourself if you need history.
- One concurrent SSE connection per account per stream (live and prematch counted separately).
- pinnapi is an independent service, **not affiliated with or endorsed by Pinnacle**.

MIT licensed.
