Official Python SDK 0.3.0
The typed synchronous client covers the six Starter routes, parses quotas and ETags, and validates bulk IDs before any call.
Install
pip install foresportia
Version 0.3.0, Python >=3.9. The client is synchronous and typed.
The six Starter routes, typed
| Method | Route |
|---|---|
list_leagues() | GET /v1/leagues |
list_league_matches(code, …) | GET /v1/leagues/{code}/matches |
get_match(match_id) | GET /v1/matches/{match_id} |
get_matches_bulk(match_ids) | POST /v1/matches/bulk |
list_today_matches() | GET /v1/matches/today |
list_today_picks(limit=20) | GET /v1/picks/today |
from foresportia import ForesportiaClient
with ForesportiaClient.from_env() as client:
leagues = client.list_leagues()
bulk = client.get_matches_bulk([match_id_1, match_id_2])
for league in leagues.data:
print(league.code, league.matches_available)
for error in bulk.data.errors:
print("failed:", error.match_id, error.code)
Read verified historical summaries
Use include="past" on list_league_matches(). Historical rows retain
the probabilities and pick published before kickoff, then expose the verified final result.
from foresportia import ForesportiaClient
with ForesportiaClient.from_env() as client:
response = client.list_league_matches(
"SUE",
include="past",
days=7,
limit=50,
)
for match in response.data:
print(
match.kickoff,
match.home_team,
match.away_team,
match.result_score,
match.pick,
)
Automatic pagination
SDK 0.3.0 also provides iter_league_matches(), which follows
next_cursor lazily while keeping the same filters.
from foresportia import ForesportiaClient
with ForesportiaClient.from_env() as client:
for match in client.iter_league_matches(
"SUE",
include="past",
days=7,
limit=50,
):
print(match.kickoff, match.result_score, match.pick)
For a full worked example that charts upcoming matches, markets, and verified history with
list_league_history(), follow the
football dashboard tutorial.
Responses, quotas, and ETags
Each typed method returns an ApiResponse exposing data (typed result),
payload (raw dict), etag, quota (parsed headers), and
status_code. Passing etag= sends If-None-Match; a
304 is a normal response (response.not_modified), never a generic error.
In SDK 0.3.0, league-match responses also expose next_cursor,
history_available_from, and history_entitlement_days as typed properties.
Additional counters, including historical_matches_available, remain available in
response.payload.
first = client.get_match(match_id)
second = client.get_match(match_id, etag=first.etag)
detail = first.data if second.not_modified else second.data
Errors and bulk validation
Errors are typed: authentication (401), authorization (403), not found (404), validation (400/422),
rate limit (429), concurrency limit, server (5xx), and transport. Bulk IDs are validated client-side
(1 to 100 unique fsm:v1:* IDs) before any network call, and
per-ID failures are reported without hiding successful results.
Retries are disabled by default: a request that times out client-side may already have been counted
against your quota, so each retry can consume an extra unit. Enable them explicitly with
max_retries=2.