{
  "openapi": "3.0.3",
  "info": {
    "title": "KenoSpots Keno Results API",
    "description": "A free JSON API that returns the latest keno and Quick Draw draw results for 20+ US states and Canadian games. Each response contains a `draws` array ordered newest first, where every draw includes the official draw number, draw date, IANA timezone, the 20 winning numbers, and optional bonus, multiplier, Bullseye, and jackpot fields where the game reports them.\n\nNo API key is required for the free tier. Swap the `{slug}` path parameter for any supported game to fetch its most recent draws.\n\n## Rate limits\nThe free tier is limited to **60 requests per minute per IP**, with no authentication required. Draw data refreshes roughly every 60 seconds, so polling faster than once a minute per game returns no fresher data. Please cache responses where you can. Clients that exceed the limit receive an `HTTP 429` response; back off and retry after a short delay.\n\n## Attribution\nThe API is free for personal and commercial use. If you publish or display data from this API, you must include a visible \"Powered by KenoSpots\" credit linking back to https://kenospots.com/. Please do not resell raw API responses or present the data as your own. Always verify winning tickets against the official lottery. KenoSpots is an independent informational resource and is not affiliated with any lottery commission.",
    "version": "1.0.0",
    "termsOfService": "https://kenospots.com/terms/",
    "contact": {
      "name": "KenoSpots API Team",
      "email": "api@kenospots.com",
      "url": "https://kenospots.com/api/"
    },
    "license": {
      "name": "Free for personal and commercial use with attribution",
      "url": "https://kenospots.com/api/#attribution"
    }
  },
  "externalDocs": {
    "description": "Human-readable API documentation",
    "url": "https://kenospots.com/api/"
  },
  "servers": [
    {
      "url": "https://app.kenospots.com",
      "description": "Production API"
    }
  ],
  "tags": [
    {
      "name": "Results",
      "description": "Fetch the latest keno and Quick Draw draw results for a supported game."
    }
  ],
  "paths": {
    "/api/results/{slug}": {
      "get": {
        "tags": ["Results"],
        "summary": "Get latest draws for a game",
        "description": "Returns the most recent draws for the game identified by `{slug}`, ordered newest first. No authentication is required. An unknown slug returns `404`.",
        "operationId": "getResultsBySlug",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "The game identifier. Pass one of the supported slugs, for example `mass-keno` or `ohio-keno`.",
            "schema": {
              "type": "string",
              "enum": [
                "mass-keno",
                "ohio-keno",
                "michigan-club-keno",
                "california-hot-spot",
                "ny-quick-draw",
                "new-jersey-quick-draw",
                "pennsylvania-keno",
                "virginia-keno",
                "maryland-keno",
                "kentucky-keno",
                "georgia-keno",
                "oregon-keno",
                "connecticut-keno",
                "kansas-keno",
                "rhode-island-keno",
                "new-hampshire-keno",
                "missouri-keno",
                "delaware-keno",
                "dc-keno",
                "wyoming-keno",
                "bc-keno",
                "daily-keno",
                "keno-atlantic"
              ]
            },
            "examples": {
              "massachusetts": {
                "summary": "Massachusetts Keno",
                "value": "mass-keno"
              },
              "ohio": {
                "summary": "Ohio Keno",
                "value": "ohio-keno"
              },
              "newYork": {
                "summary": "New York Quick Draw",
                "value": "ny-quick-draw"
              },
              "ontario": {
                "summary": "OLG Daily Keno (Ontario, field of 1-70)",
                "value": "daily-keno"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The latest draws for the requested game.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResultsResponse"
                },
                "example": {
                  "draws": [
                    {
                      "drawNumber": 3023269,
                      "drawDate": "2026-06-24",
                      "drawTime": "2026-06-24T17:12:00-04:00",
                      "timezone": "America/New_York",
                      "winningNumbers": [75, 65, 62, 31, 52, 27, 66, 12, 7, 30, 46, 10, 58, 2, 76, 32, 29, 45, 61, 59],
                      "bonus": 1,
                      "extraNumbers": [],
                      "bullseyeNumber": null,
                      "multiplier": null,
                      "multiplierType": "booster",
                      "jackpotAmount": null,
                      "ballsDrawn": 20,
                      "source": "Massachusetts Lottery feed",
                      "kenospotsUpdatedAt": "2026-06-24T21:13:04.512Z",
                      "freshnessStatus": "live",
                      "expectedUpdateFrequency": "every few minutes",
                      "isOfficial": false,
                      "disclaimer": "KenoSpots is an independent informational site. Verify prizes with the official lottery."
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "The requested slug is not a recognized game.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Unknown game slug"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. The free tier allows 60 requests per minute per IP. Back off and retry after a short delay.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Rate limit exceeded"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ResultsResponse": {
        "type": "object",
        "description": "The top-level response body for a results request.",
        "required": ["draws"],
        "properties": {
          "draws": {
            "type": "array",
            "description": "The recent draws for the game, ordered newest first.",
            "items": {
              "$ref": "#/components/schemas/Draw"
            }
          }
        }
      },
      "Draw": {
        "type": "object",
        "description": "A single keno draw. Optional fields are populated only for games that report them and are `null` or empty otherwise.",
        "required": ["drawNumber", "drawDate", "drawTime", "timezone", "winningNumbers", "ballsDrawn", "source", "kenospotsUpdatedAt", "freshnessStatus", "expectedUpdateFrequency", "isOfficial", "disclaimer"],
        "properties": {
          "drawNumber": {
            "type": "integer",
            "description": "The official sequential game number for the draw. Useful as a stable identifier and for ordering.",
            "example": 3023269
          },
          "drawDate": {
            "type": "string",
            "format": "date",
            "description": "The draw date in YYYY-MM-DD format, in the game's local timezone.",
            "example": "2026-06-24"
          },
          "drawTime": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "The draw time as an ISO 8601 timestamp with the game's local UTC offset, derived from the draw date and timezone. Useful for games that draw every few minutes, where the date alone is not enough to order draws. Null when no usable draw date is available.",
            "example": "2026-06-24T17:12:00-04:00"
          },
          "timezone": {
            "type": "string",
            "description": "The IANA timezone the draw date and time are expressed in.",
            "example": "America/New_York"
          },
          "winningNumbers": {
            "type": "array",
            "description": "The drawn numbers, in draw order. Standard keno draws 20 numbers from 1-80; some Canadian games draw from a field of 1-70.",
            "items": {
              "type": "integer"
            },
            "example": [75, 65, 62, 31, 52, 27, 66, 12, 7, 30, 46, 10, 58, 2, 76, 32, 29, 45, 61, 59]
          },
          "ballsDrawn": {
            "type": "integer",
            "description": "How many numbers were drawn (typically 20).",
            "example": 20
          },
          "bonus": {
            "type": "integer",
            "description": "The bonus or multiplier value applied to the draw, where the game supports it (often 1 when no enhanced multiplier is in play).",
            "example": 1
          },
          "multiplier": {
            "type": "integer",
            "nullable": true,
            "description": "The active multiplier for games that draw one separately from `bonus`. Null when not applicable.",
            "example": null
          },
          "multiplierType": {
            "type": "string",
            "nullable": true,
            "description": "The name of the multiplier feature for the game, for example `booster`.",
            "example": "booster"
          },
          "extraNumbers": {
            "type": "array",
            "description": "Any supplementary numbers some games draw in addition to the main 20. Empty for most games.",
            "items": {
              "type": "integer"
            },
            "example": []
          },
          "bullseyeNumber": {
            "type": "integer",
            "nullable": true,
            "description": "The Bullseye number for games that offer a Bullseye add-on. Null otherwise.",
            "example": null
          },
          "jackpotAmount": {
            "type": "number",
            "nullable": true,
            "description": "The reported jackpot amount where the game publishes one. Null otherwise.",
            "example": null
          },
          "source": {
            "type": "string",
            "description": "Human-readable name of the upstream feed this result was sourced from.",
            "example": "Massachusetts Lottery feed"
          },
          "kenospotsUpdatedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "ISO 8601 timestamp (UTC) of when KenoSpots last fetched and cached this result.",
            "example": "2026-06-24T21:13:04.512Z"
          },
          "freshnessStatus": {
            "type": "string",
            "enum": ["live", "hourly", "daily"],
            "description": "How frequently this feed publishes new draws. `live` feeds draw every few minutes, `hourly` refresh roughly once an hour, and `daily` publish a batch each day.",
            "example": "live"
          },
          "expectedUpdateFrequency": {
            "type": "string",
            "description": "Human-readable cadence at which this feed updates.",
            "example": "every few minutes"
          },
          "isOfficial": {
            "type": "boolean",
            "description": "Always `false`. KenoSpots is an independent informational resource, not the official source of results.",
            "example": false
          },
          "disclaimer": {
            "type": "string",
            "description": "Standard disclaimer reminding consumers to verify prizes with the official lottery.",
            "example": "KenoSpots is an independent informational site. Verify prizes with the official lottery."
          }
        }
      },
      "Error": {
        "type": "object",
        "description": "A standard error response.",
        "properties": {
          "error": {
            "type": "string",
            "description": "A human-readable description of the error.",
            "example": "Unknown game slug"
          }
        }
      }
    }
  }
}
