propline 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- propline-0.1.0/LICENSE +21 -0
- propline-0.1.0/PKG-INFO +155 -0
- propline-0.1.0/README.md +128 -0
- propline-0.1.0/propline/__init__.py +6 -0
- propline-0.1.0/propline/client.py +201 -0
- propline-0.1.0/propline.egg-info/PKG-INFO +155 -0
- propline-0.1.0/propline.egg-info/SOURCES.txt +10 -0
- propline-0.1.0/propline.egg-info/dependency_links.txt +1 -0
- propline-0.1.0/propline.egg-info/requires.txt +1 -0
- propline-0.1.0/propline.egg-info/top_level.txt +1 -0
- propline-0.1.0/pyproject.toml +34 -0
- propline-0.1.0/setup.cfg +4 -0
propline-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 PropLine
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
propline-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: propline
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python SDK for the PropLine player props betting odds API
|
|
5
|
+
Author-email: PropLine <support@prop-line.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://prop-line.com
|
|
8
|
+
Project-URL: Documentation, https://prop-line.com/docs
|
|
9
|
+
Project-URL: Repository, https://github.com/andyt338/propline-python
|
|
10
|
+
Project-URL: API Reference, https://api.prop-line.com/docs
|
|
11
|
+
Keywords: sports,betting,odds,player-props,api,sportsbook,mlb,nba,nhl,nfl
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
22
|
+
Requires-Python: >=3.8
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Requires-Dist: httpx>=0.24.0
|
|
26
|
+
Dynamic: license-file
|
|
27
|
+
|
|
28
|
+
# PropLine Python SDK
|
|
29
|
+
|
|
30
|
+
Official Python client for the [PropLine](https://prop-line.com) player props API — real-time betting odds for MLB, NBA, NHL, and NFL.
|
|
31
|
+
|
|
32
|
+
## Installation
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
pip install propline
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Quick Start
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
from propline import PropLine
|
|
42
|
+
|
|
43
|
+
client = PropLine("your_api_key")
|
|
44
|
+
|
|
45
|
+
# List available sports
|
|
46
|
+
sports = client.get_sports()
|
|
47
|
+
# [{"key": "baseball_mlb", "title": "MLB", "active": True}, ...]
|
|
48
|
+
|
|
49
|
+
# Get today's NBA games
|
|
50
|
+
events = client.get_events("basketball_nba")
|
|
51
|
+
for event in events:
|
|
52
|
+
print(f"{event['away_team']} @ {event['home_team']}")
|
|
53
|
+
|
|
54
|
+
# Get player props for a game
|
|
55
|
+
odds = client.get_odds("basketball_nba", event_id=events[0]["id"],
|
|
56
|
+
markets=["player_points", "player_rebounds", "player_assists"])
|
|
57
|
+
|
|
58
|
+
for bookmaker in odds["bookmakers"]:
|
|
59
|
+
for market in bookmaker["markets"]:
|
|
60
|
+
for outcome in market["outcomes"]:
|
|
61
|
+
print(f"{outcome['description']} {outcome['name']} "
|
|
62
|
+
f"{outcome['point']} @ {outcome['price']}")
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Get Your API Key
|
|
66
|
+
|
|
67
|
+
1. Go to [prop-line.com](https://prop-line.com)
|
|
68
|
+
2. Enter your email
|
|
69
|
+
3. Get your API key instantly — **500 requests/day, no credit card required**
|
|
70
|
+
|
|
71
|
+
## Available Sports
|
|
72
|
+
|
|
73
|
+
| Key | Sport |
|
|
74
|
+
|-----|-------|
|
|
75
|
+
| `baseball_mlb` | MLB |
|
|
76
|
+
| `basketball_nba` | NBA |
|
|
77
|
+
| `hockey_nhl` | NHL |
|
|
78
|
+
| `football_nfl` | NFL |
|
|
79
|
+
|
|
80
|
+
## Available Markets
|
|
81
|
+
|
|
82
|
+
### MLB
|
|
83
|
+
`pitcher_strikeouts`, `pitcher_earned_runs`, `pitcher_hits_allowed`, `batter_hits`, `batter_home_runs`, `batter_rbis`, `batter_total_bases`, `batter_stolen_bases`, `batter_walks`, `batter_singles`, `batter_doubles`, `batter_runs`
|
|
84
|
+
|
|
85
|
+
### NBA
|
|
86
|
+
`player_points`, `player_rebounds`, `player_assists`, `player_threes`, `player_points_rebounds_assists`, `player_double_double`
|
|
87
|
+
|
|
88
|
+
### NHL
|
|
89
|
+
`player_goals`, `player_shots_on_goal`, `goalie_saves`, `player_blocked_shots`
|
|
90
|
+
|
|
91
|
+
### Game Lines (all sports)
|
|
92
|
+
`h2h`, `spreads`, `totals`
|
|
93
|
+
|
|
94
|
+
## Examples
|
|
95
|
+
|
|
96
|
+
### Get MLB pitcher strikeout props
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
from propline import PropLine
|
|
100
|
+
|
|
101
|
+
client = PropLine("your_api_key")
|
|
102
|
+
|
|
103
|
+
events = client.get_events("baseball_mlb")
|
|
104
|
+
for event in events:
|
|
105
|
+
odds = client.get_odds("baseball_mlb", event_id=event["id"],
|
|
106
|
+
markets=["pitcher_strikeouts"])
|
|
107
|
+
|
|
108
|
+
print(f"\n{event['away_team']} @ {event['home_team']}")
|
|
109
|
+
for bk in odds["bookmakers"]:
|
|
110
|
+
for mkt in bk["markets"]:
|
|
111
|
+
for o in mkt["outcomes"]:
|
|
112
|
+
if o["point"]:
|
|
113
|
+
print(f" {o['description']} {o['name']} {o['point']}: {o['price']}")
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Get historical line movement (Pro only)
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
history = client.get_odds_history("baseball_mlb", event_id=16,
|
|
120
|
+
markets=["pitcher_strikeouts"])
|
|
121
|
+
|
|
122
|
+
for market in history["markets"]:
|
|
123
|
+
for outcome in market["outcomes"]:
|
|
124
|
+
print(f"\n{outcome['description']}:")
|
|
125
|
+
for snap in outcome["snapshots"]:
|
|
126
|
+
print(f" {snap['recorded_at']}: {snap['price']} @ {snap['point']}")
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Error Handling
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
from propline import PropLine, AuthError, RateLimitError, PropLineError
|
|
133
|
+
|
|
134
|
+
client = PropLine("your_api_key")
|
|
135
|
+
|
|
136
|
+
try:
|
|
137
|
+
odds = client.get_odds("baseball_mlb", event_id=1)
|
|
138
|
+
except AuthError:
|
|
139
|
+
print("Invalid API key")
|
|
140
|
+
except RateLimitError:
|
|
141
|
+
print("Daily limit exceeded — upgrade at prop-line.com/#pricing")
|
|
142
|
+
except PropLineError as e:
|
|
143
|
+
print(f"API error: {e.status_code} — {e.detail}")
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Links
|
|
147
|
+
|
|
148
|
+
- **Website**: [prop-line.com](https://prop-line.com)
|
|
149
|
+
- **API Docs**: [prop-line.com/docs](https://prop-line.com/docs)
|
|
150
|
+
- **Dashboard**: [prop-line.com/dashboard](https://prop-line.com/dashboard)
|
|
151
|
+
- **API Reference**: [api.prop-line.com/docs](https://api.prop-line.com/docs)
|
|
152
|
+
|
|
153
|
+
## License
|
|
154
|
+
|
|
155
|
+
MIT
|
propline-0.1.0/README.md
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# PropLine Python SDK
|
|
2
|
+
|
|
3
|
+
Official Python client for the [PropLine](https://prop-line.com) player props API — real-time betting odds for MLB, NBA, NHL, and NFL.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install propline
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
from propline import PropLine
|
|
15
|
+
|
|
16
|
+
client = PropLine("your_api_key")
|
|
17
|
+
|
|
18
|
+
# List available sports
|
|
19
|
+
sports = client.get_sports()
|
|
20
|
+
# [{"key": "baseball_mlb", "title": "MLB", "active": True}, ...]
|
|
21
|
+
|
|
22
|
+
# Get today's NBA games
|
|
23
|
+
events = client.get_events("basketball_nba")
|
|
24
|
+
for event in events:
|
|
25
|
+
print(f"{event['away_team']} @ {event['home_team']}")
|
|
26
|
+
|
|
27
|
+
# Get player props for a game
|
|
28
|
+
odds = client.get_odds("basketball_nba", event_id=events[0]["id"],
|
|
29
|
+
markets=["player_points", "player_rebounds", "player_assists"])
|
|
30
|
+
|
|
31
|
+
for bookmaker in odds["bookmakers"]:
|
|
32
|
+
for market in bookmaker["markets"]:
|
|
33
|
+
for outcome in market["outcomes"]:
|
|
34
|
+
print(f"{outcome['description']} {outcome['name']} "
|
|
35
|
+
f"{outcome['point']} @ {outcome['price']}")
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Get Your API Key
|
|
39
|
+
|
|
40
|
+
1. Go to [prop-line.com](https://prop-line.com)
|
|
41
|
+
2. Enter your email
|
|
42
|
+
3. Get your API key instantly — **500 requests/day, no credit card required**
|
|
43
|
+
|
|
44
|
+
## Available Sports
|
|
45
|
+
|
|
46
|
+
| Key | Sport |
|
|
47
|
+
|-----|-------|
|
|
48
|
+
| `baseball_mlb` | MLB |
|
|
49
|
+
| `basketball_nba` | NBA |
|
|
50
|
+
| `hockey_nhl` | NHL |
|
|
51
|
+
| `football_nfl` | NFL |
|
|
52
|
+
|
|
53
|
+
## Available Markets
|
|
54
|
+
|
|
55
|
+
### MLB
|
|
56
|
+
`pitcher_strikeouts`, `pitcher_earned_runs`, `pitcher_hits_allowed`, `batter_hits`, `batter_home_runs`, `batter_rbis`, `batter_total_bases`, `batter_stolen_bases`, `batter_walks`, `batter_singles`, `batter_doubles`, `batter_runs`
|
|
57
|
+
|
|
58
|
+
### NBA
|
|
59
|
+
`player_points`, `player_rebounds`, `player_assists`, `player_threes`, `player_points_rebounds_assists`, `player_double_double`
|
|
60
|
+
|
|
61
|
+
### NHL
|
|
62
|
+
`player_goals`, `player_shots_on_goal`, `goalie_saves`, `player_blocked_shots`
|
|
63
|
+
|
|
64
|
+
### Game Lines (all sports)
|
|
65
|
+
`h2h`, `spreads`, `totals`
|
|
66
|
+
|
|
67
|
+
## Examples
|
|
68
|
+
|
|
69
|
+
### Get MLB pitcher strikeout props
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
from propline import PropLine
|
|
73
|
+
|
|
74
|
+
client = PropLine("your_api_key")
|
|
75
|
+
|
|
76
|
+
events = client.get_events("baseball_mlb")
|
|
77
|
+
for event in events:
|
|
78
|
+
odds = client.get_odds("baseball_mlb", event_id=event["id"],
|
|
79
|
+
markets=["pitcher_strikeouts"])
|
|
80
|
+
|
|
81
|
+
print(f"\n{event['away_team']} @ {event['home_team']}")
|
|
82
|
+
for bk in odds["bookmakers"]:
|
|
83
|
+
for mkt in bk["markets"]:
|
|
84
|
+
for o in mkt["outcomes"]:
|
|
85
|
+
if o["point"]:
|
|
86
|
+
print(f" {o['description']} {o['name']} {o['point']}: {o['price']}")
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Get historical line movement (Pro only)
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
history = client.get_odds_history("baseball_mlb", event_id=16,
|
|
93
|
+
markets=["pitcher_strikeouts"])
|
|
94
|
+
|
|
95
|
+
for market in history["markets"]:
|
|
96
|
+
for outcome in market["outcomes"]:
|
|
97
|
+
print(f"\n{outcome['description']}:")
|
|
98
|
+
for snap in outcome["snapshots"]:
|
|
99
|
+
print(f" {snap['recorded_at']}: {snap['price']} @ {snap['point']}")
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Error Handling
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
from propline import PropLine, AuthError, RateLimitError, PropLineError
|
|
106
|
+
|
|
107
|
+
client = PropLine("your_api_key")
|
|
108
|
+
|
|
109
|
+
try:
|
|
110
|
+
odds = client.get_odds("baseball_mlb", event_id=1)
|
|
111
|
+
except AuthError:
|
|
112
|
+
print("Invalid API key")
|
|
113
|
+
except RateLimitError:
|
|
114
|
+
print("Daily limit exceeded — upgrade at prop-line.com/#pricing")
|
|
115
|
+
except PropLineError as e:
|
|
116
|
+
print(f"API error: {e.status_code} — {e.detail}")
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Links
|
|
120
|
+
|
|
121
|
+
- **Website**: [prop-line.com](https://prop-line.com)
|
|
122
|
+
- **API Docs**: [prop-line.com/docs](https://prop-line.com/docs)
|
|
123
|
+
- **Dashboard**: [prop-line.com/dashboard](https://prop-line.com/dashboard)
|
|
124
|
+
- **API Reference**: [api.prop-line.com/docs](https://api.prop-line.com/docs)
|
|
125
|
+
|
|
126
|
+
## License
|
|
127
|
+
|
|
128
|
+
MIT
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
"""
|
|
2
|
+
PropLine API client.
|
|
3
|
+
|
|
4
|
+
Usage:
|
|
5
|
+
from propline import PropLine
|
|
6
|
+
|
|
7
|
+
client = PropLine("your_api_key")
|
|
8
|
+
|
|
9
|
+
# List sports
|
|
10
|
+
sports = client.get_sports()
|
|
11
|
+
|
|
12
|
+
# Get today's NBA games
|
|
13
|
+
events = client.get_events("basketball_nba")
|
|
14
|
+
|
|
15
|
+
# Get player props for a game
|
|
16
|
+
odds = client.get_odds("basketball_nba", event_id=21, markets=["player_points", "player_rebounds"])
|
|
17
|
+
|
|
18
|
+
# Get historical line movement (Pro only)
|
|
19
|
+
history = client.get_odds_history("baseball_mlb", event_id=16, markets=["pitcher_strikeouts"])
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
24
|
+
from typing import Any
|
|
25
|
+
|
|
26
|
+
import httpx
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class PropLineError(Exception):
|
|
30
|
+
"""Base exception for PropLine API errors."""
|
|
31
|
+
|
|
32
|
+
def __init__(self, status_code: int, detail: str):
|
|
33
|
+
self.status_code = status_code
|
|
34
|
+
self.detail = detail
|
|
35
|
+
super().__init__(f"[{status_code}] {detail}")
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class RateLimitError(PropLineError):
|
|
39
|
+
"""Raised when the daily request limit is exceeded."""
|
|
40
|
+
pass
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class AuthError(PropLineError):
|
|
44
|
+
"""Raised when the API key is missing or invalid."""
|
|
45
|
+
pass
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class PropLine:
|
|
49
|
+
"""
|
|
50
|
+
Client for the PropLine player props API.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
api_key: Your PropLine API key. Get one free at https://prop-line.com
|
|
54
|
+
base_url: API base URL (default: https://api.prop-line.com/v1)
|
|
55
|
+
timeout: Request timeout in seconds (default: 15)
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
def __init__(
|
|
59
|
+
self,
|
|
60
|
+
api_key: str,
|
|
61
|
+
base_url: str = "https://api.prop-line.com/v1",
|
|
62
|
+
timeout: float = 15.0,
|
|
63
|
+
):
|
|
64
|
+
self.api_key = api_key
|
|
65
|
+
self.base_url = base_url.rstrip("/")
|
|
66
|
+
self._client = httpx.Client(
|
|
67
|
+
headers={"X-API-Key": api_key},
|
|
68
|
+
timeout=httpx.Timeout(timeout),
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
def _request(self, method: str, path: str, **kwargs) -> Any:
|
|
72
|
+
resp = self._client.request(method, f"{self.base_url}{path}", **kwargs)
|
|
73
|
+
|
|
74
|
+
if resp.status_code == 401:
|
|
75
|
+
raise AuthError(401, resp.json().get("detail", "Invalid API key"))
|
|
76
|
+
elif resp.status_code == 429:
|
|
77
|
+
raise RateLimitError(429, resp.json().get("detail", "Rate limit exceeded"))
|
|
78
|
+
elif resp.status_code >= 400:
|
|
79
|
+
detail = resp.json().get("detail", resp.text) if resp.text else str(resp.status_code)
|
|
80
|
+
raise PropLineError(resp.status_code, detail)
|
|
81
|
+
|
|
82
|
+
return resp.json()
|
|
83
|
+
|
|
84
|
+
def get_sports(self) -> list[dict]:
|
|
85
|
+
"""
|
|
86
|
+
List all available sports.
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
List of sport objects with keys: key, title, active
|
|
90
|
+
|
|
91
|
+
Example:
|
|
92
|
+
>>> client.get_sports()
|
|
93
|
+
[{"key": "baseball_mlb", "title": "MLB", "active": True}, ...]
|
|
94
|
+
"""
|
|
95
|
+
return self._request("GET", "/sports")
|
|
96
|
+
|
|
97
|
+
def get_events(self, sport: str) -> list[dict]:
|
|
98
|
+
"""
|
|
99
|
+
List upcoming events for a sport.
|
|
100
|
+
|
|
101
|
+
Args:
|
|
102
|
+
sport: Sport key (e.g. "baseball_mlb", "basketball_nba", "hockey_nhl", "football_nfl")
|
|
103
|
+
|
|
104
|
+
Returns:
|
|
105
|
+
List of event objects with keys: id, sport_key, home_team, away_team, commence_time
|
|
106
|
+
|
|
107
|
+
Example:
|
|
108
|
+
>>> client.get_events("basketball_nba")
|
|
109
|
+
[{"id": "21", "home_team": "Cleveland Cavaliers", "away_team": "Indiana Pacers", ...}, ...]
|
|
110
|
+
"""
|
|
111
|
+
return self._request("GET", f"/sports/{sport}/events")
|
|
112
|
+
|
|
113
|
+
def get_odds(
|
|
114
|
+
self,
|
|
115
|
+
sport: str,
|
|
116
|
+
event_id: int | str | None = None,
|
|
117
|
+
markets: list[str] | None = None,
|
|
118
|
+
) -> dict | list[dict]:
|
|
119
|
+
"""
|
|
120
|
+
Get current odds. If event_id is provided, returns odds for that event
|
|
121
|
+
(including player props). Otherwise returns bulk odds for all events.
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
sport: Sport key (e.g. "baseball_mlb")
|
|
125
|
+
event_id: Optional event ID for single-event odds with player props
|
|
126
|
+
markets: List of market keys to filter by. Defaults vary by endpoint.
|
|
127
|
+
Common markets:
|
|
128
|
+
- Game lines: "h2h", "spreads", "totals"
|
|
129
|
+
- MLB props: "pitcher_strikeouts", "batter_hits", "batter_home_runs",
|
|
130
|
+
"batter_rbis", "batter_total_bases"
|
|
131
|
+
- NBA props: "player_points", "player_rebounds", "player_assists",
|
|
132
|
+
"player_threes"
|
|
133
|
+
- NHL props: "player_goals", "player_shots_on_goal", "goalie_saves"
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
Single event odds dict (if event_id provided) or list of event odds dicts.
|
|
137
|
+
|
|
138
|
+
Example:
|
|
139
|
+
>>> odds = client.get_odds("basketball_nba", event_id=21,
|
|
140
|
+
... markets=["player_points", "player_rebounds"])
|
|
141
|
+
>>> for bookmaker in odds["bookmakers"]:
|
|
142
|
+
... for market in bookmaker["markets"]:
|
|
143
|
+
... for outcome in market["outcomes"]:
|
|
144
|
+
... print(f"{outcome['description']} {outcome['name']} {outcome['point']}")
|
|
145
|
+
"""
|
|
146
|
+
params = {}
|
|
147
|
+
if markets:
|
|
148
|
+
params["markets"] = ",".join(markets)
|
|
149
|
+
|
|
150
|
+
if event_id is not None:
|
|
151
|
+
return self._request("GET", f"/sports/{sport}/events/{event_id}/odds", params=params)
|
|
152
|
+
else:
|
|
153
|
+
return self._request("GET", f"/sports/{sport}/odds", params=params)
|
|
154
|
+
|
|
155
|
+
def get_odds_history(
|
|
156
|
+
self,
|
|
157
|
+
sport: str,
|
|
158
|
+
event_id: int | str,
|
|
159
|
+
markets: list[str] | None = None,
|
|
160
|
+
) -> dict:
|
|
161
|
+
"""
|
|
162
|
+
Get historical odds movement for an event (Pro tier only).
|
|
163
|
+
|
|
164
|
+
Args:
|
|
165
|
+
sport: Sport key
|
|
166
|
+
event_id: Event ID
|
|
167
|
+
markets: List of market keys to filter by
|
|
168
|
+
|
|
169
|
+
Returns:
|
|
170
|
+
Event dict with markets containing timestamped snapshots showing
|
|
171
|
+
how odds moved over time.
|
|
172
|
+
|
|
173
|
+
Raises:
|
|
174
|
+
PropLineError: 403 if not on Pro tier
|
|
175
|
+
|
|
176
|
+
Example:
|
|
177
|
+
>>> history = client.get_odds_history("baseball_mlb", event_id=16,
|
|
178
|
+
... markets=["pitcher_strikeouts"])
|
|
179
|
+
>>> for market in history["markets"]:
|
|
180
|
+
... for outcome in market["outcomes"]:
|
|
181
|
+
... print(f"{outcome['description']}: {len(outcome['snapshots'])} changes")
|
|
182
|
+
... for snap in outcome["snapshots"]:
|
|
183
|
+
... print(f" {snap['recorded_at']}: {snap['price']} @ {snap['point']}")
|
|
184
|
+
"""
|
|
185
|
+
params = {}
|
|
186
|
+
if markets:
|
|
187
|
+
params["markets"] = ",".join(markets)
|
|
188
|
+
|
|
189
|
+
return self._request(
|
|
190
|
+
"GET", f"/sports/{sport}/events/{event_id}/odds/history", params=params
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
def close(self):
|
|
194
|
+
"""Close the HTTP client."""
|
|
195
|
+
self._client.close()
|
|
196
|
+
|
|
197
|
+
def __enter__(self):
|
|
198
|
+
return self
|
|
199
|
+
|
|
200
|
+
def __exit__(self, *args):
|
|
201
|
+
self.close()
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: propline
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python SDK for the PropLine player props betting odds API
|
|
5
|
+
Author-email: PropLine <support@prop-line.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://prop-line.com
|
|
8
|
+
Project-URL: Documentation, https://prop-line.com/docs
|
|
9
|
+
Project-URL: Repository, https://github.com/andyt338/propline-python
|
|
10
|
+
Project-URL: API Reference, https://api.prop-line.com/docs
|
|
11
|
+
Keywords: sports,betting,odds,player-props,api,sportsbook,mlb,nba,nhl,nfl
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
22
|
+
Requires-Python: >=3.8
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Requires-Dist: httpx>=0.24.0
|
|
26
|
+
Dynamic: license-file
|
|
27
|
+
|
|
28
|
+
# PropLine Python SDK
|
|
29
|
+
|
|
30
|
+
Official Python client for the [PropLine](https://prop-line.com) player props API — real-time betting odds for MLB, NBA, NHL, and NFL.
|
|
31
|
+
|
|
32
|
+
## Installation
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
pip install propline
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Quick Start
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
from propline import PropLine
|
|
42
|
+
|
|
43
|
+
client = PropLine("your_api_key")
|
|
44
|
+
|
|
45
|
+
# List available sports
|
|
46
|
+
sports = client.get_sports()
|
|
47
|
+
# [{"key": "baseball_mlb", "title": "MLB", "active": True}, ...]
|
|
48
|
+
|
|
49
|
+
# Get today's NBA games
|
|
50
|
+
events = client.get_events("basketball_nba")
|
|
51
|
+
for event in events:
|
|
52
|
+
print(f"{event['away_team']} @ {event['home_team']}")
|
|
53
|
+
|
|
54
|
+
# Get player props for a game
|
|
55
|
+
odds = client.get_odds("basketball_nba", event_id=events[0]["id"],
|
|
56
|
+
markets=["player_points", "player_rebounds", "player_assists"])
|
|
57
|
+
|
|
58
|
+
for bookmaker in odds["bookmakers"]:
|
|
59
|
+
for market in bookmaker["markets"]:
|
|
60
|
+
for outcome in market["outcomes"]:
|
|
61
|
+
print(f"{outcome['description']} {outcome['name']} "
|
|
62
|
+
f"{outcome['point']} @ {outcome['price']}")
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Get Your API Key
|
|
66
|
+
|
|
67
|
+
1. Go to [prop-line.com](https://prop-line.com)
|
|
68
|
+
2. Enter your email
|
|
69
|
+
3. Get your API key instantly — **500 requests/day, no credit card required**
|
|
70
|
+
|
|
71
|
+
## Available Sports
|
|
72
|
+
|
|
73
|
+
| Key | Sport |
|
|
74
|
+
|-----|-------|
|
|
75
|
+
| `baseball_mlb` | MLB |
|
|
76
|
+
| `basketball_nba` | NBA |
|
|
77
|
+
| `hockey_nhl` | NHL |
|
|
78
|
+
| `football_nfl` | NFL |
|
|
79
|
+
|
|
80
|
+
## Available Markets
|
|
81
|
+
|
|
82
|
+
### MLB
|
|
83
|
+
`pitcher_strikeouts`, `pitcher_earned_runs`, `pitcher_hits_allowed`, `batter_hits`, `batter_home_runs`, `batter_rbis`, `batter_total_bases`, `batter_stolen_bases`, `batter_walks`, `batter_singles`, `batter_doubles`, `batter_runs`
|
|
84
|
+
|
|
85
|
+
### NBA
|
|
86
|
+
`player_points`, `player_rebounds`, `player_assists`, `player_threes`, `player_points_rebounds_assists`, `player_double_double`
|
|
87
|
+
|
|
88
|
+
### NHL
|
|
89
|
+
`player_goals`, `player_shots_on_goal`, `goalie_saves`, `player_blocked_shots`
|
|
90
|
+
|
|
91
|
+
### Game Lines (all sports)
|
|
92
|
+
`h2h`, `spreads`, `totals`
|
|
93
|
+
|
|
94
|
+
## Examples
|
|
95
|
+
|
|
96
|
+
### Get MLB pitcher strikeout props
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
from propline import PropLine
|
|
100
|
+
|
|
101
|
+
client = PropLine("your_api_key")
|
|
102
|
+
|
|
103
|
+
events = client.get_events("baseball_mlb")
|
|
104
|
+
for event in events:
|
|
105
|
+
odds = client.get_odds("baseball_mlb", event_id=event["id"],
|
|
106
|
+
markets=["pitcher_strikeouts"])
|
|
107
|
+
|
|
108
|
+
print(f"\n{event['away_team']} @ {event['home_team']}")
|
|
109
|
+
for bk in odds["bookmakers"]:
|
|
110
|
+
for mkt in bk["markets"]:
|
|
111
|
+
for o in mkt["outcomes"]:
|
|
112
|
+
if o["point"]:
|
|
113
|
+
print(f" {o['description']} {o['name']} {o['point']}: {o['price']}")
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Get historical line movement (Pro only)
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
history = client.get_odds_history("baseball_mlb", event_id=16,
|
|
120
|
+
markets=["pitcher_strikeouts"])
|
|
121
|
+
|
|
122
|
+
for market in history["markets"]:
|
|
123
|
+
for outcome in market["outcomes"]:
|
|
124
|
+
print(f"\n{outcome['description']}:")
|
|
125
|
+
for snap in outcome["snapshots"]:
|
|
126
|
+
print(f" {snap['recorded_at']}: {snap['price']} @ {snap['point']}")
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Error Handling
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
from propline import PropLine, AuthError, RateLimitError, PropLineError
|
|
133
|
+
|
|
134
|
+
client = PropLine("your_api_key")
|
|
135
|
+
|
|
136
|
+
try:
|
|
137
|
+
odds = client.get_odds("baseball_mlb", event_id=1)
|
|
138
|
+
except AuthError:
|
|
139
|
+
print("Invalid API key")
|
|
140
|
+
except RateLimitError:
|
|
141
|
+
print("Daily limit exceeded — upgrade at prop-line.com/#pricing")
|
|
142
|
+
except PropLineError as e:
|
|
143
|
+
print(f"API error: {e.status_code} — {e.detail}")
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Links
|
|
147
|
+
|
|
148
|
+
- **Website**: [prop-line.com](https://prop-line.com)
|
|
149
|
+
- **API Docs**: [prop-line.com/docs](https://prop-line.com/docs)
|
|
150
|
+
- **Dashboard**: [prop-line.com/dashboard](https://prop-line.com/dashboard)
|
|
151
|
+
- **API Reference**: [api.prop-line.com/docs](https://api.prop-line.com/docs)
|
|
152
|
+
|
|
153
|
+
## License
|
|
154
|
+
|
|
155
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
httpx>=0.24.0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
propline
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "propline"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Python SDK for the PropLine player props betting odds API"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = {text = "MIT"}
|
|
11
|
+
requires-python = ">=3.8"
|
|
12
|
+
authors = [{name = "PropLine", email = "support@prop-line.com"}]
|
|
13
|
+
keywords = ["sports", "betting", "odds", "player-props", "api", "sportsbook", "mlb", "nba", "nhl", "nfl"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 4 - Beta",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Programming Language :: Python :: 3.8",
|
|
20
|
+
"Programming Language :: Python :: 3.9",
|
|
21
|
+
"Programming Language :: Python :: 3.10",
|
|
22
|
+
"Programming Language :: Python :: 3.11",
|
|
23
|
+
"Programming Language :: Python :: 3.12",
|
|
24
|
+
"Topic :: Software Development :: Libraries",
|
|
25
|
+
]
|
|
26
|
+
dependencies = [
|
|
27
|
+
"httpx>=0.24.0",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
[project.urls]
|
|
31
|
+
Homepage = "https://prop-line.com"
|
|
32
|
+
Documentation = "https://prop-line.com/docs"
|
|
33
|
+
Repository = "https://github.com/andyt338/propline-python"
|
|
34
|
+
"API Reference" = "https://api.prop-line.com/docs"
|
propline-0.1.0/setup.cfg
ADDED