Skip to main content

livetennisapi-haystack

Haystack 2.x integration for the Live Tennis API: live scores, matches, players, head-to-heads, the 1968-2022 results archive, rankings and in-play statistics across ATP, WTA, Challenger, ITF and juniors — as Haystack Documents for RAG and agent pipelines.

ci PyPI License: MIT

Every component returns Documents whose content is a clean human-readable summary and whose meta carries the structured fields — directly usable in prompts, document stores and agent tools. Built on the official livetennisapi Python client (retries, error mapping, typed models) — no hand-rolled HTTP.

Installation

pip install livetennisapi-haystack

Grab a free API key at https://livetennisapi.com/subscribe/free and export it — the components read LIVETENNISAPI_KEY by default and never accept a plain-string key:

export LIVETENNISAPI_KEY="twjp_your_key_here"

Quickstart

from livetennisapi_haystack import LiveTennisMatchFetcher

fetcher = LiveTennisMatchFetcher()          # key from LIVETENNISAPI_KEY
result = fetcher.run(status="live", limit=5)
for doc in result["documents"]:
    print(doc.content)
    # e.g. "Carlos Alcaraz (ESP, #2) vs Jannik Sinner (ITA, #1) — match at Wimbledon,
    #       grass court, round QF, best of 5. Live now. Score: sets 1-1, games 6-4, 3-6,
    #       2-1, points 30-15. Carlos Alcaraz (ESP, #2) is serving."

In a pipeline (runnable with only LIVETENNISAPI_KEY)

from haystack import Pipeline

from livetennisapi_haystack import LiveTennisMatchFetcher, LiveTennisPlayerSearch

pipe = Pipeline()
pipe.add_component("matches", LiveTennisMatchFetcher(limit=5))
pipe.add_component("players", LiveTennisPlayerSearch(limit=3))

result = pipe.run({"matches": {"status": "live"}, "players": {"query": "alcaraz"}})
for doc in result["matches"]["documents"] + result["players"]["documents"]:
    print("-", doc.content)

RAG over live scores

from haystack import Pipeline
from haystack.components.builders.chat_prompt_builder import ChatPromptBuilder
from haystack.components.generators.chat import OpenAIChatGenerator
from haystack.dataclasses import ChatMessage

from livetennisapi_haystack import LiveTennisMatchFetcher

prompt_template = [
    ChatMessage.from_system("You are a tennis commentator."),
    ChatMessage.from_user(
        "Current matches:\n"
        "{% for document in documents %}{{ document.content }}\n{% endfor %}\n"
        "Answer the following question: {{ query }}\nAnswer:"
    ),
]

pipe = Pipeline()
pipe.add_component("matches", LiveTennisMatchFetcher(limit=10))
pipe.add_component("prompt_builder", ChatPromptBuilder(template=prompt_template, required_variables={"query", "documents"}))
pipe.add_component("llm", OpenAIChatGenerator(model="gpt-4o-mini"))
pipe.connect("matches.documents", "prompt_builder.documents")
pipe.connect("prompt_builder.prompt", "llm.messages")

query = "Who is closest to winning right now?"
result = pipe.run({"matches": {"status": "live"}, "prompt_builder": {"query": query}})
print(result["llm"]["replies"][0].text)

A complete runnable script lives at examples/live_demo.py.

Components

Component What it fetches API endpoint(s) Tier
LiveTennisMatchFetcher Live / upcoming / completed matches, one match by id; filters: tour, player, country, from_/to /matches, /matches/{id} FREE (status="completed" listings: BASIC or any History plan)
LiveTennisPlayerSearch Player search by name, ranked players first /players FREE
LiveTennisH2HFetcher Head-to-head between two players — results archive (1968-2022) + current matches (2023-now) in one record /h2h BASIC
LiveTennisArchiveFetcher The results archive: 1,485,752 matches 1968-2022 (mode="matches"), player bios (mode="players"), career aggregates (mode="career") /history/archive/* BASIC
LiveTennisRankingsFetcher A published ranking table (atp, wta, itf_jt, itf_mt, itf_wt), optionally as of a past week /rankings PRO
LiveTennisMatchStatisticsFetcher In-play statistics: aces, double faults, serve split, hold/break %, break points /matches/{id}/statistics ULTRA

All tour-filterable components accept tour values "atp", "wta", "challenger", "itf" and "juniors"; each value covers its singles and doubles draws.

Quotas

Tier Requests/min Requests/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

At 100/day, poll no faster than every ~15 minutes on a free key; for an always-on dashboard, BASIC is the tier to recommend. Full details at https://docs.livetennisapi.com.

Authentication

The components resolve the key through Haystack's Secret (from LIVETENNISAPI_KEY by default) and hand it to the official client, which sends it as an Authorization: Bearer header — the API's preferred scheme (X-API-Key and ?token= also exist for clients that cannot set headers). Serialized pipelines carry only the environment-variable reference, never the key value.

Behavior worth knowing

  • 403 tier wall: when your key is valid but the plan does not unlock an endpoint, the component returns a single readable Document (tagged meta["error"] = "upgrade_required") instead of raising — an agent can tell the user; a RAG pipeline can filter it out. The case you will actually hit: status="completed" listings return 403 on a free key — they need the BASIC tier ($9.99/mo) or any History plan (https://livetennisapi.com/subscribe/upgrade). status="live" / "upcoming" and single-match fetches via match_id (even for a completed match) work on the free tier.
  • 429s: the official client transparently retries the per-minute window (and if it still surfaces, the component fails loud — that is a transient error). The two NON-retryable shapes become readable Documents instead: the daily cap (tagged meta["error"] = "rate_limited", with resets_at — the absolute instant the day quota resets, derived from a local midnight) and the abuse throttle (tagged "abuse_throttled", with retry_at_epoch — a 24-hour block for chronic over-cap clients; fix the retry loop, retrying is what earns it).
  • Ambiguous names: the name-keyed endpoints (/h2h, archive career) refuse a fragment matching more than one player; the component turns that into a Document tagged meta["error"] = "ambiguous_name" carrying the candidate list, so an agent can ask which one was meant.
  • Sparse data is normal: score.server is nullable (between points the feed may not know who serves next — the summary simply omits the serving sentence), doubles teams have no individual rankings, points are strings ("0", "15", "30", "40", "AD"), and archive-era fields (stats before 1991, per-match dates) are honestly None. The components tolerate all of it and render only what exists.
  • Serialization: every component implements to_dict/from_dict; the API key is stored as a Secret environment-variable reference, never as a value, so pipelines serialize safely to YAML. Note that Haystack 3.0 refuses to deserialize third-party components unless their module is allow-listed, so reload pipelines with Pipeline.loads(yaml_str, allowed_modules=["livetennisapi_haystack.match_fetcher", ...]) (or haystack.core.serialization.allow_deserialization_module(...)).
  • Sync only for now: run() — no run_async yet, although the official client has an async twin. Planned.

Development

pip install -e . pytest ruff
pytest                    # unit tests, fully mocked, no network
ruff check src tests examples
sh scripts/truthcheck.sh  # product-facts pin (also runs in CI)
LIVETENNISAPI_KEY=... pytest -m integration   # live tests, needs a key

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

livetennisapi-haystack is distributed under the terms of the MIT license.

Metadata

Release files for livetennisapi-haystack 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for livetennisapi-haystack 0.2.0
File Size Uploaded Provenance
livetennisapi_haystack-0.2.0.tar.gz 37.0 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for livetennisapi-haystack 0.2.0
File Interpreter ABI Platform
livetennisapi_haystack-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 68.3 kB

Release files / livetennisapi_haystack-0.2.0.tar.gz

Download URL livetennisapi_haystack-0.2.0.tar.gz
Size 37.0 kB
Tags Source
SHA-256 checksum
How to use checksums
d85ce0218324007309e8f08e0a5140b67de70a2bda17d2eaf2bd81edbcc6953a
BLAKE2b-256 checksum
How to use checksums
c3aa1858f50ec56a8ef71c625914051b7a57a19ca717fb7f88115a2fd42e7701
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 7, 2026.

Transparency log

Release files / livetennisapi_haystack-0.2.0-py3-none-any.whl

Download URL livetennisapi_haystack-0.2.0-py3-none-any.whl
Size 31.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
97a12671214604147b9eb04d3d0cc57c9a1170942ef10bc10598aa42bfa0a385
BLAKE2b-256 checksum
How to use checksums
0d86f48f6ccfb55ccc43c6ef960b69d8493b09413cf1a3218ab146645017fe07
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 7, 2026.

Transparency log

Security for livetennisapi-haystack 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.

Select from 2 files

Attestation for livetennisapi_haystack-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 7, 2026.

Transparency log

A 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.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page