# Tennis Score API
> Tennis scoring maths as an API, computed locally and deterministically — the game, set and match logic a scoring app, umpire tool or tennis league runs on. The game endpoint plays a game from a sequence of who won each point and returns the proper tennis score: points run 0, 15, 30, 40 and then game, but at 40-40 it is Deuce and a player must lead by two — Advantage, then game — so a,a,a,a is 40-0 and a win, while three-all is Deuce; a tiebreak flag scores to seven by two instead (and keeps going at 7-7). The set endpoint reads a set from the games each player has won: a set is taken at six games with a two-game lead, 6-6 triggers a tiebreak that ends it 7-6, and 7-5 wins if a player pulls ahead first. The match endpoint settles the match from the sets won — best-of-three is decided by two sets, best-of-five by three — and tells you the winner the moment it is reached. Everything is computed locally and deterministically, so it is instant and private. Ideal for tennis, racket-sport, scoring, umpiring and league app developers, scoreboard and live-scoring tools, and club software. Pure local computation — no key, no third-party service, instant. Scoring logic, not analytics. Live, nothing stored. 3 compute endpoints.

## Authentication
All requests require your oanor API key in the `x-oanor-key` header. Get one at https://www.oanor.com/developer/keys.

```bash
curl -H "x-oanor-key: oanor_live_…" "https://api.oanor.com/tennis-api/..."
```

## Pricing
- **Free** (Free) — 6,980 calls/Mo, 2 req/s
- **Starter** ($4/Mo) — 55,600 calls/Mo, 6 req/s
- **Pro** ($12/Mo) — 228,300 calls/Mo, 15 req/s
- **Mega** ($38/Mo) — 1,333,000 calls/Mo, 40 req/s

## Endpoints

### Tennis

#### `GET /v1/game` — Score a game

**Parameters:**
- `points` (query, required, string) — Sequence of 'a'/'b' point winners Example: `a,a,b,a,a`
- `tiebreak` (query, optional, string) — Score as a tiebreak (true/false) Example: `false`
- `tiebreak_target` (query, optional, string) — Tiebreak target points (default 7) Example: `7`

**Example:**
```bash
curl -H "x-oanor-key: $KEY" \
  "https://api.oanor.com/tennis-api/v1/game?points=a%2Ca%2Cb%2Ca%2Ca&tiebreak=false&tiebreak_target=7"
```

**Response:**
```json
{
    "data": {
        "note": "Standard game: points run 0, 15, 30, 40, then game — but at 40-40 it is Deuce and a player must lead by two (Advantage, then game). Points after the game is won are ignored.",
        "score": "40-15",
        "inputs": {
            "points": [
                "a",
                "a",
                "b",
                "a",
                "a"
            ],
            "tiebreak": false
        },
        "winner": "a",
        "complete": true,
        "points_a": 4,
        "points_b": 1
    },
    "meta": {
        "timestamp": "2026-06-06T07:13:58.211Z",
        "request_id": "45792aa8-b1c1-4d57-9182-ced4f99b1c64"
    },
    "status": "ok",
    "message": "Game score",
    "success": true
}
```

#### `GET /v1/match` — Match status

**Parameters:**
- `sets_a` (query, required, string) — Sets won by A Example: `2`
- `sets_b` (query, required, string) — Sets won by B Example: `1`
- `best_of` (query, optional, string) — Best of 3 or 5 (default 3) Example: `3`

**Example:**
```bash
curl -H "x-oanor-key: $KEY" \
  "https://api.oanor.com/tennis-api/v1/match?sets_a=2&sets_b=1&best_of=3"
```

**Response:**
```json
{
    "data": {
        "note": "Best-of-3 is won with 2 sets, best-of-5 with 3. The match ends as soon as a player reaches that many sets.",
        "score": "2-1",
        "inputs": {
            "sets_a": 2,
            "sets_b": 1,
            "best_of": 3
        },
        "winner": "a",
        "complete": true,
        "sets_to_win": 2
    },
    "meta": {
        "timestamp": "2026-06-06T07:13:58.315Z",
        "request_id": "5581dfed-a130-47e0-9ac6-1d56f1542131"
    },
    "status": "ok",
    "message": "Match status",
    "success": true
}
```

#### `GET /v1/set` — Set status

**Parameters:**
- `games_a` (query, required, string) — Games won by A Example: `6`
- `games_b` (query, required, string) — Games won by B Example: `4`
- `tiebreak_at` (query, optional, string) — Games count that triggers a tiebreak (default 6) Example: `6`

**Example:**
```bash
curl -H "x-oanor-key: $KEY" \
  "https://api.oanor.com/tennis-api/v1/set?games_a=6&games_b=4&tiebreak_at=6"
```

**Response:**
```json
{
    "data": {
        "note": "A set is won at 6 games with a two-game lead; at 6-6 a tiebreak decides it (final score 7-6), or 7-5 if a player pulls ahead first. Some formats use an advantage set with no tiebreak.",
        "score": "6-4",
        "inputs": {
            "games_a": 6,
            "games_b": 4,
            "tiebreak_at": 6
        },
        "status": "set won",
        "winner": "a",
        "needs_tiebreak": false
    },
    "meta": {
        "timestamp": "2026-06-06T07:13:58.414Z",
        "request_id": "ff528ba1-41b6-4916-b5f4-955fbe7f6c3a"
    },
    "status": "ok",
    "message": "Set status",
    "success": true
}
```

### Meta

#### `GET /v1/meta` — Spec

**Example:**
```bash
curl -H "x-oanor-key: $KEY" \
  "https://api.oanor.com/tennis-api/v1/meta"
```

**Response:**
```json
{
    "data": {
        "notes": "Players are 'a' and 'b'. Game points: 0/15/30/40, deuce and advantage at 40-40. Set: 6 games, win by 2, tiebreak at 6-6. Match: best-of-3 or best-of-5. Scoring only — not shot or rally analytics.",
        "service": "tennis-api",
        "endpoints": {
            "GET /v1/set": "Set status and winner from the games each player has won.",
            "GET /v1/game": "Score a game (or tiebreak) from a sequence of 'a'/'b' points.",
            "GET /v1/meta": "This document.",
            "GET /v1/match": "Match status and winner from the sets each player has won."
        },
        "description": "Tennis scoring: a game from a point sequence (deuce/advantage/tiebreak), a set from its games, and a match from its sets."
    },
    "meta": {
        "timestamp": "2026-06-06T07:13:58.501Z",
        "request_id": "bf9d8be5-886f-46a8-9339-478198668fb0"
    },
    "status": "ok",
    "message": "Meta",
    "success": true
}
```


---
Marketplace page: https://www.oanor.com/api/tennis-api
OpenAPI spec: https://www.oanor.com/api/tennis-api/openapi.json
