langchain-livetennis
Official LangChain integration for the Live Tennis API.
Give an agent real tennis: live scores, match detail, player profiles, upcoming fixtures, head-to-head records, rankings, in-play statistics and a 1968–2022 results archive — across ATP, WTA, Challenger, ITF and juniors.
Installation
pip install -U langchain-livetennis
Credentials
Get a free key (100 requests/day) at https://livetennisapi.com/subscribe/free, then:
export LIVETENNISAPI_KEY="twjp_..."
A request without a key is answered with HTTP 401 {"error": "unauthorized"}.
Quickstart
from langchain_livetennis import LiveTennisToolkit
toolkit = LiveTennisToolkit()
tools = toolkit.get_tools()
matches = tools[0].invoke({"status": "live", "tour": "atp", "limit": 5})
print(matches)
Or use a single tool on its own:
from langchain_livetennis import LiveTennisScoreTool
LiveTennisScoreTool().invoke({"match_id": 18953})
In an agent
from langchain.agents import create_agent
from langchain_livetennis import LiveTennisToolkit
agent = create_agent(model="claude-sonnet-4-6", tools=LiveTennisToolkit().get_tools())
agent.invoke(
{"messages": [{"role": "user", "content": "Who is leading the live ATP matches right now?"}]}
)
Tools
| Tool | Endpoint | Plan | What it returns |
|---|---|---|---|
live_tennis_matches |
GET /matches |
FREE (completed: BASIC+) |
Matches by status (live, upcoming, completed), filterable by tour, player ids, country and date range, with the latest score |
live_tennis_match |
GET /matches/{id} |
FREE | One match in full: players, tournament, surface, round, status, score |
live_tennis_match_score |
GET /matches/{id}/score |
FREE | Just the score — sets, games, points, server, tiebreak flag |
live_tennis_player_search |
GET /players |
FREE | Players matching a name, ranked players first |
live_tennis_player |
GET /players/{id} |
FREE | One player's bio, ranking and cached statistics |
live_tennis_fixtures |
GET /fixtures |
FREE | Upcoming scheduled fixtures, earliest first, filterable by tour |
live_tennis_h2h |
GET /h2h |
BASIC+ | Head-to-head between two players, 1968 to now, with per-meeting outcomes |
live_tennis_archive_matches |
GET /history/archive/matches |
BASIC+ | 1968–2022 results: score, round, seeds, ranks at the time, era serve stats |
live_tennis_archive_players |
GET /history/archive/players |
BASIC+ | Archive player bios: hand, birth date, country, height, career-high rank |
live_tennis_archive_career |
GET /history/archive/career |
BASIC+ | One player's whole archive career: W-L by surface/level/year, titles, serve sums |
live_tennis_rankings |
GET /rankings (listing) |
PRO+ | The full published table in rank order for one system (ATP/WTA/ITF circuits) |
live_tennis_player_rankings |
GET /rankings (per-player) |
ULTRA | Point-in-time ranking records per player and system, as of any date |
live_tennis_match_statistics |
GET /matches/{id}/statistics |
ULTRA | In-play statistics: aces, serve split, hold/break %, break points, freshness per family |
live_tennis_charting_player |
GET /charting/players |
ULTRA | Career shot-level charting profile (Match Charting Project) |
live_tennis_charting_match |
GET /charting/matches/{id} |
ULTRA | One charted match, every stat family for both players, per set |
Every tool returns the API's JSON payload as a string, so nothing is lost on the
way to the model. Tools above the key's plan still bind and appear in
get_tools(); calling one surfaces the API's 403 as a ToolException naming
the plan that unlocks it, so an agent can explain the gate instead of retrying
it.
tour accepts atp, wta, challenger, itf or juniors. Each value covers
that tour's singles and doubles draws, and juniors covers the boys' and girls'
Grand Slam draws. An unrecognised value is a 400 rather than a silent
pass-through, so a caller never receives a tour it did not ask for.
Plans & quotas
| Plan | Per minute | Per day | Price |
|---|---|---|---|
| FREE | 30 | 100 | $0 |
| BASIC | 60 | 1,000 | $9.99/mo |
| PRO | 300 | 10,000 | $29.99/mo |
| ULTRA | 600 | 500,000 | $99.99/mo |
On a free key (100/day), poll no faster than every 15 minutes; for an always-on
dashboard, BASIC is recommended. Every response carries X-RateLimit-Limit,
X-RateLimit-Remaining and X-RateLimit-Reset headers, and 429s a
Retry-After.
Authentication
The API accepts, in order of preference:
Authorization: Bearer twjp_...— preferred for direct HTTP callsX-API-Key: twjp_...— what this package sends?token=twjp_...— for header-less contexts (e.g. WebSockets)
This package reads the key from the LIVETENNISAPI_KEY environment variable,
or takes it explicitly via LiveTennisToolkit(api_key=...).
Errors
| Exception | When |
|---|---|
LiveTennisAuthError |
401 — key missing, unknown, or disabled |
LiveTennisUpgradeRequired |
403 — valid key, plan too low |
LiveTennisNotFound |
404 — no such match or player, or no data yet |
LiveTennisBadRequest |
400 — a query parameter was rejected |
LiveTennisRateLimited |
429 — carries .retry_after in seconds; a daily-cap 429 also carries .resets_at, the exact ISO-8601 instant the day quota resets |
LiveTennisAbuseThrottled |
429 abuse_throttled — a 24-hour block for chronic over-cap use; carries .retry_at_epoch. Fix the retry loop, don't retry |
LiveTennisServerError |
5xx, or the API was never reached |
All inherit from LiveTennisAPIError (LiveTennisAbuseThrottled also from
LiveTennisRateLimited). Inside a tool call they are re-raised as LangChain's
ToolException, so an agent can be configured to recover:
from langchain_livetennis import LiveTennisMatchesTool
tool = LiveTennisMatchesTool(handle_tool_error=True)
Requests retry automatically on per-minute 429s and 5xx only, honouring
Retry-After with exponential backoff and jitter. A 401 or 403 is never
retried — a bad key or an unentitled plan cannot start working, and retrying
only burns the rate limit. Nor are a daily-cap 429 or the abuse block —
waiting a few seconds cannot fix either, so they surface immediately with
.resets_at / .retry_at_epoch.
Configuration
from langchain_livetennis import LiveTennisClient, LiveTennisToolkit
toolkit = LiveTennisToolkit(api_key="...")
# Or share a fully configured client across every tool:
client = LiveTennisClient(api_key="...", timeout=10.0, max_retries=3)
toolkit = LiveTennisToolkit(client=client)
Development
uv sync --all-groups
uv run pytest tests/unit_tests
uv run ruff check .
uv run ruff format --check .
uv run mypy langchain_livetennis
The unit suite runs entirely against an in-process fake API
(tests/mock_api.py) — no key and no network access required. The integration
tests under tests/integration_tests/ skip themselves unless
LIVETENNISAPI_KEY is set.
Links
- Live Tennis API documentation
- Get a free API key
- Discord
- GitHub org
- Official Python client — the standalone SDK, for use outside LangChain
- OpenAPI specification
Affiliate program
Know developers who need tennis data? The affiliate program pays 51% recurring commission for the life of every referred subscription — 30-day cookie, and the people you refer get 10% off.
License
MIT
Metadata
Release files for langchain-livetennis 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| langchain_livetennis-0.2.0.tar.gz | 28.8 kB | With provenance | Details for langchain_livetennis-0.2.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| langchain_livetennis-0.2.0-py3-none-any.whl | Python 3 | none | any | Details for langchain_livetennis-0.2.0-py3-none-any.whl |
Total release size: 51.3 kB
Release files / langchain_livetennis-0.2.0.tar.gz
| Download URL | langchain_livetennis-0.2.0.tar.gz |
|---|---|
| Size | 28.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
638adcdf09c9bfe714a4aa44180962f1ae4def83303c9077cfbe8747d469491a
|
|
BLAKE2b-256 checksum How to use checksums |
c0e598674c8573c34a7d141515240906b02ffaa64d62990bb456fffcac3a91a7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 18, 2026.
Transparency logRelease files / langchain_livetennis-0.2.0-py3-none-any.whl
| Download URL | langchain_livetennis-0.2.0-py3-none-any.whl |
|---|---|
| Size | 22.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
631bc8418474cc001a4393adcc1839dd02c1e50fea5e4883e776128e4e5c5e8c
|
|
BLAKE2b-256 checksum How to use checksums |
b5659af5ef2feb6948005732253abfe71917a8201958ea0ff88c62ae59127d64
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 18, 2026.
Transparency logSecurity for langchain-livetennis 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for langchain_livetennis-0.2.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 18, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.