Python SDK for parlay-api.com — drop-in replacement for the-odds-api with player props, prediction markets, and WebSocket streaming.
Project description
parlay-api
Python SDK for parlay-api.com, a drop-in replacement for the-odds-api.com with 22 sources, player props, prediction markets, and WebSocket streaming.
pip install parlay-api
from parlay_api import ParlayAPI
client = ParlayAPI(api_key="YOUR_KEY")
events = client.odds("baseball_mlb", regions="us", markets="h2h,spreads,totals")
Why
The-odds-api is fine but ships flat -115/-115 placeholders for half the props you actually want, costs 5 to 6 times more at the Enterprise tier, and has no streaming. ParlayAPI ships real American odds across 22 sources, integrates Polymarket as a sharp prediction-market baseline, and runs WebSockets on Business+ tiers.
The SDK preserves TOA's endpoint shape, so migration is one config change.
Migration from the-odds-api
If you're currently using the unofficial Python client:
# before
from the_odds_api import OddsAPI
client = OddsAPI(api_key=KEY)
events = client.get_odds(sport_key="basketball_nba", ...)
# after, three-line diff
from parlay_api import ParlayAPI
client = ParlayAPI(api_key=KEY)
events = client.odds("basketball_nba", ...)
If you're calling TOA via raw HTTP, just swap the base URL:
# before
url = "https://api.the-odds-api.com/v4/sports/basketball_nba/odds"
# after
url = "https://parlay-api.com/v4/sports/basketball_nba/odds"
Same paths (/v4/sports, /v4/sports/{sport}/odds,
/v4/sports/{sport}/events, /v4/sports/{sport}/scores,
/v4/historical/sports/{sport}/odds), same response shapes, same
query parameters (regions, markets, bookmakers, oddsFormat,
dateFormat, eventIds, commenceTimeFrom, commenceTimeTo).
What's different from TOA
Beyond TOA's endpoints, ParlayAPI exposes:
| Endpoint | What |
|---|---|
GET /v1/sports/{sport}/props |
Flat list of paired O/U player props across every source |
GET /v1/sports/{sport}/props/markets |
Available prop market keys + which books offer each |
GET /v1/sports/{sport}/futures |
Outrights and championship futures grouped by competition |
GET /v1/usage |
Current API key usage state (tier, credits used, credits remaining) |
WSS /ws/odds/{sport}?apiKey= |
Live odds stream, Business+ tier |
Plus markets=player_* works on the standard /v4/sports/{sport}/odds
endpoint, returning paired Over/Under in TOA's exact event shape.
Quickstart
from parlay_api import ParlayAPI
client = ParlayAPI(api_key="YOUR_KEY")
# List sports
print([s["key"] for s in client.sports()])
# h2h + spreads + totals across every book
events = client.odds(
"basketball_nba",
regions="us",
markets="h2h,spreads,totals",
odds_format="american",
)
# Player props (TOA-shaped)
prop_events = client.odds(
"baseball_mlb",
markets="player_strikeouts,player_total_bases,player_hits",
)
# Player props (flat list, ParlayAPI-extension)
rows = client.props(
"baseball_mlb",
markets=["player_strikeouts"],
bookmakers=["draftkings", "pinnacle", "fanduel", "bet365"],
)
for r in rows[:10]:
print(r["bookmaker"], r["player_name"], r["line"], r["over_price"], "/", r["under_price"])
# Devig a paired market on the client side, no network
fair_over, fair_under = ParlayAPI.devig(over_price=-110, under_price=-110)
# fair_over == 0.5, fair_under == 0.5
# Compute a +EV edge in percentage points
edge = ParlayAPI.edge(book_price=+120, fair_prob=0.55)
# +9.5pp positive expected value
WebSocket streaming (Business+)
pip install parlay-api[ws]
import asyncio, json, websockets
from parlay_api import ParlayAPI
client = ParlayAPI(api_key="YOUR_KEY")
async def run():
async with websockets.connect(client.websocket_url("baseball_mlb")) as ws:
while True:
msg = json.loads(await ws.recv())
print(msg.get("type"), len(msg.get("data") or []))
asyncio.run(run())
You'll receive an initial snapshot frame (type=odds_update with the
full current state) followed by push frames whenever any book
updates a price. Optional event-level filter:
await ws.send(json.dumps({
"type": "subscribe",
"event_id": "2026-04-29_New_York_Yankees_Boston_Red_Sox",
}))
Examples
The examples/ folder ships three runnable scripts:
ev_scanner.py— pulls a sport's player props, devigs the sharpest book in each market as the fair-price baseline, and prints every other book's posted line that exceeds a +3pp edge threshold. This is the basic shape of a +EV scanner.arb_finder.py— scans h2h game lines across every book in the response for any pair where combined implied probability is under 100%. Computes the optimal stake split for a given bankroll. Risk-free profit when an arb exists.websocket_stream.py— subscribes to the live odds WebSocket for a sport and prints diff frames as they arrive.
Run any of them after setting PARLAY_API_KEY:
export PARLAY_API_KEY=your_key
cd examples
python ev_scanner.py baseball_mlb player_strikeouts --edge 3.0
python arb_finder.py basketball_nba --bankroll 1000
python websocket_stream.py icehockey_nhl
Devig math
The SDK includes the four standard devig methods so you don't have to reimplement them:
ParlayAPI.american_to_implied(-110) # 0.5238
ParlayAPI.american_to_decimal(-110) # 1.9091
ParlayAPI.decimal_to_american(2.10) # 110
ParlayAPI.implied_to_american(0.55) # -122
# Devig with three different methods:
ParlayAPI.devig(-110, -110, method="multiplicative") # standard
ParlayAPI.devig(-110, -110, method="additive") # less accurate
ParlayAPI.devig(-1500, +700, method="power") # better for skewed
Error handling
from parlay_api import (
ParlayAPI,
ParlayAPIError,
InvalidAPIKeyError,
CreditLimitExceededError,
RateLimitedError,
TierGatedError,
)
client = ParlayAPI(api_key="...")
try:
events = client.odds("basketball_nba")
except CreditLimitExceededError:
print("hit monthly credit cap")
except RateLimitedError:
print("slow down, retry in 1s")
except TierGatedError:
print("upgrade required for this feature")
except InvalidAPIKeyError:
print("API key revoked or wrong")
except ParlayAPIError as e:
print("other error:", e)
After every successful call the SDK exposes the credit headers via
client.last_quota:
client.odds("basketball_nba")
print(client.last_quota.requests_remaining) # int
Pricing
| Tier | $/month | Credits/month | Rate limit | WebSocket |
|---|---|---|---|---|
| Free | $0 | 1,000 | 10 req/s | no |
| Starter | $5 | 20,000 | 30 req/s | no |
| Pro | $20 | 100,000 | 60 req/s | no |
| Business | $40 | 1,000,000 | 100 req/s | yes |
| Enterprise | $100 | 5,000,000 | 200 req/s | yes |
| Scale | $200 | 50,000,000 | 500 req/s | yes |
Sign up at parlay-api.com.
License
MIT. See LICENSE.
Bugs and support
github.com/JacobiusMakes/parlay-api-python/issues or email peakpotentialmediaventures@gmail.com.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file parlay_api-0.1.0.tar.gz.
File metadata
- Download URL: parlay_api-0.1.0.tar.gz
- Upload date:
- Size: 12.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d2904987b45ff6f4526f11fcde3a07c30994d410c62cc5d5d5ff1f652af0efe2
|
|
| MD5 |
1bdb3fab9f5b9ebc0e63822229c291c4
|
|
| BLAKE2b-256 |
b2e95b0e8d7bfef2cdf4971d24e0cb26e0d9bd963eb50ff3f07fd4066bcdf88d
|
File details
Details for the file parlay_api-0.1.0-py3-none-any.whl.
File metadata
- Download URL: parlay_api-0.1.0-py3-none-any.whl
- Upload date:
- Size: 10.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
23343a08c02a3de0fa14988160c2e51b67fc34f7a1f551acebc6bc4eb098dac0
|
|
| MD5 |
fb5c03aa08f6b63c586d9cd986941831
|
|
| BLAKE2b-256 |
90ee236bd5d40420a1612d00cb0e0112b7a771ef308a08f2c37992a61b67850a
|