---
title: "Search players by name (FREE)"
method: GET
path: "/players"
---

# Search players by name (FREE)

`GET /players`

## Request

- Base URL: `https://api.livetennisapi.com/api/public/v1`
- URL: `https://api.livetennisapi.com/api/public/v1/players`
- Auth: one of:
  - HTTP bearer
  - API key in header `X-API-Key`

## Query parameters

- `search` string
- `limit` integer
- `offset` integer

## Response `200`

Players (ranked first; no stats object on the list)

- object
  - `data` Player[]
    - `id` integer
    - `name` string
    - `tour` string, nullable: The record's OWN tour, which is NOT the `tour` filter vocabulary. It is granular (`juniors_boys`, `juniors_girls`, `challenger_men`) where the filter is grouped (`juniors`, `challenger`), and a doubles team reports it UPPERCASE (`ATP`) where an individual reports lowercase (`atp`). Treat it as an opaque string; do not parse it into the filter enum.
    - `country` string, nullable
    - `ranking` integer, nullable: Official singles ranking POSITION (the ordinal: 1, 25, 100) — never points, seed, race, UTR, Elo or a doubles rank. Men from the official ATP table, women from the WTA table, chosen by the player (a Challenger or ITF man who holds an ATP ranking carries it here). Refreshed from the standings ahead of each match the player has with us; a player who has not played recently keeps their last refreshed position. `null` when no ranking is held (doubles teams, most ITF/junior-only players). Always the CURRENT record, even on historical matches — use `/rankings?as_of=` for the rank in force on a date.
    - `ranking_points` integer, nullable: Points on the same official table, refreshed with `ranking`.
    - `ranking_movement` 'up' | 'down' | 'same' | 'null', nullable
    - `hand` 'R' | 'L' | 'null', nullable
    - `backhand` 1 | 2 | null, nullable
    - `birthday` string, date, nullable
    - `is_doubles_team` boolean
    - `data_completeness` object: How much biographical detail is known for this player, so a consumer can distinguish "not in the feed" from "not yet fetched" without probing. Present on every player in a match payload. Lower tours carry far less of it than main tour.
      - `known` integer, nullable: Fields populated, of `of`. NULL on a doubles team, where per-player biography does not apply — distinct from `0`, which means the fields apply and none are known. Do not decode this into a non-nullable integer.
      - `of` integer, nullable: Fields considered. NULL on a doubles team, as for `known`.
      - `missing` string[]: Names of the unpopulated fields, e.g. ["backhand", "hand"].
      - `note` string: Present only when the object is not applicable, explaining why (e.g. a doubles team).
    - `stats` object: Single-player endpoint only
      - `ratings` object, nullable
      - `ratings_as_of` string, date, nullable: The date (UTC) the `ratings` block was last refreshed (added 2026-09-10). The current Elo is refreshed every week from the published rating tables; read this before treating a rating as this week's. Null when there is no rating.
      - `season` unknown
  - `meta` ListMeta
    - `limit` integer
    - `offset` integer
    - `count` integer
    - `total` integer, nullable: Size of the whole filtered set. Null when it cannot be counted cheaply.
    - `has_more` boolean: More results exist beyond this page. Read this rather than comparing count to limit. For a complete enumeration of a filtered set, page `offset` forward by `limit` until this is false; on `completed`/`cancelled` listings `total` is null and this is the only end-of-data signal.
    - `next_cursor` string, nullable: Change-feed only (`?updated_since=` / `?cursor=`). Opaque token to pass back as `?cursor=`. Null means you are caught up — stop paging and switch to polling from `watermark`.
    - `watermark` string, date-time, nullable: Change-feed only. The floor to use on your NEXT poll. Deliberately trails the server clock by 5s so a row committed during this request cannot fall through the gap.

## Other responses

- `401`: Missing, unknown, or disabled credentials
- `429`: Rate limit exceeded (Retry-After header present). Three body shapes, told apart by `error` and `scope`: the per-MINUTE limit (`rate_limited`, with `upgrade_url`, `tier` and `price` naming the next tier up); the per-DAY quota (`rate_limited` with `scope: "day"`, `limit_per_day`, and `resets_at` — the absolute ISO instant the daily window resets); and `abuse_throttled` with `retry_at_epoch` — a 24-hour block applied to clients that keep hammering far past their cap, which a well-behaved retry loop never sees. Fix the loop rather than retrying through it.

---

[API](https://skmtc.dev/livetennisapi/apis/live-tennis-api.md) · [All operations](https://skmtc.dev/livetennisapi/apis/live-tennis-api/llms.txt) · [OpenAPI document](https://skmtc.dev/livetennisapi/apis/live-tennis-api/revisions/7881947e8e43?raw)
