# Mahjong Scoring API
> Riichi (Japanese) mahjong scoring as an API, computed locally and deterministically and exactly — the points a winning hand pays, straight from the scoring table, not a lookup you have to memorise. The score endpoint turns han and fu into the payment using base = fu × 2^(2 + han): a ron pays base × 4 (a dealer ron × 6) rounded up to the nearest 100, while a tsumo splits base × 2 from the dealer and base × 1 from each non-dealer (a dealer tsumo takes base × 2 from all three) — so a non-dealer 3 han 30 fu ron is 3,900, a 4 han 30 fu is 7,700, and a non-dealer mangan ron is 8,000. The limit endpoint classifies a hand: mangan (5 han, or 3–4 han where the fu pushes the base to 2,000), haneman (6–7), baiman (8–10), sanbaiman (11–12) and yakuman (13+), with the base points behind each. The honba endpoint adds the table bonuses — 300 per honba counter and 1,000 per riichi stick — on top of the won hand. Everything is computed locally and deterministically, so it is instant and exact. Ideal for mahjong apps, online-table and scorekeeper tools, club and tournament software, and learning aids. Pure local computation — no key, no third-party service, instant. Exact scoring-table maths. Live, nothing stored. 3 compute endpoints. Japanese riichi rules; other variants (MCR, Hong Kong) score differently.

## 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/mahjong-api/..."
```

## Pricing
- **Free** (Free) — 5,000 calls/Mo, 2 req/s
- **Starter** ($4/Mo) — 75,000 calls/Mo, 8 req/s
- **Pro** ($13/Mo) — 310,000 calls/Mo, 20 req/s
- **Mega** ($39/Mo) — 1,450,000 calls/Mo, 48 req/s

## Endpoints

### Mahjong

#### `GET /v1/honba` — Honba and riichi-stick bonuses

**Parameters:**
- `points` (query, required, string) — Base won points Example: `3900`
- `honba` (query, optional, string) — Honba counters Example: `2`
- `riichi_sticks` (query, optional, string) — Riichi sticks on the table Example: `1`

**Example:**
```bash
curl -H "x-oanor-key: $KEY" \
  "https://api.oanor.com/mahjong-api/v1/honba?points=3900&honba=2&riichi_sticks=1"
```

**Response:**
```json
{
    "data": {
        "note": "Each honba counter adds 300 points to the win (100 from each player on a tsumo, all 300 from the discarder on a ron). Riichi sticks on the table are worth 1000 each and go to the winner. Sticks are picked up; honba carries to the next hand if the dealer keeps winning or on a draw.",
        "inputs": {
            "honba": 2,
            "points": 3900,
            "riichi_sticks": 1
        },
        "total_won": 5500,
        "honba_bonus": 600,
        "riichi_stick_bonus": 1000
    },
    "meta": {
        "timestamp": "2026-06-06T15:30:46.268Z",
        "request_id": "06faedde-9d94-4e20-a671-2cef6c3b3934"
    },
    "status": "ok",
    "message": "Honba bonus",
    "success": true
}
```

#### `GET /v1/limit` — Limit-hand classification

**Parameters:**
- `han` (query, required, string) — Han count Example: `7`
- `fu` (query, optional, string) — Fu (default 30) Example: `30`

**Example:**
```bash
curl -H "x-oanor-key: $KEY" \
  "https://api.oanor.com/mahjong-api/v1/limit?han=7&fu=30"
```

**Response:**
```json
{
    "data": {
        "note": "Limit hands cap the score: mangan (5 han, or 3–4 han with high fu where base reaches 2000) = 2000 base, haneman (6–7) = 3000, baiman (8–10) = 4000, sanbaiman (11–12) = 6000, yakuman (13+) = 8000. A non-dealer mangan ron is 8000 points; a dealer mangan ron is 12000.",
        "limit": "haneman",
        "inputs": {
            "fu": 30,
            "han": 7
        },
        "base_points": 3000,
        "is_limit_hand": true
    },
    "meta": {
        "timestamp": "2026-06-06T15:30:46.376Z",
        "request_id": "a37f5028-0e6b-4f45-b493-d10a5651cb6e"
    },
    "status": "ok",
    "message": "Limit hand",
    "success": true
}
```

#### `GET /v1/score` — Points from han and fu

**Parameters:**
- `han` (query, required, string) — Han count Example: `3`
- `fu` (query, optional, string) — Fu (default 30; ignored at 5+ han) Example: `30`
- `dealer` (query, optional, string) — Dealer (oya) win Example: `false`
- `tsumo` (query, optional, string) — Self-draw win Example: `false`

**Example:**
```bash
curl -H "x-oanor-key: $KEY" \
  "https://api.oanor.com/mahjong-api/v1/score?han=3&fu=30&dealer=false&tsumo=false"
```

**Response:**
```json
{
    "data": {
        "note": "Riichi scoring: base = fu × 2^(2 + han); a ron pays base×4 (dealer ×6) rounded up to 100, a tsumo splits base×2 from the dealer and base×1 from each non-dealer (dealer tsumo is base×2 from all three). From 5 han the hand is a limit hand and fu no longer matters. Add honba and riichi sticks separately.",
        "limit": null,
        "inputs": {
            "fu": 30,
            "han": 3,
            "tsumo": false,
            "dealer": false
        },
        "payments": {
            "discarder_pays": 3900
        },
        "base_points": 960,
        "total_points": 3900
    },
    "meta": {
        "timestamp": "2026-06-06T15:30:46.479Z",
        "request_id": "8f177790-cb6a-4120-8722-c6684cc70493"
    },
    "status": "ok",
    "message": "Hand score",
    "success": true
}
```

### Meta

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

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

**Response:**
```json
{
    "data": {
        "notes": "Exact riichi scoring: base = fu × 2^(2+han), ron base×4 (dealer ×6) round up to 100, tsumo split base×2/base×1. Limits mangan→yakuman. Japanese rules; for other variants (MCR, HK) the tables differ.",
        "service": "mahjong-api",
        "endpoints": {
            "GET /v1/meta": "This document.",
            "GET /v1/honba": "Honba-counter and riichi-stick bonuses on top of a won hand.",
            "GET /v1/limit": "Limit-hand classification (mangan … yakuman) from han and fu.",
            "GET /v1/score": "Points a winning hand pays from han, fu, dealer status and win type."
        },
        "description": "Riichi (Japanese) mahjong scoring: points from han and fu, limit-hand classification, and honba/riichi-stick bonuses."
    },
    "meta": {
        "timestamp": "2026-06-06T15:30:46.577Z",
        "request_id": "5a099961-8266-4597-9beb-93335fce5827"
    },
    "status": "ok",
    "message": "Meta",
    "success": true
}
```


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