{
  "openapi": "3.1.0",
  "info": {
    "title": "台灣彩券開獎歷史 API",
    "description": "timetable.tw 台灣彩券開獎歷史的公開唯讀 JSON API。資料供查詢、統計與研究參考，實際開獎結果與投注規則請以台灣彩券官方公告為準。",
    "version": "1.0.0",
    "license": {
      "name": "資料使用條款",
      "url": "https://lottery.timetable.tw/about/license"
    }
  },
  "servers": [
    {
      "url": "https://lottery.timetable.tw",
      "description": "Production"
    }
  ],
  "externalDocs": {
    "description": "timetable.tw 開發者資源",
    "url": "https://lottery.timetable.tw/developers"
  },
  "tags": [
    {
      "name": "Games",
      "description": "彩券類型"
    },
    {
      "name": "Draws",
      "description": "開獎記錄"
    },
    {
      "name": "Statistics",
      "description": "開獎統計分析"
    }
  ],
  "paths": {
    "/api/games": {
      "get": {
        "operationId": "listGames",
        "tags": [
          "Games"
        ],
        "summary": "列出彩券類型",
        "responses": {
          "200": {
            "description": "彩券類型清單",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Game"
                  }
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/draws": {
      "get": {
        "operationId": "listDraws",
        "tags": [
          "Draws"
        ],
        "summary": "查詢開獎記錄",
        "description": "依彩券類型、日期、期別與排序方式查詢開獎記錄。使用 latestEach=true 可取得每種遊戲最新一筆。",
        "parameters": [
          {
            "$ref": "#/components/parameters/GameTypeId"
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Offset"
          },
          {
            "$ref": "#/components/parameters/StartDate"
          },
          {
            "$ref": "#/components/parameters/EndDate"
          },
          {
            "$ref": "#/components/parameters/StartPeriod"
          },
          {
            "$ref": "#/components/parameters/EndPeriod"
          },
          {
            "$ref": "#/components/parameters/SortOrder"
          },
          {
            "$ref": "#/components/parameters/LatestEach"
          }
        ],
        "responses": {
          "200": {
            "description": "開獎記錄與總筆數",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DrawList"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/stats": {
      "get": {
        "operationId": "getDrawStats",
        "tags": [
          "Statistics"
        ],
        "summary": "取得彩券統計摘要",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequiredGameTypeId"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/AnyJson"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/stats/comparison": {
      "get": {
        "operationId": "compareDrawStats",
        "tags": [
          "Statistics"
        ],
        "summary": "比較不同統計期間",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequiredGameTypeId"
          },
          {
            "$ref": "#/components/parameters/StartYear"
          },
          {
            "$ref": "#/components/parameters/EndYear"
          },
          {
            "$ref": "#/components/parameters/StartPeriod"
          },
          {
            "$ref": "#/components/parameters/EndPeriod"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/AnyJson"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/stats/date-range": {
      "get": {
        "operationId": "getDrawDateRange",
        "tags": [
          "Statistics"
        ],
        "summary": "取得可用日期與期別範圍",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequiredGameTypeId"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/AnyJson"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/stats/games-comparison": {
      "get": {
        "operationId": "compareGames",
        "tags": [
          "Statistics"
        ],
        "summary": "比較各彩券遊戲統計",
        "responses": {
          "200": {
            "$ref": "#/components/responses/AnyJson"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/stats/heatmap": {
      "get": {
        "operationId": "getNumberHeatmap",
        "tags": [
          "Statistics"
        ],
        "summary": "取得號碼熱度圖資料",
        "description": "type 可使用 general 或 special。",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequiredGameTypeId"
          },
          {
            "$ref": "#/components/parameters/StartYear"
          },
          {
            "$ref": "#/components/parameters/EndYear"
          },
          {
            "$ref": "#/components/parameters/StartPeriod"
          },
          {
            "$ref": "#/components/parameters/EndPeriod"
          },
          {
            "name": "type",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "general",
                "special"
              ],
              "default": "general"
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/AnyJson"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/stats/number-cooccurrence": {
      "get": {
        "operationId": "getNumberCooccurrence",
        "tags": [
          "Statistics"
        ],
        "summary": "取得號碼共現關係",
        "parameters": [
          {
            "$ref": "#/components/parameters/StatsQueryGameTypeId"
          },
          {
            "$ref": "#/components/parameters/StartYear"
          },
          {
            "$ref": "#/components/parameters/EndYear"
          },
          {
            "$ref": "#/components/parameters/StartPeriod"
          },
          {
            "$ref": "#/components/parameters/EndPeriod"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/AnyJson"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/stats/number-missing": {
      "get": {
        "operationId": "getNumberMissing",
        "tags": [
          "Statistics"
        ],
        "summary": "取得號碼遺漏分析",
        "parameters": [
          {
            "$ref": "#/components/parameters/StatsQueryGameTypeId"
          },
          {
            "$ref": "#/components/parameters/MinimumNumber"
          },
          {
            "$ref": "#/components/parameters/MaximumNumber"
          },
          {
            "$ref": "#/components/parameters/IsSpecial"
          },
          {
            "$ref": "#/components/parameters/StartYear"
          },
          {
            "$ref": "#/components/parameters/EndYear"
          },
          {
            "$ref": "#/components/parameters/StartPeriod"
          },
          {
            "$ref": "#/components/parameters/EndPeriod"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/AnyJson"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/stats/number-temperature": {
      "get": {
        "operationId": "getNumberTemperature",
        "tags": [
          "Statistics"
        ],
        "summary": "取得號碼冷熱門分析",
        "parameters": [
          {
            "$ref": "#/components/parameters/StatsQueryGameTypeId"
          },
          {
            "$ref": "#/components/parameters/StartYear"
          },
          {
            "$ref": "#/components/parameters/EndYear"
          },
          {
            "$ref": "#/components/parameters/StartPeriod"
          },
          {
            "$ref": "#/components/parameters/EndPeriod"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/AnyJson"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/stats/numbers-frequency": {
      "get": {
        "operationId": "getNumbersFrequency",
        "tags": [
          "Statistics"
        ],
        "summary": "取得號碼出現頻率",
        "parameters": [
          {
            "$ref": "#/components/parameters/StatsQueryGameTypeId"
          },
          {
            "$ref": "#/components/parameters/StartYear"
          },
          {
            "$ref": "#/components/parameters/EndYear"
          },
          {
            "$ref": "#/components/parameters/StartPeriod"
          },
          {
            "$ref": "#/components/parameters/EndPeriod"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/AnyJson"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/stats/odd-even-ratio": {
      "get": {
        "operationId": "getOddEvenRatio",
        "tags": [
          "Statistics"
        ],
        "summary": "取得奇偶與大小比例",
        "parameters": [
          {
            "$ref": "#/components/parameters/StatsQueryGameTypeId"
          },
          {
            "$ref": "#/components/parameters/StartYear"
          },
          {
            "$ref": "#/components/parameters/EndYear"
          },
          {
            "$ref": "#/components/parameters/StartPeriod"
          },
          {
            "$ref": "#/components/parameters/EndPeriod"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/AnyJson"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/stats/prize-combinations": {
      "get": {
        "operationId": "getPrizeCombinations",
        "tags": [
          "Statistics"
        ],
        "summary": "取得獎項組合統計",
        "parameters": [
          {
            "$ref": "#/components/parameters/StatsQueryGameTypeId"
          },
          {
            "name": "prizeLevel",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/StartYear"
          },
          {
            "$ref": "#/components/parameters/EndYear"
          },
          {
            "$ref": "#/components/parameters/StartPeriod"
          },
          {
            "$ref": "#/components/parameters/EndPeriod"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/AnyJson"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/stats/prize-levels": {
      "get": {
        "operationId": "getPrizeLevels",
        "tags": [
          "Statistics"
        ],
        "summary": "取得彩券獎項列表",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequiredGameTypeId"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/AnyJson"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/stats/scatter-data": {
      "get": {
        "operationId": "getScatterData",
        "tags": [
          "Statistics"
        ],
        "summary": "取得散點圖資料",
        "description": "type 可使用 number-frequency、sales-prize、date-sales 或 number-distribution。",
        "parameters": [
          {
            "$ref": "#/components/parameters/StatsQueryGameTypeId"
          },
          {
            "name": "type",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "number-frequency",
                "sales-prize",
                "date-sales",
                "number-distribution"
              ],
              "default": "number-frequency"
            }
          },
          {
            "$ref": "#/components/parameters/StartYear"
          },
          {
            "$ref": "#/components/parameters/EndYear"
          },
          {
            "$ref": "#/components/parameters/StartPeriod"
          },
          {
            "$ref": "#/components/parameters/EndPeriod"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/AnyJson"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/stats/sum-trend": {
      "get": {
        "operationId": "getSumTrend",
        "tags": [
          "Statistics"
        ],
        "summary": "取得號碼和值趨勢",
        "parameters": [
          {
            "$ref": "#/components/parameters/StatsQueryGameTypeId"
          },
          {
            "$ref": "#/components/parameters/StartYear"
          },
          {
            "$ref": "#/components/parameters/EndYear"
          },
          {
            "$ref": "#/components/parameters/StartPeriod"
          },
          {
            "$ref": "#/components/parameters/EndPeriod"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/AnyJson"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/stats/summary": {
      "get": {
        "operationId": "getStatsSummary",
        "tags": [
          "Statistics"
        ],
        "summary": "取得統計摘要與遊戲資訊",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequiredGameTypeId"
          },
          {
            "$ref": "#/components/parameters/StartYear"
          },
          {
            "$ref": "#/components/parameters/EndYear"
          },
          {
            "$ref": "#/components/parameters/StartPeriod"
          },
          {
            "$ref": "#/components/parameters/EndPeriod"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/AnyJson"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/api/stats/trends": {
      "get": {
        "operationId": "getTrends",
        "tags": [
          "Statistics"
        ],
        "summary": "取得銷售與獎金趨勢",
        "parameters": [
          {
            "$ref": "#/components/parameters/StatsQueryGameTypeId"
          },
          {
            "name": "period",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "month",
                "year",
                "week"
              ],
              "default": "month"
            }
          },
          {
            "$ref": "#/components/parameters/StartYear"
          },
          {
            "$ref": "#/components/parameters/EndYear"
          },
          {
            "$ref": "#/components/parameters/StartPeriod"
          },
          {
            "$ref": "#/components/parameters/EndPeriod"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/AnyJson"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    }
  },
  "components": {
    "parameters": {
      "GameTypeId": {
        "name": "gameTypeId",
        "in": "query",
        "description": "彩券類型 ID。",
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      },
      "RequiredGameTypeId": {
        "name": "gameTypeId",
        "in": "query",
        "description": "彩券類型 ID。",
        "required": true,
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      },
      "StatsQueryGameTypeId": {
        "name": "gameTypeId",
        "in": "query",
        "description": "彩券類型 ID。",
        "required": true,
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      },
      "Limit": {
        "name": "limit",
        "in": "query",
        "description": "回傳筆數，預設 50。",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 500,
          "default": 50
        }
      },
      "Offset": {
        "name": "offset",
        "in": "query",
        "description": "跳過的筆數，預設 0。",
        "schema": {
          "type": "integer",
          "minimum": 0,
          "default": 0
        }
      },
      "StartDate": {
        "name": "startDate",
        "in": "query",
        "schema": {
          "type": "string",
          "format": "date"
        }
      },
      "EndDate": {
        "name": "endDate",
        "in": "query",
        "schema": {
          "type": "string",
          "format": "date"
        }
      },
      "StartYear": {
        "name": "startYear",
        "in": "query",
        "schema": {
          "type": "string",
          "pattern": "^[0-9]{4}$"
        }
      },
      "EndYear": {
        "name": "endYear",
        "in": "query",
        "schema": {
          "type": "string",
          "pattern": "^[0-9]{4}$"
        }
      },
      "StartPeriod": {
        "name": "startPeriod",
        "in": "query",
        "schema": {
          "type": "string"
        }
      },
      "EndPeriod": {
        "name": "endPeriod",
        "in": "query",
        "schema": {
          "type": "string"
        }
      },
      "SortOrder": {
        "name": "sortOrder",
        "in": "query",
        "schema": {
          "type": "string",
          "enum": [
            "DESC",
            "ASC"
          ],
          "default": "DESC"
        }
      },
      "LatestEach": {
        "name": "latestEach",
        "in": "query",
        "description": "設為 true 時只回傳每種遊戲最新一筆。",
        "schema": {
          "type": "boolean",
          "default": false
        }
      },
      "MinimumNumber": {
        "name": "minNumber",
        "in": "query",
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      },
      "MaximumNumber": {
        "name": "maxNumber",
        "in": "query",
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      },
      "IsSpecial": {
        "name": "isSpecial",
        "in": "query",
        "description": "設為 true 時分析特別號，預設分析一般號碼。",
        "schema": {
          "type": "boolean",
          "default": false
        }
      }
    },
    "responses": {
      "AnyJson": {
        "description": "JSON 結果；具體欄位依端點與 query 參數而定。",
        "content": {
          "application/json": {
            "schema": {}
          }
        }
      },
      "BadRequest": {
        "description": "缺少或無效的 query 參數。",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "找不到指定的彩券類型或資源。",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "ServerError": {
        "description": "伺服器或資料庫暫時無法使用。",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "Game": {
        "type": "object",
        "required": [
          "id",
          "name",
          "display_name"
        ],
        "properties": {
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string"
          },
          "display_name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "number_count": {
            "type": "integer"
          },
          "has_special_number": {
            "type": "boolean"
          },
          "special_number_name": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "Draw": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "game_type_id": {
            "type": "integer"
          },
          "game_name": {
            "type": "string"
          },
          "game_display_name": {
            "type": "string"
          },
          "period": {
            "type": "string"
          },
          "draw_date": {
            "type": "string",
            "format": "date"
          },
          "numbers": {
            "type": "array",
            "items": {
              "type": "integer"
            }
          },
          "special_number": {
            "type": [
              "integer",
              "null"
            ]
          },
          "sales_amount": {
            "type": "number"
          },
          "sales_count": {
            "type": "number"
          },
          "total_prize": {
            "type": "number"
          }
        }
      },
      "DrawList": {
        "type": "object",
        "required": [
          "records",
          "totalCount"
        ],
        "properties": {
          "records": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Draw"
            }
          },
          "totalCount": {
            "type": "integer"
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string"
          }
        }
      }
    }
  }
}
