# Bowling Score API
> Ten-pin bowling maths as an API, computed locally and deterministically — the scoring, handicap and average numbers a bowler, league or scoring app runs on. The score endpoint plays a full game from a comma list of the pins knocked down on each roll and applies the real rules: a strike scores 10 plus your next two rolls, a spare 10 plus the next one, an open frame just the pins, with the 10th frame’s bonus rolls handled — so twelve strikes is a perfect 300, twenty 9-then-miss frames are 90, and all spares with a 5 bonus is 150, returned frame by frame with the running total. The handicap endpoint levels a league: handicap per game = ⌊(basis − average) × percent⌋, never below zero, so a 150 average on the common 90 %-of-220 setup earns 63 pins a game and 189 over a three-game series. The average endpoint divides total pins by games (dropping the fraction, as leagues do), rolls in a new series to update it, and works out the pins you need over the next games to reach a target average. Everything is computed locally and deterministically, so it is instant and private. Ideal for bowling-league, scoring, sports and recreation app developers, scorekeeping and handicap tools, and centre-management software. Pure local computation — no key, no third-party service, instant. 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/bowling-api/..."
```

## Pricing
- **Free** (Free) — 7,450 calls/Mo, 2 req/s
- **Starter** ($4/Mo) — 55,400 calls/Mo, 6 req/s
- **Pro** ($12/Mo) — 227,800 calls/Mo, 15 req/s
- **Mega** ($37/Mo) — 1,331,000 calls/Mo, 40 req/s

## Endpoints

### Bowling

#### `GET /v1/average` — Average + target

**Parameters:**
- `total_pins` (query, required, string) — Total pins Example: `450`
- `games` (query, required, string) — Games bowled Example: `3`
- `add_pins` (query, optional, string) — Pins to add (new average)
- `add_games` (query, optional, string) — Games to add
- `target_average` (query, optional, string) — Target average
- `over_games` (query, optional, string) — Games to reach target over (default 1)

**Example:**
```bash
curl -H "x-oanor-key: $KEY" \
  "https://api.oanor.com/bowling-api/v1/average?total_pins=450&games=3"
```

**Response:**
```json
{
    "data": {
        "note": "Average = total pins ÷ games (leagues drop the fraction). To reach a target average over the next games, you need target × (total games) − current pins. Bowl above your average to raise it.",
        "inputs": {
            "games": 3,
            "total_pins": 450
        },
        "average": 150,
        "average_floor": 150
    },
    "meta": {
        "timestamp": "2026-06-06T07:13:58.618Z",
        "request_id": "4b168d38-4450-461d-b0c8-352b2265be0c"
    },
    "status": "ok",
    "message": "Average",
    "success": true
}
```

#### `GET /v1/handicap` — League handicap

**Parameters:**
- `average` (query, required, string) — Bowler average Example: `150`
- `basis` (query, optional, string) — Handicap basis (default 220) Example: `220`
- `percent` (query, optional, string) — Handicap percent (default 90) Example: `90`
- `games` (query, optional, string) — Games in the series (default 1) Example: `3`

**Example:**
```bash
curl -H "x-oanor-key: $KEY" \
  "https://api.oanor.com/bowling-api/v1/handicap?average=150&basis=220&percent=90&games=3"
```

**Response:**
```json
{
    "data": {
        "note": "Handicap per game = ⌊(basis − average) × percent⌋, never below 0. A common league setup is 90 % of 220. Handicap levels the field: a lower average earns more pins. Series handicap is the per-game figure times the number of games.",
        "inputs": {
            "basis": 220,
            "games": 3,
            "average": 150,
            "percent": 90
        },
        "handicap_series": 189,
        "handicap_per_game": 63
    },
    "meta": {
        "timestamp": "2026-06-06T07:13:58.710Z",
        "request_id": "59c95dbb-0489-4a96-90b2-7ef6299b583b"
    },
    "status": "ok",
    "message": "Handicap",
    "success": true
}
```

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

**Parameters:**
- `rolls` (query, required, string) — Comma list of pins per roll Example: `10,10,10,10,10,10,10,10,10,10,10,10`

**Example:**
```bash
curl -H "x-oanor-key: $KEY" \
  "https://api.oanor.com/bowling-api/v1/score?rolls=10%2C10%2C10%2C10%2C10%2C10%2C10%2C10%2C10%2C10%2C10%2C10"
```

**Response:**
```json
{
    "data": {
        "note": "Standard ten-pin scoring: a strike scores 10 plus your next two rolls, a spare 10 plus the next one, an open frame the pins. The 10th frame allows bonus rolls. A perfect game (twelve strikes) is 300.",
        "score": 300,
        "frames": [
            {
                "mark": "X",
                "frame": 1,
                "cumulative": 30
            },
            {
                "mark": "X",
                "frame": 2,
                "cumulative": 60
            },
            {
                "mark": "X",
                "frame": 3,
                "cumulative": 90
            },
            {
                "mark": "X",
                "frame": 4,
                "cumulative": 120
            },
            {
                "mark": "X",
                "frame": 5,
                "cumulative": 150
            },
            {
                "mark": "X",
                "frame": 6,
                "cumulative": 180
            },
            {
                "mark": "X",
                "frame": 7,
                "cumulative": 210
            },
            {
                "mark": "X",
                "frame": 8,
                "cumulative": 240
            },
            {
                "mark": "X",
                "frame": 9,
                "cumulative": 270
            },
            {
                "mark": "X",
                "frame": 10,
                "cumulative": 300
            }
        ],
        "inputs
…(truncated, see openapi.json for full schema)
```

### Meta

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

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

**Response:**
```json
{
    "data": {
        "notes": "Pins per roll are 0–10; a perfect game is twelve strikes (300). Handicap = ⌊(basis − average) × percent⌋ ≥ 0. Average drops the fraction in most leagues. Pin scoring, not lane physics.",
        "service": "bowling-api",
        "endpoints": {
            "GET /v1/meta": "This document.",
            "GET /v1/score": "Score a game from a comma list of pins per roll.",
            "GET /v1/average": "Average, new average after more games, and pins needed for a target.",
            "GET /v1/handicap": "League handicap per game and per series from an average."
        },
        "description": "Ten-pin bowling maths: full game scoring with strike/spare bonuses, league handicap, and average / target-average."
    },
    "meta": {
        "timestamp": "2026-06-06T07:13:58.883Z",
        "request_id": "eed7b1bc-c279-4764-9a38-14987e2e0bdf"
    },
    "status": "ok",
    "message": "Meta",
    "success": true
}
```


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