Live Tennis API DocsGet a free key
Explore the documentation

Live Tennis API · docs · guide

Live Tennis API client libraries

Which client libraries does the Live Tennis API have? There are official clients for Python, JavaScript and TypeScript, Go, PHP, .NET, Dart, R and Swift. Seven more packages build on them, among them an MCP server and an export command. The tables list the install command, the latest version and the coverage of each.

Versions read from each registry on . Coverage read from the source of each published version.

Which client library should I use?

Pick the row for your language. Every package calls the same REST API with the same key. The version is the newest release on the registry named under each install command. These client libraries are the official SDKs for the API.

Every official client library and tool, with its install command and version
LibraryLatest versionMinimum runtimeInstall and packageLanguageLicenceSource
Python client1.8.0Python 3.9pip install livetennisapi
livetennisapi on PyPI
PythonMITGitHub
JavaScript and TypeScript client1.10.2Node 18npm install livetennisapi
livetennisapi on npm
JavaScript, TypeScriptMITGitHub
Go client1.2.1Go 1.25go get github.com/livetennisapi/livetennisapi-go
github.com/livetennisapi/livetennisapi-go on Go modules
GoMITGitHub
PHP client1.1.1PHP 8.1composer require livetennisapi/livetennisapi
livetennisapi/livetennisapi on Packagist
PHPMITGitHub
.NET client1.2.1.NET Standard 2.0 or .NET 8dotnet add package LiveTennisApi
LiveTennisApi on NuGet
C#MITGitHub
Dart and Flutter client1.2.1Dart 3.5dart pub add livetennisapi
livetennisapi on pub.dev
DartMITGitHub
Swift client1.1.1Swift 5.9.package(url: "https://github.com/livetennisapi/livetennisapi-swift.git", from: "1.1.1")
livetennisapi-swift on Git tag
SwiftMITGitHub
R client0.2.0R 4.1install.packages("livetennisapi", repos = c("https://livetennisapi.r-universe.dev", "https://cloud.r-project.org"))
livetennisapi on R-universe
RMITGitHub
MCP server1.6.5Node 20npx -y livetennisapi-mcp
livetennisapi-mcp on npm
TypeScriptMITGitHub
Vercel AI SDK tools1.3.0Node 22npm install livetennisapi-ai
livetennisapi-ai on npm
TypeScriptMITGitHub
Export command0.1.0Python 3.9pip install livetennisapi-export
livetennisapi-export on PyPI
PythonMITGitHub
Laravel package1.1.0PHP 8.2composer require livetennisapi/livetennisapi-laravel
livetennisapi/livetennisapi-laravel on Packagist
PHPMITGitHub
Haystack integration0.2.0Python 3.10pip install livetennisapi-haystack
livetennisapi-haystack on PyPI
PythonMITGitHub
LangChain integration0.2.0Python 3.10pip install -U langchain-livetennis
langchain-livetennis on PyPI
PythonMITGitHub
LlamaIndex tools0.1.0Python 3.10pip install llama-index-tools-livetennisapi
llama-index-tools-livetennisapi on PyPI
PythonMITGitHub

Every package is MIT licensed. Plugins for apps and automation platforms are not in this table. They live in the GitHub organisation.

Which libraries support REST, the live stream, file export and MCP?

Every library reads the REST API. Two open the live stream, one writes files and one is an MCP server.

Which parts of the API each library covers
LibraryRESTLive streamFile exportMCP
Python clientYesYesNoNo
JavaScript and TypeScript clientYesYesNoNo
Go clientYesToken onlyNoNo
PHP clientYesToken onlyNoNo
.NET clientYesToken onlyNoNo
Dart and Flutter clientYesToken onlyNoNo
Swift clientYesToken onlyNoNo
R clientYesNoNoNo
MCP serverYesNoNoYes
Vercel AI SDK toolsYesNoNoNo
Export commandYesNoCSV, JSON Lines, ParquetNo
Laravel packageYesToken onlyNoNo
Haystack integrationYesNoNoNo
LangChain integrationYesNoNoNo
LlamaIndex toolsYesNoNoNo

Live stream says whether the package opens the WebSocket feed for you. The Python and JavaScript clients do. In Python, pip install "livetennisapi[all]" adds the WebSocket feed.

Token only means the client calls GET /ws-token for a push feed token. You open the socket with your own WebSocket library. The push feed and webhooks page describes the frames.

The MCP server also runs hosted at https://mcp.livetennisapi.com/mcp, with nothing to install. The AI SDK guide and the export guide cover those two packages in full.

Which endpoints does each client cover?

The eight language clients do not all reach the same endpoints. Each cell was read from the source of the published version in the first table.

Endpoint groups and the language clients that cover them
EndpointsPythonJSGoPHP.NETDartSwiftRPaths
Matches and live scoresYesYesYesYesYesYesYesYes/matches
/matches/{matchId}
/matches/{matchId}/score
Players, fixtures and tournamentsYesYesYesYesYesYesYesYes/players
/players/{playerId}
/fixtures
/tournaments
/tournaments/{tournamentId}
Player recordNoYesNoNoNoNoNoYes/players/{playerId}/stats
RankingsYesYesYesYesYesYesYesYes/rankings
Results archive and head-to-headYesYesYesYesYesYesYesPart/history/archive/matches
/history/archive/matches/{archiveId}
/history/archive/players
/history/archive/career
/h2h
Completed matches and the point-by-point tapeYesYesYesYesYesYesYesNo/history/matches
/history/matches/{matchId}
History coverage reportYesYesNoNoNoNoNoNo/history/coverage
Match events, statistics and analysisYesYesYesYesYesYesYesNo/matches/{matchId}/events
/matches/{matchId}/statistics
/matches/{matchId}/analysis
Per-point events over RESTYesYesNoNoNoNoNoNo/matches/{matchId}/points
Markets and pricesYesYesYesYesYesYesYesNo/markets
/markets/{matchId}/prices
Rally and charting dataYesYesYesYesYesYesYesNo/rally/matches
/rally/matches/{rallyMatchId}
/history/matches/{matchId}/rally
/charting/players
/charting/matches/{chartingMatchId}
History packagesYesYesYesYesYesYesYesNo/history/packages
/history/packages/{period}
WebhooksNoNoYesYesYesYesYesNoPOST /webhooks
/webhooks
DELETE /webhooks/{webhookId}
Push feed tokenYesYesYesYesYesYesYesNo/ws-token
Usage and quotaYesNoYesYesYesYesYesYes/usage

Part for R means it lists archive results, players, careers and head-to-head records. It has no call for a single archive result.

An endpoint with no method in your client is still one HTTP request away. The reference lists every path. The errors page says when to retry.

What is the smallest working call in each language?

Each example lists live matches. Every call needs an API key, and a free key is enough for these. The free plan has 100 requests a day.

Python

pip install livetennisapi
from livetennisapi import LiveTennisAPI

with LiveTennisAPI(api_key="twjp_…") as client:   # or set LIVETENNISAPI_KEY
    for match in client.list_matches(status="live"):
        print(match.tournament, match.p1.name, "vs", match.p2.name, match.score.sets)

The client reads LIVETENNISAPI_KEY when you pass no key. The spec lets score be null, so check it before you read sets. The example is from the README of version 1.8.0.

JavaScript and TypeScript

npm install livetennisapi
import { LiveTennisAPI } from 'livetennisapi';

const client = new LiveTennisAPI({ apiKey: 'twjp_…' });   // or $LIVETENNISAPI_KEY

const { data } = await client.listMatches({ status: 'live' });
for (const match of data) {
  console.log(match.tournament, match.players?.p1?.name, 'vs', match.players?.p2?.name);
}

The package has no runtime dependencies and ships its own types. The example is from the README of version 1.10.2.

Go

go get github.com/livetennisapi/livetennisapi-go
package main

import (
	"context"
	"fmt"
	"log"
	"os"

	"github.com/livetennisapi/livetennisapi-go"
)

func main() {
	client := livetennisapi.New(os.Getenv("LIVETENNISAPI_KEY"))

	page, err := client.ListMatches(context.Background(), livetennisapi.ListMatchesParams{
		Status:     livetennisapi.StatusLive,
		ListParams: livetennisapi.ListParams{Limit: 10},
	})
	if err != nil {
		log.Fatal(err)
	}

	for _, match := range page.Data {
		fmt.Printf("%-28s %s vs %s — %s\n",
			match.Tournament,
			match.Players.P1.Name,
			match.Players.P2.Name,
			match.Score, // nil-safe: prints "-" before a match starts
		)
	}
}

The module uses the standard library only. The example is from the README of version 1.2.1.

PHP

composer require livetennisapi/livetennisapi
composer require guzzlehttp/guzzle
use LiveTennisApi\LiveTennisApi;

$client = new LiveTennisApi('twjp_…');      // or set LIVETENNISAPI_KEY

foreach ($client->listMatches('live') as $match) {
    echo $match->tournament, ' [', $match->tour, ']: ',
         $match->p1()?->name, ' vs ', $match->p2()?->name, "\n";

    // score is nullable — an upcoming match has none yet
    if ($match->score !== null) {
        // points are STRINGS ("40", "AD"); games are player-major per-set lists
        echo '  ', implode('-', $match->score->points), "\n";
    }
}

The client needs a PSR-18 HTTP client and PSR-17 factories. The second line installs Guzzle, which provides both. The example is from the README of version 1.1.1.

.NET

dotnet add package LiveTennisApi
using LiveTennisApi;
using LiveTennisApi.Models;

using var client = new LiveTennisApiClient("twjp_your_key");

var live = await client.ListMatchesAsync(MatchStatus.Live);
foreach (var m in live.Data)
{
    Console.WriteLine($"{m.Tournament}: {m.Players?.P1?.Name} vs {m.Players?.P2?.Name}");
}

The package targets .NET Standard 2.0 and .NET 8. The example is from the README of version 1.2.1.

Dart and Flutter

dart pub add livetennisapi
import 'package:livetennisapi/livetennisapi.dart';

Future<void> main() async {
  final client = LiveTennisApi(apiKey: 'twjp_your_key');
  try {
    final page = await client.listMatches(status: MatchStatus.live);
    for (final match in page.data) {
      final s = match.score;
      final (g1, g2) = s?.gamesForSet(0) ?? (null, null);
      print('${match.tournament} [${match.tour}]: '
          '${match.p1?.name} vs ${match.p2?.name} '
          '(${g1 ?? '-'}-${g2 ?? '-'}, serving: ${s?.server ?? '—'})');
    }
  } on UpgradeRequiredException catch (e) {
    print('Needs the ${e.requiredTier} tier');
  } on RateLimitedException catch (e) {
    print('Slow down; retry after ${e.retryAfter}s');
  } finally {
    client.close();
  }
}

The package is pure Dart and depends only on package:http. The example is from the README of version 1.2.1.

Swift

.package(url: "https://github.com/livetennisapi/livetennisapi-swift.git", from: "1.1.1")
import LiveTennisApi

let client = LiveTennisApiClient(apiKey: "twjp_your_key_here")

let live = try await client.listMatches(status: .live, tour: .atp)
for match in live.data {
    let p1 = match.players?.p1?.name ?? "?"
    let p2 = match.players?.p2?.name ?? "?"
    print("\(match.tournament): \(p1) vs \(p2) — \(match.score?.description ?? "-")")
}

Add the first line to the dependencies in Package.swift. The package supports macOS 12, iOS 15, tvOS 15, watchOS 8 and Linux. The example is from the README of version 1.1.1.

R

install.packages("livetennisapi", repos = c("https://livetennisapi.r-universe.dev", "https://cloud.r-project.org"))
library(livetennisapi)

live <- live_matches(tour = "atp")
if (nrow(live) > 0) {
  print(live[, c("id", "tournament", "players.p1.name", "players.p2.name")])
  match_score(live$id[1])
}

search_players("sinner")
list_fixtures(tour = "wta", limit = 20)

List functions return a tibble. Put the key in ~/.Renviron as LIVETENNISAPI_KEY. The example is from the README of version 0.2.0.

How do I check that a version here is current?

The versions were read from the registries on . The registry link under each install command always shows the newest release.

The docs repository has a script, scripts/check_client_versions.py. It reads every registry again and names each row that is behind.