---
title: "Slate-wide events feed — every match's events in one call, oldest first, cursor by id (PRO)"
method: GET
path: "/events"
---

# Slate-wide events feed — every match's events in one call, oldest first, cursor by id (PRO)

`GET /events`

## Request

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

Added 2026-09-13. The rows of GET /matches/{matchId}/events for EVERY match in one request, so a poller watching the whole live slate spends one request per tick rather than one per match. `after_id` returns rows with id greater than the one passed, ascending, and `meta.next_cursor` names the last id served (null on a short page = caught up); `since` (UTC instant) is the first-call lower bound; with neither the newest page is served, still ascending. `type` narrows to a comma-separated list of event types or the family name `stoppages` (stoppage_*, pause_*, medical_timeout_*, trainer_called*, toilet_break_*). Rows carry `id` and `match_id` next to the per-match fields. Measured 2026-09-13: a scorer-stated stoppage reaches the feed a median 8 s (p90 13 s) after the scorer's own instant; the WebSocket `stoppages` signal pushes the same row as it is written.

## Query parameters

- `type` string
- `after_id` integer
- `since` string, date-time
- `limit` integer

## Response `200`

Events across the slate, ascending id

- object
  - `data` SlateEvent[]
    - `type` 'break' | 'set_won' | 'game_won' | 'momentum_run' | 'stoppage_start' | 'stoppage_end' | 'pause_start' | 'pause_end' | 'medical_timeout_start' | 'medical_timeout_end' | 'trainer_called' | 'trainer_called_end' | 'toilet_break_start' | 'toilet_break_end': The stoppage family (added 2026-09-12). `medical_timeout_start/end`, `trainer_called/_end` and `toilet_break_start/end` are stated by the match scorer or chair umpire, with `player` = the player concerned. Coverage (2026-09-13): WTA, WTA 125, Challenger and UTR singles — WTA and WTA 125 from the umpire console in two layers: the match state within ~20 s (`trainer_called`, `toilet_break_*`, `stoppage_*`, player null) and the console's event feed, published by the tour with a variable delay (measured 2026-09-13: about one minute to an hour behind play), which adds `medical_timeout_start/end` with the player and exact instants; Challenger and UTR from the scorer timeline (22 of 70 finished Challenger matches, median 8 s). ITF World Tennis Tour singles from the court's live-scoring state (the state, not the player: `player` is null on ITF rows; first medical timeout observed and published 2026-09-13). ATP main tour: a public live-score service's match stage is watched for its medical-timeout and interruption stages — present in its vocabulary, not yet observed on a tennis match, so ATP rows are mapped, not yet proven (`player` null, `at` = our observation instant). Not doubles. `stoppage_start/end` is a whole-match stop (`reason` weather | other when stated, unknown when only a bare suspension flag reached us). `pause_start/end` is an interruption of play measured from our own point clocks (`basis: inferred`), never labelled medical.
    - `player` 1 | 2 | null, nullable
    - `timestamp` string, date-time, nullable
    - `at` string, date-time, nullable: Stoppage family — the UTC instant the stoppage happened (for a pause, its last score change).
    - `detected_at` string, date-time, nullable: Stoppage family — when we recorded it.
    - `basis` 'observed' | 'inferred' | 'null', nullable: Stoppage family — observed (a source stated it) or inferred (measured from our clocks).
    - `reason` string, nullable: Stoppage family — medical_timeout | unspecified | no_treatment | taping | changeover_treatment | evaluating | failed | toilet_break | weather | other | resumed | unknown.
    - `position` 'point' | 'changeover' | 'setbreak' | 'null', nullable: pause rows only — where the last point left the match, which sets the silence threshold.
    - `score` object, nullable: Stoppage family — sets, games, points, server at the moment of the stoppage.
    - `duration_seconds` integer, nullable: end rows only.
    - `id` integer: The event's id; the `after_id` cursor.
    - `match_id` integer
  - `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

- `400`: bad_type, bad_after_id or bad_since
- `401`: Missing, unknown, or disabled credentials
- `403`: Your tier doesn't unlock this endpoint
- `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)
