{
  "openapi": "3.1.0",
  "info": {
    "title": "MouseHunt API",
    "version": "1.0.0",
    "description": "Unofficial, read-only API for public MouseHunt data."
  },
  "servers": [
    {
      "url": "https://api.mouse.rip"
    }
  ],
  "tags": [
    {
      "name": "Search & Querying",
      "x-page": "search",
      "x-summary": "Cross-type search, filtering, sorting, pagination, and facet counts for items and mice.",
      "description": "Every collection accepts query parameters for filtering, searching, sorting, pagination, and field selection. [`/search`](#search) returns compact, relevance-ranked results across items, mice, and locations, and the [facet endpoints](#get-item-facets) list the available filter values with counts.",
      "x-sections": [
        {
          "title": "Query parameters",
          "description": "Every collection accepts these optional parameters: `/items`, `/mice`, [`/attraction`](/attraction), [`/environments`](/environments), [`/recipes`](/recipes), [`/store`](/store), [`/titles`](/titles), [`/power-types`](/power-types) and [`/scoreboards`](/scoreboards). The same options work when requesting a single record, such as `/items/114`. Requests without a query string return the complete, unmodified response.\n\nFiltered collection responses include `ETag`, `X-Result-Count`, and `X-Total-Count` headers and support conditional requests with `If-None-Match`. Invalid pagination values, unsupported sort fields, more than 50 filters, and more than 100 `fields` return a `400` with an `error.code` of `invalid_query`. Parameters that match no field on any record, such as tracking params or typos, are ignored.",
          "parameters": [
            {
              "name": "q",
              "in": "query",
              "schema": {
                "type": "string"
              },
              "description": "Case-insensitive partial search across name, type, abbreviated name, and description. `search` is an alias."
            },
            {
              "name": "[field]",
              "in": "query",
              "schema": {
                "type": "string"
              },
              "description": "Any field acts as a case-insensitive exact filter, e.g. `classification=bait`, `group=Event Mice`, or boolean flags like `is_tradable=true`. Nested fields use dots, including through lists, e.g. `has_stats.power_type=hydro` or `items.type=super_brie_cheese`; a list matches if any of its values does. For fields only some records have, such as an item's `status` or `category`, records missing the field are excluded."
            },
            {
              "name": "ids",
              "in": "query",
              "schema": {
                "type": "string"
              },
              "description": "Comma-separated (or repeated) IDs for bulk lookup, e.g. `ids=114,3058`."
            },
            {
              "name": "types",
              "in": "query",
              "schema": {
                "type": "string"
              },
              "description": "Comma-separated (or repeated) type slugs for bulk lookup."
            },
            {
              "name": "fields",
              "in": "query",
              "schema": {
                "type": "string"
              },
              "description": "Comma-separated fields to return. Nested fields are supported, e.g. `fields=id,name,images.thumbnail`."
            },
            {
              "name": "sort",
              "in": "query",
              "schema": {
                "type": "string"
              },
              "description": "Sort field; prefix with `-` for descending. Items support `classification`, `id`, `name`, `type`, `has_stats.power`, `has_stats.power_bonus`, `has_stats.luck`, and `has_stats.attraction_bonus`. Mice support `gold`, `group`, `id`, `name`, `points`, `subgroup`, `type`, and `wisdom`. Each other collection lists its sort fields on its page. Records without the field go last in either direction."
            },
            {
              "name": "offset",
              "in": "query",
              "schema": {
                "type": "integer"
              },
              "description": "Number of records to skip. Defaults to `0`."
            },
            {
              "name": "limit",
              "in": "query",
              "schema": {
                "type": "integer"
              },
              "description": "Maximum number of records to return. Unlimited by default."
            },
            {
              "name": "meta",
              "in": "query",
              "schema": {
                "type": "boolean"
              },
              "description": "Set to `true` to wrap collection results in `{ data, meta }` with pagination metadata."
            },
            {
              "name": "v",
              "in": "query",
              "schema": {
                "type": "string"
              },
              "description": "Cache-busting version token from [`/versions`](/versions). Not a filter."
            }
          ],
          "x-example": "/items?classification=bait&is_tradable=true&fields=id,name&limit=3&meta=true",
          "x-example-response": "{\n  \"data\": [\n    { \"id\": 103, \"name\": \"Maki Cheese\" },\n    { \"id\": 105, \"name\": \"Moon Cheese\" },\n    { \"id\": 108, \"name\": \"Radioactive Blue Cheese\" }\n  ],\n  \"meta\": {\n    \"count\": 3,\n    \"has_more\": true,\n    \"limit\": 3,\n    \"next_offset\": 3,\n    \"offset\": 0,\n    \"total\": 28\n  }\n}",
          "x-nav": "Query parameters"
        }
      ]
    },
    {
      "name": "Mice",
      "x-page": "mice",
      "x-summary": "Mouse data including stats, weaknesses, minlucks, wisdom, attraction rates, and images.",
      "description": "`/mouse` is an alias for `/mice`. Any `:id` accepts a numeric ID or a mouse type (slug)."
    },
    {
      "name": "Burroughs Rift Mice",
      "x-page": "brift-mice-per-mist-level",
      "x-summary": "Burroughs Rift mice grouped by mist tier and cheese type.",
      "description": "The mice available in the Burroughs Rift at each mist tier, grouped by cheese type."
    },
    {
      "name": "Catch Rate",
      "x-page": "catch-rate",
      "x-summary": "Catch rates for a trap against a mouse, several mice, or a setup.",
      "description": "Work out the chance of catching a mouse from your trap's power, luck, and power type."
    },
    {
      "name": "Attraction",
      "x-page": "attraction",
      "x-summary": "Mouse attraction rates by location, stage, cheese and charm, from MH-Tools and MHCT.",
      "description": "Mouse attraction rates from [MH-Tools](https://github.com/tsitu/MH-Tools) and [MHCT](https://mhct.win), per population: a location, stage, cheese and charm. `-` means no stage or no charm.",
      "x-footer": "## Sources\n\nMH-Tools is the preferred source. MHCT fills in only populations MH-Tools doesn't have; its rates are never mixed into an MH-Tools population. [`/attraction/meta`](#get-attraction-sources-and-coverage) gives each population's source and sample size.\n\nMHCT rates use the last 365 days of hunts, with at least 100 attracted hunts per population. They count catches and failed catches, not failures to attract. MHCT stages are renamed to the matching MH-Tools stage, and finer MHCT splits (Sunken City depths, Furoma Rift batteries, Train Station steps, Bountiful Beanstalk room loot, Moussu Picchu weather) are pooled into it. Stages without a clear MH-Tools match keep their MHCT name, with simultaneous tags joined by ` + `.\n\nRates are observed proportions, not exact game odds, and other equipment and hunt details are pooled. Zugzwang's Tower, Iceberg, Valour Rift, and Epilogue Falls use MH-Tools data only. A missing population does not mean a 0% attraction rate."
    },
    {
      "name": "Loot",
      "x-page": "loot",
      "x-summary": "What each mouse drops, and which mice drop each item, from MHCT.",
      "description": "What each mouse drops at each location, built weekly from [MHCT](https://mhct.win) hunt data. Both endpoints accept an ID or type. A known mouse or item without enough data returns `[]`; anything else returns `404`.\n\nMouse/location pairs with fewer than 100 catches, and drops under 0.1%, are left out. `lift` is near 1 for charms, cheese and event loot any mouse can drop, and high for mouse-specific loot."
    },
    {
      "name": "Items",
      "x-page": "items",
      "x-summary": "Item data including stats, images, tradability, and name/ID lookups.",
      "description": "`/item` is an alias for `/items`. Any `:id` accepts a numeric ID or an item type (slug)."
    },
    {
      "name": "Trap Special Effects",
      "x-page": "trap-special-effects",
      "x-summary": "Bases with special effects, globally and by location.",
      "description": "The bases that have a special effect, both globally (`all`) and per location. Values are base types (slugs)."
    },
    {
      "name": "Airship Parts",
      "x-page": "airships",
      "x-summary": "Floating Islands airship hulls, balloons, and sails.",
      "description": "Floating Islands airship parts: hulls, balloons, and sails."
    },
    {
      "name": "Potions",
      "x-page": "potions",
      "x-summary": "Potion recipes: inputs, outputs, gold cost, and required title.",
      "description": "Every potion and its recipes — what it consumes, what it produces, the gold cost, and the title required for each recipe tier."
    },
    {
      "name": "Environments",
      "x-page": "environments",
      "x-summary": "Permanent and event locations, with images, regions, and required titles.",
      "description": ""
    },
    {
      "name": "Maps",
      "x-page": "maps",
      "x-summary": "Scroll-to-map mappings, map relations, and the maps a mouse appears on.",
      "description": "Data about treasure maps: which maps a scroll case opens, the chests they award, and which maps a mouse can appear on."
    },
    {
      "name": "Relic Hunter",
      "x-page": "relic-hunter",
      "x-summary": "Where the Relic Hunter is, where it has been, and location hints.",
      "description": ""
    },
    {
      "name": "Timers",
      "x-page": "timers",
      "x-summary": "Where the rotating locations are in their cycles, and when the daily reset is.",
      "description": "The Forbidden Grove's gate, Balack's Cove's tide, the Seasonal Garden's season, and the Toxic Spill's pollution level all follow a fixed schedule that's the same for every hunter, so these are worked out from the clock rather than fetched. The daily reset is at midnight UTC, when free gifts reset and the Relic Hunter moves."
    },
    {
      "name": "Shops",
      "x-page": "shops",
      "x-summary": "What each location's shop sells, and what it costs.",
      "description": "What every location's shop sells, the gold and items each costs, and what a hunter must own to buy it."
    },
    {
      "name": "Recipes",
      "x-page": "recipes",
      "x-summary": "Crafting recipes and what unlocks them.",
      "description": "Every crafting recipe: what it makes and what unlocks it. Ingredients aren't included. Filter on nested fields with dots, e.g. `unlock.tasks.requirements.type=keepers_assistant`."
    },
    {
      "name": "Store",
      "x-page": "store",
      "x-summary": "SUPER|brie+ store packs, prices and contents.",
      "description": "The SUPER|brie+ store: every pack, what it contains, and its price and SKU on each app store. Filter by contents with `items.type`, e.g. `/store?items.type=super_brie_cheese`."
    },
    {
      "name": "Power Types",
      "x-page": "power-types",
      "x-summary": "Power types, their game codes and icons.",
      "description": "The ten power types."
    },
    {
      "name": "Scoreboards",
      "x-page": "scoreboards",
      "x-summary": "Scoreboards, their groups, and whether they have a weekly ranking.",
      "description": "Every scoreboard, grouped the way the game lists them, and whether each has a weekly ranking."
    },
    {
      "name": "Titles",
      "x-page": "titles",
      "x-summary": "Hunter titles, their icons, and what each unlocks.",
      "description": "Every hunter title from Novice upwards, with its icons, crafting slots, and what it unlocks."
    },
    {
      "name": "Library Assignments",
      "x-page": "library-assignments",
      "x-summary": "Library assignment sets, their costs, rewards and tasks.",
      "description": ""
    },
    {
      "name": "Journals",
      "x-page": "journals",
      "x-summary": "Journal theme mappings for environments and events.",
      "description": ""
    },
    {
      "name": "MHCT",
      "x-page": "mhct",
      "x-summary": "Mouse and item attraction, drop, map, and convertible data sourced from MouseHunt Community Tools (mhct.win).",
      "description": "Community-collected data from [MouseHunt Community Tools](https://mhct.win/) (MHCT). Live endpoints are cached for up to 72 hours, or 6 hours with a rolling time filter.\n\n> MHCT measures rates out of `10,000`, where `10000` means 100%. Divide by `100` to\n> get a percentage."
    },
    {
      "name": "Scrambles",
      "x-page": "scrambles",
      "x-summary": "Scrambles quotes, all of them or one at random.",
      "description": "Quotes from Scrambles: the full list, or one at random."
    },
    {
      "name": "MarketHunt",
      "x-page": "markethunt",
      "x-summary": "MarketHunt prices and charts.",
      "description": "Data from [MarketHunt](https://markethunt.win), the MouseHunt marketplace tracker."
    },
    {
      "name": "Gift Links",
      "x-page": "gift-links",
      "x-summary": "Recent MouseHunt reward and gift links announced by the community.",
      "description": "Recent MouseHunt reward and gift links, newest first. Expired gifts are hidden by default."
    },
    {
      "name": "Versions",
      "x-page": "versions",
      "x-summary": "API status, data versions, and the OpenAPI spec.",
      "description": "Check that the API is up, find out when its data has changed, and get the full API contract. To keep a local copy of a data file current, save its hash from [`/versions`](#get-data-versions) and download the file again only when the hash changes."
    }
  ],
  "x-tagGroups": [
    {
      "name": "Search & Querying",
      "tags": [
        "Search & Querying"
      ]
    },
    {
      "name": "Mice",
      "tags": [
        "Mice",
        "Burroughs Rift Mice",
        "Catch Rate"
      ]
    },
    {
      "name": "Attraction",
      "tags": [
        "Attraction"
      ]
    },
    {
      "name": "Loot",
      "tags": [
        "Loot"
      ]
    },
    {
      "name": "Items",
      "tags": [
        "Items",
        "Trap Special Effects",
        "Airship Parts",
        "Potions"
      ]
    },
    {
      "name": "Environments",
      "tags": [
        "Environments"
      ]
    },
    {
      "name": "Maps",
      "tags": [
        "Maps"
      ]
    },
    {
      "name": "Relic Hunter",
      "tags": [
        "Relic Hunter"
      ]
    },
    {
      "name": "Timers",
      "tags": [
        "Timers"
      ]
    },
    {
      "name": "Game data",
      "tags": [
        "Shops",
        "Recipes",
        "Store",
        "Power Types",
        "Scoreboards",
        "Titles",
        "Library Assignments",
        "Journals"
      ]
    },
    {
      "name": "MHCT",
      "tags": [
        "MHCT"
      ]
    },
    {
      "name": "Scrambles",
      "tags": [
        "Scrambles"
      ]
    },
    {
      "name": "MarketHunt",
      "tags": [
        "MarketHunt"
      ]
    },
    {
      "name": "Tools & Services",
      "tags": [
        "Gift Links",
        "Versions"
      ]
    }
  ],
  "paths": {
    "/attraction": {
      "get": {
        "summary": "Get attraction populations",
        "description": "One record per population, queryable like the other collections. Filter on `location`, `stage`, `cheese`, `charm` or `source`; `q` searches the location, stage, cheese, charm and mouse names. Sort on `location`, `stage`, `cheese`, `charm`, `source`, `sample_size` or `rate`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/CollectionQuery"
          },
          {
            "name": "mouse",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Mouse type or name; comma-separated or repeated. Returns only populations that attract it, lists only that mouse in each, and adds its `rate`, which you can sort on."
          }
        ],
        "responses": {
          "200": {
            "description": "Matching populations.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AttractionPopulation"
                  }
                }
              }
            }
          }
        },
        "tags": [
          "Attraction"
        ],
        "x-example": "/attraction?mouse=burglar&sort=-rate&limit=1",
        "x-nav": "Populations"
      }
    },
    "/attraction/location": {
      "get": {
        "summary": "Get attraction rates by location",
        "description": "The same rates nested as `location → stage → cheese → charm → mouse → percentage`. Filters keep the hierarchy and percentages, and remove empty branches; no matches returns `{}`.\n\nValues match case-insensitively. Repeat a parameter for several values (`location=bazaar&location=zugzwang_library`); different filters combine with AND. Commas don't separate values.",
        "parameters": [
          {
            "name": "location",
            "in": "query",
            "description": "Environment slug, e.g. `bazaar` or `cursed_city`.",
            "style": "form",
            "explode": true,
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "minLength": 1
              }
            }
          },
          {
            "name": "stage",
            "in": "query",
            "description": "Exact stage name, or `-` for no stage.",
            "style": "form",
            "explode": true,
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "minLength": 1
              }
            }
          },
          {
            "name": "cheese",
            "in": "query",
            "description": "Cheese type slug.",
            "style": "form",
            "explode": true,
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "minLength": 1
              }
            }
          },
          {
            "name": "charm",
            "in": "query",
            "description": "Charm type slug, or `-` for no charm.",
            "style": "form",
            "explode": true,
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "minLength": 1
              }
            }
          },
          {
            "name": "mouse",
            "in": "query",
            "description": "Mouse type slug.",
            "style": "form",
            "explode": true,
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "minLength": 1
              }
            }
          },
          {
            "name": "v",
            "in": "query",
            "description": "Optional cache token; not a filter.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Location → stage → cheese → charm → mouse → percentage.",
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Keyed by location.",
                  "additionalProperties": {
                    "type": "object",
                    "description": "Keyed by stage.",
                    "additionalProperties": {
                      "type": "object",
                      "description": "Keyed by cheese.",
                      "additionalProperties": {
                        "type": "object",
                        "description": "Keyed by charm.",
                        "additionalProperties": {
                          "type": "object",
                          "description": "Keyed by mouse.",
                          "additionalProperties": {
                            "type": "number",
                            "minimum": 0,
                            "maximum": 100
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "304": {
            "description": "Unchanged response (If-None-Match)."
          },
          "400": {
            "$ref": "#/components/responses/InvalidQuery"
          },
          "503": {
            "description": "Attraction dataset unavailable."
          }
        },
        "tags": [
          "Attraction"
        ],
        "x-example": "/attraction/location?location=bazaar&cheese=super_brie_cheese&charm=-",
        "x-nav": "Rates by location"
      }
    },
    "/attraction/location/{location}": {
      "get": {
        "summary": "Get attraction rates for a location",
        "description": "Just that location's stages, with the same filters as `/attraction/location`. Unknown locations return `404`.",
        "parameters": [
          {
            "name": "location",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Environment slug."
          }
        ],
        "responses": {
          "200": {
            "description": "Keyed by stage."
          },
          "404": {
            "description": "Unknown location."
          }
        },
        "tags": [
          "Attraction"
        ],
        "x-example": "/attraction/location/bazaar?cheese=super_brie_cheese&charm=-",
        "x-nav": "Rates for a location"
      }
    },
    "/attraction/meta": {
      "get": {
        "summary": "Get attraction sources and coverage",
        "responses": {
          "200": {
            "description": "Source timestamps, thresholds, exclusions, selected population counts, and population metadata keyed by location, stage, cheese and charm.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "mh_tools",
                    "mhct",
                    "population_counts",
                    "populations"
                  ]
                }
              }
            }
          }
        },
        "tags": [
          "Attraction"
        ],
        "description": "Where each population came from and its sample size, using the same hierarchy through charm, plus source timestamps, thresholds, and counts of the populations left out. MHCT entries also have per-mouse encounter counts, first and last hunt times (Unix seconds), and the MHCT stages pooled into the population.",
        "x-example": "/attraction/meta",
        "x-nav": "Sources and coverage"
      }
    },
    "/attraction-meta": {
      "x-data-file": true,
      "get": {
        "summary": "Older name for sources and coverage",
        "responses": {
          "200": {
            "description": "Source timestamps, thresholds, exclusions, selected population counts, and population metadata keyed by location, stage, cheese and charm.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "mh_tools",
                    "mhct",
                    "population_counts",
                    "populations"
                  ]
                }
              }
            }
          }
        },
        "tags": [
          "Attraction"
        ],
        "description": "The same as [`/attraction/meta`](#get-attraction-sources-and-coverage)."
      }
    },
    "/mice-attraction-rates-by-location": {
      "get": {
        "summary": "Older name for rates by location",
        "description": "The same as [`/attraction/location`](#get-attraction-rates-by-location), including its filters.",
        "parameters": [
          {
            "name": "location",
            "in": "query",
            "description": "Environment slug, e.g. `bazaar` or `cursed_city`.",
            "style": "form",
            "explode": true,
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "minLength": 1
              }
            }
          },
          {
            "name": "stage",
            "in": "query",
            "description": "Exact stage name, or `-` for no stage.",
            "style": "form",
            "explode": true,
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "minLength": 1
              }
            }
          },
          {
            "name": "cheese",
            "in": "query",
            "description": "Cheese type slug.",
            "style": "form",
            "explode": true,
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "minLength": 1
              }
            }
          },
          {
            "name": "charm",
            "in": "query",
            "description": "Charm type slug, or `-` for no charm.",
            "style": "form",
            "explode": true,
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "minLength": 1
              }
            }
          },
          {
            "name": "mouse",
            "in": "query",
            "description": "Mouse type slug.",
            "style": "form",
            "explode": true,
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "minLength": 1
              }
            }
          },
          {
            "name": "v",
            "in": "query",
            "description": "Optional cache token; not a filter.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Location → stage → cheese → charm → mouse → percentage.",
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Keyed by location.",
                  "additionalProperties": {
                    "type": "object",
                    "description": "Keyed by stage.",
                    "additionalProperties": {
                      "type": "object",
                      "description": "Keyed by cheese.",
                      "additionalProperties": {
                        "type": "object",
                        "description": "Keyed by charm.",
                        "additionalProperties": {
                          "type": "object",
                          "description": "Keyed by mouse.",
                          "additionalProperties": {
                            "type": "number",
                            "minimum": 0,
                            "maximum": 100
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "304": {
            "description": "Unchanged response (If-None-Match)."
          },
          "400": {
            "$ref": "#/components/responses/InvalidQuery"
          },
          "503": {
            "description": "Attraction dataset unavailable."
          }
        },
        "tags": [
          "Attraction"
        ]
      }
    },
    "/items": {
      "get": {
        "summary": "Get all items",
        "parameters": [
          {
            "$ref": "#/components/parameters/CollectionQuery"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/ItemCollection"
          },
          "400": {
            "$ref": "#/components/responses/InvalidQuery"
          }
        },
        "tags": [
          "Items"
        ],
        "description": "> This endpoint supports filtering, searching, sorting, pagination, and\n> field selection via query parameters — see\n> [Search & Querying](/search#query-parameters).",
        "x-example": "/items",
        "x-nav": "All items"
      }
    },
    "/items/{id}": {
      "get": {
        "summary": "Get item by ID",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/CollectionQuery"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/Item"
          },
          "400": {
            "$ref": "#/components/responses/InvalidQuery"
          },
          "404": {
            "description": "Item not found"
          }
        },
        "tags": [
          "Items"
        ],
        "x-example": "/items/power_trinket",
        "x-nav": "Item by ID/name"
      }
    },
    "/mice": {
      "get": {
        "summary": "Get all mice",
        "parameters": [
          {
            "$ref": "#/components/parameters/CollectionQuery"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/MouseCollection"
          },
          "400": {
            "$ref": "#/components/responses/InvalidQuery"
          }
        },
        "tags": [
          "Mice"
        ],
        "description": "> This endpoint supports filtering, searching, sorting, pagination, and\n> field selection via query parameters — see\n> [Search & Querying](/search#query-parameters).",
        "x-example": "/mice",
        "x-nav": "All mice"
      }
    },
    "/mice/{id}": {
      "get": {
        "summary": "Get mouse by ID",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/CollectionQuery"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/Mouse"
          },
          "400": {
            "$ref": "#/components/responses/InvalidQuery"
          },
          "404": {
            "description": "Mouse not found"
          }
        },
        "tags": [
          "Mice"
        ],
        "x-example": "/mice/glazed",
        "x-nav": "Mouse by ID/name"
      }
    },
    "/search": {
      "get": {
        "summary": "Search",
        "parameters": [
          {
            "$ref": "#/components/parameters/SearchQuery"
          },
          {
            "$ref": "#/components/parameters/SearchTypes"
          },
          {
            "$ref": "#/components/parameters/SearchLimit"
          }
        ],
        "responses": {
          "200": {
            "description": "Relevance-ranked compact results",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "integer",
                      "description": "Item or mouse ID, or a location's numeric environment ID."
                    },
                    "type": {
                      "type": "string",
                      "description": "Item or mouse type, or location slug (its `id` in `/environments`)."
                    },
                    "name": {
                      "type": "string",
                      "description": "Item, mouse, or location name."
                    },
                    "resource": {
                      "type": "string",
                      "description": "`item`, `location`, or `mouse`."
                    },
                    "image": {
                      "type": "string",
                      "description": "Thumbnail image URL, if available."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidQuery"
          }
        },
        "tags": [
          "Search & Querying"
        ],
        "description": "Searches items, mice, and locations at once. Exact matches (a name, a mouse's short name, or a type) rank first, then items whose abbreviation is the whole query (see `/item-abbreviations`, so `sb` finds SUPER|brie+), then prefix matches, then partial matches. A term shared by more than four items names a group (`charm`, `hal`), so its items come after the name matches.",
        "x-example": "/search?q=snow&limit=3",
        "x-nav": "Search"
      }
    },
    "/catch-rate": {
      "get": {
        "summary": "Get catch rates",
        "description": "The chance a trap catches a mouse, using the community's catch rate formula:\n\n`catch rate = min(1, (E·P + 2·⌊min(E, 1.4)·L⌋²) / (E·P + M))`\n\nwhere E is the trap's effectiveness against the mouse (1 = 100%), P the trap's power, L its luck, and M the mouse's power.\n\nPass your trap's total `power` and `luck` (as shown in game) and its `power_type`, then either:\n\n- `mouse` for one mouse,\n- `mice` (comma-separated) for several, or\n- `location` and `cheese` (plus `stage`, `charm`, and `source` if more than one setup matches) for every mouse that setup attracts, with an `overall_catch_rate` weighted by attraction rate.\n\n> Effectiveness and mouse power come from community data, so treat the results as estimates.",
        "tags": [
          "Catch Rate"
        ],
        "parameters": [
          {
            "name": "power_type",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "example": "hydro"
            },
            "description": "The trap's power type, e.g. `hydro` (see `/power-types`)."
          },
          {
            "name": "power",
            "in": "query",
            "required": true,
            "schema": {
              "type": "number",
              "minimum": 0
            },
            "description": "The trap's total power."
          },
          {
            "name": "luck",
            "in": "query",
            "schema": {
              "type": "number",
              "minimum": 0,
              "default": 0
            },
            "description": "The trap's total luck."
          },
          {
            "name": "mouse",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "A mouse ID or type."
          },
          {
            "name": "mice",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Comma-separated mouse IDs or types."
          },
          {
            "name": "location",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "A location slug, to rate everything a setup attracts (see `/attraction`). Needs `cheese`."
          },
          {
            "name": "cheese",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "With `location`: the cheese type."
          },
          {
            "name": "stage",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "With `location`: the stage, if the location has more than one."
          },
          {
            "name": "charm",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "-"
            },
            "description": "With `location`: the charm type. Defaults to `-` (none)."
          },
          {
            "name": "source",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "With `location`: `mh-tools` or `mhct`, if both have the setup."
          }
        ],
        "responses": {
          "200": {
            "description": "Catch rates. One mouse's fields are at the top level; with `mice` or `location` they're in `mice`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "power_type": {
                      "type": "string",
                      "description": "The power type used."
                    },
                    "power": {
                      "type": "number",
                      "description": "The trap power used."
                    },
                    "luck": {
                      "type": "number",
                      "description": "The trap luck used."
                    },
                    "mouse": {
                      "type": "object",
                      "description": "The mouse's `id`, `type`, and `name`."
                    },
                    "effectiveness": {
                      "type": "integer",
                      "description": "The power type's effectiveness against the mouse, as a percentage (`0` means it can't be caught)."
                    },
                    "mouse_power": {
                      "type": "number",
                      "description": "The mouse's power."
                    },
                    "catch_rate": {
                      "type": "number",
                      "description": "The chance of catching the mouse, from `0` to `1`."
                    },
                    "minluck": {
                      "type": "integer",
                      "description": "The luck that catches the mouse every time with this power type, or `null` if it can't be caught."
                    },
                    "guaranteed": {
                      "type": "boolean",
                      "description": "Whether `luck` is at least the minluck."
                    },
                    "attraction_rate": {
                      "type": "number",
                      "description": "With `location`: how often the setup attracts the mouse, as a percentage."
                    },
                    "setup": {
                      "type": "object",
                      "description": "With `location`: the attraction setup used (`location`, `stage`, `cheese`, `charm`, `source`, `sample_size`)."
                    },
                    "overall_catch_rate": {
                      "type": "number",
                      "description": "With `location`: the chance of catching whatever the setup attracts, from `0` to `1`."
                    },
                    "mice": {
                      "type": "array",
                      "description": "With `mice` or `location`: one entry per mouse.",
                      "items": {
                        "type": "object",
                        "properties": {
                          "mouse": {
                            "type": "object",
                            "description": "The mouse's `id`, `type`, and `name`."
                          },
                          "effectiveness": {
                            "type": "integer",
                            "description": "The power type's effectiveness against the mouse, as a percentage (`0` means it can't be caught)."
                          },
                          "mouse_power": {
                            "type": "number",
                            "description": "The mouse's power."
                          },
                          "catch_rate": {
                            "type": "number",
                            "description": "The chance of catching the mouse, from `0` to `1`."
                          },
                          "minluck": {
                            "type": "integer",
                            "description": "The luck that catches the mouse every time with this power type, or `null` if it can't be caught."
                          },
                          "guaranteed": {
                            "type": "boolean",
                            "description": "Whether `luck` is at least the minluck."
                          },
                          "attraction_rate": {
                            "type": "number",
                            "description": "With `location`: how often the setup attracts the mouse, as a percentage."
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidQuery"
          },
          "404": {
            "description": "Unknown mouse, or no attraction setup matches"
          }
        },
        "x-example": "/catch-rate?mouse=abominable_snow&power=1000&luck=10&power_type=hydro",
        "x-nav": "Catch rates"
      }
    },
    "/items/facets": {
      "get": {
        "summary": "Get item facets",
        "responses": {
          "200": {
            "$ref": "#/components/responses/Facets"
          }
        },
        "tags": [
          "Search & Querying"
        ],
        "description": "The available item filter values and how many items match each, covering `classification`, `is_tradable`, and `tags`.",
        "x-example": "/items/facets",
        "x-nav": "Item facets"
      }
    },
    "/mice/facets": {
      "get": {
        "summary": "Get mouse facets",
        "responses": {
          "200": {
            "$ref": "#/components/responses/Facets"
          }
        },
        "tags": [
          "Search & Querying"
        ],
        "description": "The available mouse filter values and how many mice match each, covering `group`, `subgroup`, and `weakness`.",
        "x-example": "/mice/facets",
        "x-nav": "Mouse facets"
      }
    },
    "/status": {
      "get": {
        "summary": "Get API status",
        "responses": {
          "200": {
            "description": "API status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Status"
                }
              }
            }
          }
        },
        "tags": [
          "Versions"
        ],
        "description": "Whether the API is up, which query features it supports, and the record count and version of the main datasets.",
        "x-example": "/status",
        "x-nav": "API status"
      }
    },
    "/mouse-loot/{id}": {
      "get": {
        "summary": "Get a mouse's loot",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "responses": {
          "200": {
            "description": "Loot rows; empty for a known mouse without enough data",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/MouseLoot"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Mouse not found"
          }
        },
        "tags": [
          "Loot"
        ],
        "description": "The mouse's most-caught location first, and the most likely drops first within it.",
        "x-example": "/mouse-loot/thunderlord",
        "x-nav": "A mouse's loot"
      }
    },
    "/mouse-loot/parts/{part}": {
      "get": {
        "summary": "Get a part of the mouse loot data",
        "description": "All mouse loot, split by mouse ID into 16 parts. Each part maps mouse IDs to the same rows as `/mouse-loot/{id}`.",
        "parameters": [
          {
            "name": "part",
            "in": "path",
            "required": true,
            "description": "1 to 16",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 16
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Rows keyed by mouse ID",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/MouseLoot"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not a part from 1 to 16"
          }
        },
        "tags": [
          "Loot"
        ],
        "x-example": "/mouse-loot/parts/1",
        "x-nav": "All mouse loot, in parts"
      }
    },
    "/item-droppers/{id}": {
      "get": {
        "summary": "Get the mice that drop an item",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "responses": {
          "200": {
            "description": "Dropper rows; empty for a known item without enough data",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ItemDropper"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Item not found"
          }
        },
        "tags": [
          "Loot"
        ],
        "description": "The most likely droppers first.",
        "x-example": "/item-droppers/dragon_scale_crafting_item",
        "x-nav": "Mice that drop an item"
      }
    },
    "/item-droppers/parts/{part}": {
      "get": {
        "summary": "Get a part of the item dropper data",
        "description": "All item droppers, split by item ID into 16 parts. Each part maps item IDs to the same rows as `/item-droppers/{id}`.",
        "parameters": [
          {
            "name": "part",
            "in": "path",
            "required": true,
            "description": "1 to 16",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 16
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Rows keyed by item ID",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/ItemDropper"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not a part from 1 to 16"
          }
        },
        "tags": [
          "Loot"
        ],
        "x-example": "/item-droppers/parts/1",
        "x-nav": "All item droppers, in parts"
      }
    },
    "/mice-powertype-mastery/{id}": {
      "get": {
        "summary": "Get power type mastery for a power type or mouse",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Power type (e.g. arcane), or a mouse's numeric ID or type slug."
          }
        ],
        "responses": {
          "200": {
            "description": "An array of mouse type slugs for a power type, or a mouse's id, type and power_type"
          },
          "404": {
            "description": "Power type or mouse not found"
          }
        },
        "tags": [
          "Mice"
        ],
        "description": "Pass a power type (e.g. `arcane`) to get its mice, or a mouse's ID or type to get the power type it counts toward.",
        "x-example": "/mice-powertype-mastery/thunderlord"
      }
    },
    "/titles": {
      "get": {
        "summary": "Get all titles",
        "parameters": [
          {
            "$ref": "#/components/parameters/CollectionQuery"
          }
        ],
        "responses": {
          "200": {
            "description": "List and query hunter titles",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Title"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidQuery"
          }
        },
        "tags": [
          "Titles"
        ],
        "description": "> Supports filtering, searching, sorting, pagination, and field selection. See [Search & Querying](/search#query-parameters).",
        "x-example": "/titles",
        "x-nav": "Titles"
      }
    },
    "/titles/{id}": {
      "get": {
        "summary": "Get a title",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Title type slug (e.g. master) or the game's numeric title ID."
          },
          {
            "$ref": "#/components/parameters/CollectionQuery"
          }
        ],
        "responses": {
          "200": {
            "description": "Get a title by type slug or game title ID",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Title"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidQuery"
          },
          "404": {
            "description": "Not found"
          }
        },
        "tags": [
          "Titles"
        ],
        "description": "Accepts a title type (`master`) or the game's numeric title ID (`14`).",
        "x-example": "/titles/master"
      }
    },
    "/power-types": {
      "get": {
        "summary": "Get all power types",
        "parameters": [
          {
            "$ref": "#/components/parameters/CollectionQuery"
          }
        ],
        "responses": {
          "200": {
            "description": "List power types",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/PowerType"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidQuery"
          }
        },
        "tags": [
          "Power Types"
        ],
        "x-example": "/power-types",
        "x-nav": "Power types"
      }
    },
    "/power-types/{id}": {
      "get": {
        "summary": "Get a power type",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Name slug (e.g. hydro) or game code (e.g. hdr)."
          },
          {
            "$ref": "#/components/parameters/CollectionQuery"
          }
        ],
        "responses": {
          "200": {
            "description": "Get a power type",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PowerType"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidQuery"
          },
          "404": {
            "description": "Not found"
          }
        },
        "tags": [
          "Power Types"
        ],
        "description": "Accepts the name (`hydro`) or the game code (`hdr`).",
        "x-example": "/power-types/hdr"
      }
    },
    "/scoreboards": {
      "get": {
        "summary": "Get all scoreboards",
        "parameters": [
          {
            "$ref": "#/components/parameters/CollectionQuery"
          }
        ],
        "responses": {
          "200": {
            "description": "List and query scoreboards",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Scoreboard"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidQuery"
          }
        },
        "tags": [
          "Scoreboards"
        ],
        "description": "> Supports filtering, searching, sorting, pagination, and field selection. See [Search & Querying](/search#query-parameters).",
        "x-example": "/scoreboards?group=General",
        "x-nav": "Scoreboards"
      }
    },
    "/scoreboards/{id}": {
      "get": {
        "summary": "Get a scoreboard",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Scoreboard ID."
          },
          {
            "$ref": "#/components/parameters/CollectionQuery"
          }
        ],
        "responses": {
          "200": {
            "description": "Get a scoreboard",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Scoreboard"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidQuery"
          },
          "404": {
            "description": "Not found"
          }
        },
        "tags": [
          "Scoreboards"
        ],
        "description": "Accepts a scoreboard ID.",
        "x-example": "/scoreboards/gold"
      }
    },
    "/recipes": {
      "get": {
        "summary": "Get all recipes",
        "description": "> Supports filtering, searching, sorting, pagination, and field selection. See [Search & Querying](/search#query-parameters).",
        "parameters": [
          {
            "$ref": "#/components/parameters/CollectionQuery"
          }
        ],
        "responses": {
          "200": {
            "description": "List and query crafting recipes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Recipe"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidQuery"
          }
        },
        "tags": [
          "Recipes"
        ],
        "x-example": "/recipes?status=active&limit=1",
        "x-nav": "Recipes"
      }
    },
    "/recipes/{id}": {
      "get": {
        "summary": "Get recipes by recipe or item",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Recipe type, or the numeric ID or type of the item it makes."
          },
          {
            "$ref": "#/components/parameters/CollectionQuery"
          }
        ],
        "responses": {
          "200": {
            "description": "Get the recipes with a type, or that make an item",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Recipe"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidQuery"
          }
        },
        "tags": [
          "Recipes"
        ],
        "description": "Accepts a recipe type, or the ID or type of the item a recipe makes, and returns every matching recipe.",
        "x-example": "/recipes/ancient_cheese"
      }
    },
    "/store": {
      "get": {
        "summary": "Get all store packs",
        "description": "> Supports filtering, searching, sorting, pagination, and field selection. See [Search & Querying](/search#query-parameters).",
        "parameters": [
          {
            "$ref": "#/components/parameters/CollectionQuery"
          }
        ],
        "responses": {
          "200": {
            "description": "List and query SUPER|brie+ store packs",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/StorePack"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidQuery"
          }
        },
        "tags": [
          "Store"
        ],
        "x-example": "/store?items.type=super_brie_cheese&limit=1",
        "x-nav": "Store"
      }
    },
    "/store/{id}": {
      "get": {
        "summary": "Get a store pack",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Pack type or an app store SKU."
          },
          {
            "$ref": "#/components/parameters/CollectionQuery"
          }
        ],
        "responses": {
          "200": {
            "description": "Get a store pack",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StorePack"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidQuery"
          },
          "404": {
            "description": "Not found"
          }
        },
        "tags": [
          "Store"
        ],
        "description": "Accepts a pack type or either store's SKU.",
        "x-example": "/store/icy_rhinobot_skin"
      }
    },
    "/shops": {
      "get": {
        "summary": "Get all shops",
        "description": "Filters narrow both the shops and their items; shops left with no items are dropped.",
        "parameters": [
          {
            "name": "location",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Location type. Comma-separated or repeated."
          },
          {
            "name": "item",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "ID or type of an item the shop sells. Comma-separated or repeated."
          },
          {
            "name": "cost",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "ID or type of an item used to pay. Comma-separated or repeated."
          },
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Shop tab, e.g. `bait`, `weapon`, `map_piece`. Comma-separated or repeated."
          },
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Partial item name or type."
          }
        ],
        "responses": {
          "200": {
            "description": "Shops",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Shop"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidQuery"
          }
        },
        "tags": [
          "Shops"
        ],
        "x-example": "/shops?item=sky_cheese",
        "x-nav": "Shops"
      }
    },
    "/shops/{id}": {
      "get": {
        "summary": "Get a location's shop",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Location type."
          },
          {
            "name": "item",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "ID or type of an item the shop sells. Comma-separated or repeated."
          },
          {
            "name": "cost",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "ID or type of an item used to pay. Comma-separated or repeated."
          },
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Shop tab, e.g. `bait`, `weapon`, `map_piece`. Comma-separated or repeated."
          },
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Partial item name or type."
          }
        ],
        "responses": {
          "200": {
            "description": "Shop",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Shop"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidQuery"
          },
          "404": {
            "description": "Location not found, or no items match"
          }
        },
        "tags": [
          "Shops"
        ],
        "description": "Accepts a location type. Takes the same filters as `/shops`, which narrow the shop's items. Returns `404` for an unknown location, or when the filters match no items.",
        "x-example": "/shops/floating_islands"
      }
    },
    "/versions": {
      "get": {
        "summary": "Get data versions",
        "responses": {
          "200": {
            "description": "Version hash by data file",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "[name]": {
                      "type": "string",
                      "description": "Keyed by data file name, such as `mice`. The hash of that file's current contents."
                    }
                  }
                }
              }
            }
          }
        },
        "tags": [
          "Versions"
        ],
        "description": "A short hash for every data file, keyed by name (`mice`, `items`, `environments`, and so on). A hash changes only when its file does. Responses are cached for five minutes.",
        "x-example": "/versions",
        "x-nav": "Data versions"
      }
    },
    "/mhct/{id}": {
      "get": {
        "summary": "Get mouse attraction rates",
        "description": "Live attraction rates for a mouse, by location, stage, and cheese. Replace `:id` with the mouse type or ID.\n\nAppend a time filter to the ID, e.g. `/mhct/948-3_months` or `/mhct/948-hlwn_22`; the default is `all_time`, and [`/mhct/filters`](#get-time-filters) lists them all. Unknown IDs and mice with no data return an empty array.",
        "tags": [
          "MHCT"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Mouse ID or type, optionally followed by an MHCT time filter, e.g. `948-3_months` or `948-hlwn_22`. Defaults to all time."
          }
        ],
        "responses": {
          "200": {
            "description": "Mouse attraction rates from MHCT",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "location": {
                        "type": "string",
                        "description": "Location name."
                      },
                      "stage": {
                        "type": "string",
                        "description": "Location stage, or `null` when not applicable."
                      },
                      "cheese": {
                        "type": "string",
                        "description": "Cheese used."
                      },
                      "total_hunts": {
                        "type": "integer",
                        "description": "Number of hunts the rate is based on."
                      },
                      "rate": {
                        "type": "integer",
                        "description": "Attraction rate out of 10,000 (divide by 100 for a percentage)."
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-example": "/mhct/948",
        "x-example-response": "[\n  {\n    \"location\": \"Prickly Plains\",\n    \"stage\": null,\n    \"total_hunts\": 12500,\n    \"rate\": 10000,\n    \"cheese\": \"Flamin' Queso\"\n  }\n]",
        "x-nav": "Mouse attraction rates"
      }
    },
    "/mhct/item/{id}": {
      "get": {
        "summary": "Get item drop rates",
        "description": "Live drop rates for an item, by location, stage, and cheese. Replace `:id` with the item type or ID.\n\nAppend a time filter to the ID as with [mouse attraction rates](#get-mouse-attraction-rates), e.g. `/mhct/item/3058-3_months`. The default is `all_time`.",
        "tags": [
          "MHCT"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Item ID or type, optionally followed by an MHCT time filter, e.g. `114-1_month`."
          }
        ],
        "responses": {
          "200": {
            "description": "Item drop rates from MHCT",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "location": {
                        "type": "string",
                        "description": "Location name."
                      },
                      "stage": {
                        "type": "string",
                        "description": "Location stage, or `null` when not applicable."
                      },
                      "cheese": {
                        "type": "string",
                        "description": "Cheese used."
                      },
                      "total_hunts": {
                        "type": "integer",
                        "description": "Number of hunts the rate is based on."
                      },
                      "total_catches": {
                        "type": "integer",
                        "description": "Number of catches in the sample."
                      },
                      "total_drops": {
                        "type": "integer",
                        "description": "Number of drops in the sample."
                      },
                      "drop_pct": {
                        "type": "string",
                        "description": "Drop rate as a percentage."
                      },
                      "min_amt": {
                        "type": "integer",
                        "description": "Minimum quantity dropped."
                      },
                      "max_amt": {
                        "type": "integer",
                        "description": "Maximum quantity dropped."
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-example": "/mhct/item/3058",
        "x-example-response": "[\n  {\n    \"location\": \"Floating Islands\",\n    \"stage\": \"Low Tier Loot\",\n    \"cheese\": \"Cloudy Cheesecake\",\n    \"total_hunts\": 8000,\n    \"total_catches\": 6200,\n    \"total_drops\": 1240,\n    \"drop_pct\": \"20.00\",\n    \"min_amt\": 1,\n    \"max_amt\": 3\n  }\n]",
        "x-nav": "Item drop rates"
      }
    },
    "/mhct/redirect/{id}": {
      "get": {
        "summary": "MHCT mouse redirect",
        "description": "An HTML page that redirects to the mouse's attraction page on [mhct.win](https://mhct.win/), not JSON. Replace `:id` with the mouse type or ID; the time filter suffix works here too, e.g. `/mhct/redirect/948-3_months`.",
        "tags": [
          "MHCT"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Mouse ID or type, optionally followed by an MHCT time filter, e.g. `948-3_months` or `948-hlwn_22`. Defaults to all time."
          }
        ],
        "responses": {
          "200": {
            "description": "Redirect to a mouse on MHCT",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-example": "/mhct/redirect/948",
        "x-nav": "Redirects"
      }
    },
    "/mhct/redirect/item/{id}": {
      "get": {
        "summary": "Redirect to an item on MHCT",
        "description": "An HTML page that redirects to the item's loot page on [mhct.win](https://mhct.win/), not JSON. Replace `:id` with the item type or ID; the time filter suffix works here too.",
        "tags": [
          "MHCT"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Item ID or type, optionally followed by an MHCT time filter, e.g. `114-1_month`."
          }
        ],
        "responses": {
          "200": {
            "description": "Redirect to an item on MHCT",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-example": "/mhct/redirect/item/3058"
      }
    },
    "/mhct/convertibles/{id}": {
      "get": {
        "summary": "Get convertible contents",
        "description": "The possible rewards (and odds) from opening a convertible item. Replace `:id` with the item type or ID.",
        "tags": [
          "MHCT"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Item ID or type."
          }
        ],
        "responses": {
          "200": {
            "description": "What a convertible contains",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "integer",
                        "description": "Reward item ID (`0` if unknown)."
                      },
                      "name": {
                        "type": "string",
                        "description": "Reward item name."
                      },
                      "min": {
                        "type": "integer",
                        "description": "Minimum quantity awarded."
                      },
                      "max": {
                        "type": "integer",
                        "description": "Maximum quantity awarded."
                      },
                      "chance": {
                        "type": "string",
                        "description": "Chance of receiving the reward, as a percentage."
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-example": "/mhct/convertibles/super_brie_cheese",
        "x-example-response": "[\n  {\n    \"id\": 114,\n    \"name\": \"SUPER|brie+\",\n    \"min\": 70,\n    \"max\": 70,\n    \"chance\": \"100.00\"\n  }\n]",
        "x-nav": "Convertible contents"
      }
    },
    "/mhct/convertible-sources/{id}": {
      "get": {
        "summary": "Get where an item comes from in convertibles",
        "description": "The convertibles (chests, bags, eggs, and so on) that can contain an item, most likely first. The reverse of [convertible contents](#get-convertible-contents). Replace `:id` with the item type or ID. Retired convertibles are left out unless `include_retired=true`. Known items with no sources return an empty array.",
        "tags": [
          "MHCT"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Item ID or type."
          },
          {
            "name": "include_retired",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            },
            "description": "Include retired content: maps and items MHCT marks `(Retired)`, and items the game marks `inactive` or `removed`. Left out by default."
          }
        ],
        "responses": {
          "200": {
            "description": "Convertibles containing the item",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "integer",
                        "description": "The convertible's item ID, or `null` if it isn't in `/items`."
                      },
                      "type": {
                        "type": "string",
                        "description": "The convertible's item type, or `null`."
                      },
                      "name": {
                        "type": "string",
                        "description": "The convertible's name, as MHCT has it."
                      },
                      "chance": {
                        "type": "number",
                        "description": "Chance an opening contains the item, as a percentage."
                      },
                      "min": {
                        "type": "integer",
                        "description": "Minimum quantity when it does."
                      },
                      "max": {
                        "type": "integer",
                        "description": "Maximum quantity when it does."
                      },
                      "single_opens": {
                        "type": "integer",
                        "description": "Number of single openings sampled."
                      },
                      "retired": {
                        "type": "boolean",
                        "description": "Whether the convertible is retired. Only `true` with `include_retired=true`."
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Item not found"
          }
        },
        "x-example": "/mhct/convertible-sources/dragonbane_potion",
        "x-nav": "Convertible sources"
      }
    },
    "/mhct/map/{id}": {
      "get": {
        "summary": "Get the mice on a map",
        "description": "The mice on one treasure map (or, for a Scavenger Hunt, the items), with how often each appears. Replace `:id` with the MHCT map ID, the map's name, or its slug (e.g. `rare_map`). Updated weekly.",
        "tags": [
          "MHCT"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "MHCT map ID, map name, or name slug."
          }
        ],
        "responses": {
          "200": {
            "description": "The map",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "mhct_id": {
                      "type": "integer",
                      "description": "MHCT map ID."
                    },
                    "name": {
                      "type": "string",
                      "description": "Map name."
                    },
                    "mice": {
                      "type": "array",
                      "description": "Mice on the map, each with `id`, `type`, `name`, `rate` (out of 10,000), `seen`, and `total`."
                    },
                    "items": {
                      "type": "array",
                      "description": "For a Scavenger Hunt, the items on it instead of mice, with the same fields."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Map not found"
          }
        },
        "x-example": "/mhct/map/10th_birthday_event_map",
        "x-nav": "Mice on a map"
      }
    },
    "/mhct/ids": {
      "get": {
        "summary": "Get MHCT IDs",
        "description": "Everything MHCT tracks, keyed by MHCT item type, with the game's ID and type where the name matches. The types are `mouse` (attraction), `mousemaps` (map objectives, including Scavenger Hunt items), `loot`, `convertible`, `itemconvertibles` (items that come out of convertibles), and `map`. Updated weekly.",
        "tags": [
          "MHCT"
        ],
        "responses": {
          "200": {
            "description": "Each MHCT item type's list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "mhct_id": {
                          "type": "integer",
                          "description": "MHCT's ID. For mice and maps, MHCT numbers them itself; for items, it's usually the game's item ID."
                        },
                        "name": {
                          "type": "string",
                          "description": "The name MHCT uses."
                        },
                        "kind": {
                          "type": "string",
                          "description": "`mouse`, `item`, or `map`."
                        },
                        "id": {
                          "type": "integer",
                          "description": "The game's ID, or `null` if the name doesn't match anything in `/mice` or `/items` (maps never have one)."
                        },
                        "type": {
                          "type": "string",
                          "description": "The game's type (slug), or `null`."
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-example": "/mhct/ids",
        "x-nav": "MHCT IDs"
      }
    },
    "/mhct/ids/{type}": {
      "get": {
        "summary": "Get MHCT IDs for one item type",
        "description": "One of the lists from `/mhct/ids`. Replace `:type` with `mouse`, `mousemaps`, `loot`, `convertible`, `itemconvertibles`, or `map`.",
        "tags": [
          "MHCT"
        ],
        "parameters": [
          {
            "name": "type",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "mouse",
                "mousemaps",
                "loot",
                "convertible",
                "itemconvertibles",
                "map"
              ]
            },
            "description": "MHCT item type."
          }
        ],
        "responses": {
          "200": {
            "description": "The list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "mhct_id": {
                        "type": "integer",
                        "description": "MHCT's ID. For mice and maps, MHCT numbers them itself; for items, it's usually the game's item ID."
                      },
                      "name": {
                        "type": "string",
                        "description": "The name MHCT uses."
                      },
                      "kind": {
                        "type": "string",
                        "description": "`mouse`, `item`, or `map`."
                      },
                      "id": {
                        "type": "integer",
                        "description": "The game's ID, or `null` if the name doesn't match anything in `/mice` or `/items` (maps never have one)."
                      },
                      "type": {
                        "type": "string",
                        "description": "The game's type (slug), or `null`."
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Unknown item type"
          }
        },
        "x-example": "/mhct/ids/loot",
        "x-nav": "MHCT IDs by type"
      }
    },
    "/mhct/filters": {
      "get": {
        "summary": "Get time filters",
        "description": "The time filters MHCT offers, for the `-filter` suffix on [mouse attraction rates](#get-mouse-attraction-rates) and [item drop rates](#get-item-drop-rates), newest event first. `rolling` filters cover a recent window and keep changing; `event` filters cover a past event. Updated weekly.",
        "tags": [
          "MHCT"
        ],
        "responses": {
          "200": {
            "description": "MHCT time filters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "string",
                        "description": "The filter, e.g. `hlwn_25`."
                      },
                      "name": {
                        "type": "string",
                        "description": "Its name on MHCT, e.g. `Halloween 2025`."
                      },
                      "kind": {
                        "type": "string",
                        "description": "`all_time`, `rolling`, or `event`."
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-example": "/mhct/filters",
        "x-nav": "Time filters"
      }
    },
    "/map/mouse/{id}": {
      "get": {
        "summary": "Get maps for a mouse",
        "description": "The treasure maps a mouse can appear on, from [MHCT](https://mhct.win/). Only maps where the mouse was seen at least 5 times are returned, and retired maps are left out unless `include_retired=true`. Replace `:id` with the mouse type or ID.",
        "tags": [
          "Maps"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Mouse ID or type."
          },
          {
            "name": "include_retired",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            },
            "description": "Include retired content: maps and items MHCT marks `(Retired)`, and items the game marks `inactive` or `removed`. Left out by default."
          }
        ],
        "responses": {
          "200": {
            "description": "Treasure maps a mouse appears on",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "map": {
                        "type": "string",
                        "description": "Map name."
                      },
                      "rate": {
                        "type": "integer",
                        "description": "Appearance rate out of 10,000 (divide by 100 for a percentage)."
                      },
                      "seen_maps": {
                        "type": "integer",
                        "description": "Number of sampled maps the mouse was seen on."
                      },
                      "total_maps": {
                        "type": "integer",
                        "description": "Total number of sampled maps."
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-example": "/map/mouse/948",
        "x-example-response": "[\n  {\n    \"map\": \"Prickly Plains Map\",\n    \"rate\": 5000,\n    \"seen_maps\": 120,\n    \"total_maps\": 240\n  }\n]",
        "x-nav": "Maps for a mouse"
      }
    },
    "/map/relations": {
      "get": {
        "summary": "Get map relations",
        "tags": [
          "Maps"
        ],
        "responses": {
          "200": {
            "description": "Scroll cases, the maps they open, and the chests they award",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "scrollCase": {
                        "type": "object",
                        "description": "The scroll case, with `id`, `type`, and `name`."
                      },
                      "map": {
                        "type": "object",
                        "description": "The map the scroll case opens into, with `name` and `mhctId`."
                      },
                      "chests": {
                        "type": "array",
                        "description": "The treasure chests the map awards, each with `id`, `type`, `name`, and `rare`."
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "description": "Every scroll case, the treasure map it opens into, and the chests that map awards. For one scroll case, map, or chest, use `/map/relations/:id`.",
        "x-example": "/map/relations/chrome_scroll_case_convertible",
        "x-nav": "Map relations"
      }
    },
    "/map/relations/{id}": {
      "get": {
        "summary": "Map relations for one scroll case, map or chest",
        "description": "Accepts a scroll case or chest type or item ID, a map's MHCT ID, or a map name or slug.",
        "tags": [
          "Maps"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Scroll case, chest, or map."
          }
        ],
        "responses": {
          "200": {
            "description": "Map relations for one scroll case, map or chest",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array"
                }
              }
            }
          }
        },
        "x-example": "/map/relations/easy_map"
      }
    },
    "/potions": {
      "get": {
        "summary": "Get all potions",
        "tags": [
          "Potions"
        ],
        "responses": {
          "200": {
            "description": "Potion recipes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "integer",
                        "description": "Potion item ID."
                      },
                      "type": {
                        "type": "string",
                        "description": "Potion item type (slug)."
                      },
                      "name": {
                        "type": "string",
                        "description": "Potion name."
                      },
                      "image": {
                        "type": "string",
                        "description": "Potion image URL."
                      },
                      "recipes": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "input": {
                              "type": "object",
                              "description": "The item consumed: `id`, `type`, `name`, and `quantity`."
                            },
                            "output": {
                              "type": "object",
                              "description": "The item produced: `id`, `type`, `name`, and `quantity`."
                            },
                            "gold_cost": {
                              "type": "integer",
                              "description": "Gold cost to brew this recipe."
                            },
                            "title_required": {
                              "type": "string",
                              "description": "Minimum hunter title for this recipe, e.g. `novice` or `lord_lady`."
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-example": "/potions",
        "x-nav": "Potions"
      }
    },
    "/potions/{id}": {
      "get": {
        "summary": "Get potions by ID",
        "description": "Replace `:id` with a potion's ID or type, or the ID or type of an item a potion uses or makes. Returns an array of matching potions in the same shape as [`/potions`](#get-all-potions), empty when nothing matches.",
        "tags": [
          "Potions"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Item ID or type."
          }
        ],
        "responses": {
          "200": {
            "description": "Potions by potion or ingredient",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array"
                }
              }
            }
          }
        },
        "x-example": "/potions/brie_cheese_potion",
        "x-nav": "Potions by item"
      }
    },
    "/mice-powertype-mastery": {
      "get": {
        "summary": "Get power type mastery mice",
        "tags": [
          "Mice"
        ],
        "responses": {
          "200": {
            "description": "Mice counted toward each power type's mastery",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        },
        "description": "Mouse types (slugs) that count toward each power type's mastery, keyed by power type.",
        "x-example": "/mice-powertype-mastery",
        "x-nav": "Power type mastery"
      }
    },
    "/relic-hunter": {
      "get": {
        "summary": "Get Relic Hunter location",
        "description": "The Relic Hunter's current location, from [MHCT](https://mhct.win). If MHCT reports a location this API doesn't know, or can't be reached, the response is `{ \"id\": \"unknown\", \"name\": \"Unknown\", \"last_seen\": … }`.",
        "tags": [
          "Relic Hunter"
        ],
        "responses": {
          "200": {
            "description": "The Relic Hunter's current location",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "The environment ID."
                    },
                    "name": {
                      "type": "string",
                      "description": "The environment name."
                    },
                    "article": {
                      "type": "string",
                      "description": "The environment name with article."
                    },
                    "image": {
                      "type": "string",
                      "description": "The environment image."
                    },
                    "headerImage": {
                      "type": "string",
                      "description": "The environment header image."
                    },
                    "region": {
                      "type": "string",
                      "description": "The environment region."
                    },
                    "order": {
                      "type": "integer",
                      "description": "The environment order."
                    },
                    "title": {
                      "type": "string",
                      "description": "The title needed to access the environment."
                    },
                    "last_seen": {
                      "type": "string",
                      "description": "When MHCT last saw the Relic Hunter there, as an ISO 8601 date, or `null`.",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          }
        },
        "x-example": "/relic-hunter",
        "x-example-response": "{\n  \"id\": \"meadow\",\n  \"name\": \"Meadow\",\n  \"article\": \"the Meadow\",\n  \"image\": \"https://www.mousehuntgame.com/images/environments/a441eb078698da69ef2765983f4b5912.jpg\",\n  \"headerImage\": \"https://www.mousehuntgame.com/images/environments/6ef3ffe2f90a79250807b46105e77b68.jpg\",\n  \"region\": \"gnawnia\",\n  \"order\": 10,\n  \"title\": \"novice\",\n  \"last_seen\": \"2026-10-10T19:45:12.000Z\"\n}",
        "x-nav": "Current location"
      }
    },
    "/relic-hunter/history": {
      "get": {
        "summary": "Get Relic Hunter history",
        "description": "When the Relic Hunter was last seen in each location, most recent first. Sightings are recorded at least every two hours; locations it hasn't been seen in since recording started aren't listed.",
        "tags": [
          "Relic Hunter"
        ],
        "responses": {
          "200": {
            "description": "Last sighting in each location",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "string",
                        "description": "The location slug."
                      },
                      "name": {
                        "type": "string",
                        "description": "The location name."
                      },
                      "environment_id": {
                        "type": "integer",
                        "description": "The game's numeric environment ID."
                      },
                      "last_seen": {
                        "type": "string",
                        "description": "When the Relic Hunter was last seen there, as an ISO 8601 date.",
                        "format": "date-time"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-example": "/relic-hunter/history",
        "x-example-response": "[\n  {\n    \"id\": \"meadow\",\n    \"name\": \"Meadow\",\n    \"environment_id\": 18,\n    \"last_seen\": \"2026-10-10T19:45:12.000Z\"\n  },\n  {\n    \"id\": \"harbour\",\n    \"name\": \"Harbour\",\n    \"environment_id\": 1,\n    \"last_seen\": \"2026-10-08T03:12:40.000Z\"\n  }\n]",
        "x-nav": "Location history"
      }
    },
    "/relic-hunter/history/{id}": {
      "get": {
        "summary": "Get when the Relic Hunter was last in a location",
        "description": "The last sighting in one location. Replace `:id` with the location's slug, numeric environment ID, or name. A location it hasn't been seen in since recording started has `last_seen: null`.",
        "tags": [
          "Relic Hunter"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Location slug, numeric environment ID, or name."
          }
        ],
        "responses": {
          "200": {
            "description": "The last sighting",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "The location slug."
                    },
                    "name": {
                      "type": "string",
                      "description": "The location name."
                    },
                    "environment_id": {
                      "type": "integer",
                      "description": "The game's numeric environment ID."
                    },
                    "last_seen": {
                      "type": "string",
                      "description": "When the Relic Hunter was last seen there, as an ISO 8601 date, or `null` if it hasn't been seen there since recording started.",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Location not found"
          }
        },
        "x-example": "/relic-hunter/history/meadow",
        "x-example-response": "{\n  \"id\": \"meadow\",\n  \"name\": \"Meadow\",\n  \"environment_id\": 18,\n  \"last_seen\": \"2026-10-10T19:45:12.000Z\"\n}",
        "x-nav": "Last seen in a location"
      }
    },
    "/timers": {
      "get": {
        "summary": "Get location timers",
        "description": "Every rotating location's current stage and the stages that follow, and the next daily reset.",
        "tags": [
          "Timers"
        ],
        "parameters": [
          {
            "name": "at",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Work the timers out for this time instead of now: an ISO 8601 date or a Unix time in seconds."
          }
        ],
        "responses": {
          "200": {
            "description": "The timers",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "now": {
                      "type": "string",
                      "format": "date-time",
                      "description": "The time the timers were worked out for."
                    },
                    "daily_reset": {
                      "type": "object",
                      "description": "The next daily reset.",
                      "properties": {
                        "at": {
                          "type": "string",
                          "format": "date-time",
                          "description": "When it is: the next midnight UTC."
                        },
                        "in_minutes": {
                          "type": "integer",
                          "description": "Minutes until it, rounded up."
                        }
                      }
                    },
                    "locations": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "The location slug."
                          },
                          "name": {
                            "type": "string",
                            "description": "The location name."
                          },
                          "environment_id": {
                            "type": "integer",
                            "description": "The game's numeric environment ID."
                          },
                          "rotation_minutes": {
                            "type": "integer",
                            "description": "How long one full rotation takes."
                          },
                          "current": {
                            "type": "object",
                            "properties": {
                              "name": {
                                "type": "string",
                                "description": "The stage, e.g. `Low Tide`, `Winter`, or `Count/Countess`."
                              },
                              "note": {
                                "type": "string",
                                "description": "Only for a stage the location passes through twice a rotation: `rising` or `falling`."
                              },
                              "power_type": {
                                "type": "string",
                                "description": "Seasonal Garden only: the power type the season favors."
                              },
                              "starts_at": {
                                "type": "string",
                                "format": "date-time",
                                "description": "When the stage starts."
                              },
                              "ends_at": {
                                "type": "string",
                                "format": "date-time",
                                "description": "When the stage ends."
                              },
                              "starts_in_minutes": {
                                "type": "integer",
                                "description": "Minutes until it starts, rounded up; 0 for the current stage."
                              },
                              "ends_in_minutes": {
                                "type": "integer",
                                "description": "Minutes until it ends, rounded up."
                              }
                            },
                            "description": "The stage the location is in."
                          },
                          "upcoming": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "name": {
                                  "type": "string",
                                  "description": "The stage, e.g. `Low Tide`, `Winter`, or `Count/Countess`."
                                },
                                "note": {
                                  "type": "string",
                                  "description": "Only for a stage the location passes through twice a rotation: `rising` or `falling`."
                                },
                                "power_type": {
                                  "type": "string",
                                  "description": "Seasonal Garden only: the power type the season favors."
                                },
                                "starts_at": {
                                  "type": "string",
                                  "format": "date-time",
                                  "description": "When the stage starts."
                                },
                                "ends_at": {
                                  "type": "string",
                                  "format": "date-time",
                                  "description": "When the stage ends."
                                },
                                "starts_in_minutes": {
                                  "type": "integer",
                                  "description": "Minutes until it starts, rounded up; 0 for the current stage."
                                },
                                "ends_in_minutes": {
                                  "type": "integer",
                                  "description": "Minutes until it ends, rounded up."
                                }
                              }
                            },
                            "description": "The stages that follow, in order, through one full rotation. The last is the next time the current stage comes round."
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`at` isn't a date"
          }
        },
        "x-example": "/timers?at=2026-10-11T12:00:00Z",
        "x-example-response": "{\n  \"now\": \"2026-10-11T12:00:00.000Z\",\n  \"daily_reset\": {\n    \"at\": \"2026-10-12T00:00:00.000Z\",\n    \"in_minutes\": 720\n  },\n  \"locations\": [\n    {\n      \"id\": \"forbidden_grove\",\n      \"name\": \"Forbidden Grove\",\n      \"environment_id\": 11,\n      \"rotation_minutes\": 1200,\n      \"current\": {\n        \"name\": \"Open\",\n        \"starts_at\": \"2026-10-11T12:00:00.000Z\",\n        \"ends_at\": \"2026-10-12T04:00:00.000Z\",\n        \"starts_in_minutes\": 0,\n        \"ends_in_minutes\": 960\n      },\n      \"upcoming\": [\n        {\n          \"name\": \"Closed\",\n          \"starts_at\": \"2026-10-12T04:00:00.000Z\",\n          \"ends_at\": \"2026-10-12T08:00:00.000Z\",\n          \"starts_in_minutes\": 960,\n          \"ends_in_minutes\": 1200\n        },\n        {\n          \"name\": \"Open\",\n          \"starts_at\": \"2026-10-12T08:00:00.000Z\",\n          \"ends_at\": \"2026-10-13T00:00:00.000Z\",\n          \"starts_in_minutes\": 1200,\n          \"ends_in_minutes\": 2160\n        }\n      ]\n    },\n    {\n      \"id\": \"balacks_cove\",\n      \"name\": \"Balack's Cove\",\n      \"environment_id\": 2,\n      \"rotation_minutes\": 1120,\n      \"current\": {\n        \"name\": \"Low Tide\",\n        \"starts_at\": \"2026-10-11T04:01:00.000Z\",\n        \"ends_at\": \"2026-10-11T20:01:00.000Z\",\n        \"starts_in_minutes\": 0,\n        \"ends_in_minutes\": 481\n      },\n      \"upcoming\": [\n        {\n          \"name\": \"Mid Tide\",\n          \"note\": \"rising\",\n          \"starts_at\": \"2026-10-11T20:01:00.000Z\",\n          \"ends_at\": \"2026-10-11T21:01:00.000Z\",\n          \"starts_in_minutes\": 481,\n          \"ends_in_minutes\": 541\n        },\n        {\n          \"name\": \"High Tide\",\n          \"starts_at\": \"2026-10-11T21:01:00.000Z\",\n          \"ends_at\": \"2026-10-11T21:41:00.000Z\",\n          \"starts_in_minutes\": 541,\n          \"ends_in_minutes\": 581\n        },\n        {\n          \"name\": \"Mid Tide\",\n          \"note\": \"falling\",\n          \"starts_at\": \"2026-10-11T21:41:00.000Z\",\n          \"ends_at\": \"2026-10-11T22:41:00.000Z\",\n          \"starts_in_minutes\": 581,\n          \"ends_in_minutes\": 641\n        },\n        {\n          \"name\": \"Low Tide\",\n          \"starts_at\": \"2026-10-11T22:41:00.000Z\",\n          \"ends_at\": \"2026-10-12T14:41:00.000Z\",\n          \"starts_in_minutes\": 641,\n          \"ends_in_minutes\": 1601\n        }\n      ]\n    },\n    {\n      \"id\": \"seasonal_garden\",\n      \"name\": \"Seasonal Garden\",\n      \"environment_id\": 31,\n      \"rotation_minutes\": 19200,\n      \"current\": {\n        \"name\": \"Summer\",\n        \"power_type\": \"tactical\",\n        \"starts_at\": \"2026-10-10T16:00:00.000Z\",\n        \"ends_at\": \"2026-10-14T00:00:00.000Z\",\n        \"starts_in_minutes\": 0,\n        \"ends_in_minutes\": 3600\n      },\n      \"upcoming\": [\n        {\n          \"name\": \"Fall\",\n          \"power_type\": \"shadow\",\n          \"starts_at\": \"2026-10-14T00:00:00.000Z\",\n          \"ends_at\": \"2026-10-17T08:00:00.000Z\",\n          \"starts_in_minutes\": 3600,\n          \"ends_in_minutes\": 8400\n        },\n        {\n          \"name\": \"Winter\",\n          \"power_type\": \"hydro\",\n          \"starts_at\": \"2026-10-17T08:00:00.000Z\",\n          \"ends_at\": \"2026-10-20T16:00:00.000Z\",\n          \"starts_in_minutes\": 8400,\n          \"ends_in_minutes\": 13200\n        },\n        {\n          \"name\": \"Spring\",\n          \"power_type\": \"physical\",\n          \"starts_at\": \"2026-10-20T16:00:00.000Z\",\n          \"ends_at\": \"2026-10-24T00:00:00.000Z\",\n          \"starts_in_minutes\": 13200,\n          \"ends_in_minutes\": 18000\n        },\n        {\n          \"name\": \"Summer\",\n          \"power_type\": \"tactical\",\n          \"starts_at\": \"2026-10-24T00:00:00.000Z\",\n          \"ends_at\": \"2026-10-27T08:00:00.000Z\",\n          \"starts_in_minutes\": 18000,\n          \"ends_in_minutes\": 22800\n        }\n      ]\n    },\n    {\n      \"id\": \"pollution_outbreak\",\n      \"name\": \"Toxic Spill\",\n      \"environment_id\": 45,\n      \"rotation_minutes\": 18120,\n      \"current\": {\n        \"name\": \"Hero\",\n        \"starts_at\": \"2026-10-10T17:00:00.000Z\",\n        \"ends_at\": \"2026-10-11T23:00:00.000Z\",\n        \"starts_in_minutes\": 0,\n        \"ends_in_minutes\": 660\n      },\n      \"upcoming\": [\n        {\n          \"name\": \"Knight\",\n          \"note\": \"rising\",\n          \"starts_at\": \"2026-10-11T23:00:00.000Z\",\n          \"ends_at\": \"2026-10-12T15:00:00.000Z\",\n          \"starts_in_minutes\": 660,\n          \"ends_in_minutes\": 1620\n        },\n        {\n          \"name\": \"Lord/Lady\",\n          \"note\": \"rising\",\n          \"starts_at\": \"2026-10-12T15:00:00.000Z\",\n          \"ends_at\": \"2026-10-13T09:00:00.000Z\",\n          \"starts_in_minutes\": 1620,\n          \"ends_in_minutes\": 2700\n        },\n        {\n          \"name\": \"Baron/Baroness\",\n          \"note\": \"rising\",\n          \"starts_at\": \"2026-10-13T09:00:00.000Z\",\n          \"ends_at\": \"2026-10-14T03:00:00.000Z\",\n          \"starts_in_minutes\": 2700,\n          \"ends_in_minutes\": 3780\n        },\n        {\n          \"name\": \"Count/Countess\",\n          \"note\": \"rising\",\n          \"starts_at\": \"2026-10-14T03:00:00.000Z\",\n          \"ends_at\": \"2026-10-15T03:00:00.000Z\",\n          \"starts_in_minutes\": 3780,\n          \"ends_in_minutes\": 5220\n        },\n        {\n          \"name\": \"Duke/Duchess\",\n          \"note\": \"rising\",\n          \"starts_at\": \"2026-10-15T03:00:00.000Z\",\n          \"ends_at\": \"2026-10-16T03:00:00.000Z\",\n          \"starts_in_minutes\": 5220,\n          \"ends_in_minutes\": 6660\n        },\n        {\n          \"name\": \"Grand Duke/Duchess\",\n          \"note\": \"rising\",\n          \"starts_at\": \"2026-10-16T03:00:00.000Z\",\n          \"ends_at\": \"2026-10-17T03:00:00.000Z\",\n          \"starts_in_minutes\": 6660,\n          \"ends_in_minutes\": 8100\n        },\n        {\n          \"name\": \"Archduke/Archduchess\",\n          \"starts_at\": \"2026-10-17T03:00:00.000Z\",\n          \"ends_at\": \"2026-10-18T03:00:00.000Z\",\n          \"starts_in_minutes\": 8100,\n          \"ends_in_minutes\": 9540\n        },\n        {\n          \"name\": \"Grand Duke/Duchess\",\n          \"note\": \"falling\",\n          \"starts_at\": \"2026-10-18T03:00:00.000Z\",\n          \"ends_at\": \"2026-10-19T03:00:00.000Z\",\n          \"starts_in_minutes\": 9540,\n          \"ends_in_minutes\": 10980\n        },\n        {\n          \"name\": \"Duke/Duchess\",\n          \"note\": \"falling\",\n          \"starts_at\": \"2026-10-19T03:00:00.000Z\",\n          \"ends_at\": \"2026-10-20T03:00:00.000Z\",\n          \"starts_in_minutes\": 10980,\n          \"ends_in_minutes\": 12420\n        },\n        {\n          \"name\": \"Count/Countess\",\n          \"note\": \"falling\",\n          \"starts_at\": \"2026-10-20T03:00:00.000Z\",\n          \"ends_at\": \"2026-10-21T03:00:00.000Z\",\n          \"starts_in_minutes\": 12420,\n          \"ends_in_minutes\": 13860\n        },\n        {\n          \"name\": \"Baron/Baroness\",\n          \"note\": \"falling\",\n          \"starts_at\": \"2026-10-21T03:00:00.000Z\",\n          \"ends_at\": \"2026-10-21T21:00:00.000Z\",\n          \"starts_in_minutes\": 13860,\n          \"ends_in_minutes\": 14940\n        },\n        {\n          \"name\": \"Lord/Lady\",\n          \"note\": \"falling\",\n          \"starts_at\": \"2026-10-21T21:00:00.000Z\",\n          \"ends_at\": \"2026-10-22T15:00:00.000Z\",\n          \"starts_in_minutes\": 14940,\n          \"ends_in_minutes\": 16020\n        },\n        {\n          \"name\": \"Knight\",\n          \"note\": \"falling\",\n          \"starts_at\": \"2026-10-22T15:00:00.000Z\",\n          \"ends_at\": \"2026-10-23T07:00:00.000Z\",\n          \"starts_in_minutes\": 16020,\n          \"ends_in_minutes\": 16980\n        },\n        {\n          \"name\": \"Hero\",\n          \"starts_at\": \"2026-10-23T07:00:00.000Z\",\n          \"ends_at\": \"2026-10-24T13:00:00.000Z\",\n          \"starts_in_minutes\": 16980,\n          \"ends_in_minutes\": 18780\n        }\n      ]\n    }\n  ]\n}",
        "x-nav": "All timers"
      }
    },
    "/timers/{id}": {
      "get": {
        "summary": "Get one location's timer",
        "description": "One rotating location. Replace `:id` with the location's slug, numeric environment ID, or name: `forbidden_grove`, `balacks_cove`, `seasonal_garden`, or `pollution_outbreak` (also `toxic_spill`).",
        "tags": [
          "Timers"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Location slug, numeric environment ID, or name."
          },
          {
            "name": "at",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Work the timers out for this time instead of now: an ISO 8601 date or a Unix time in seconds."
          }
        ],
        "responses": {
          "200": {
            "description": "The location's timer",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "The location slug."
                    },
                    "name": {
                      "type": "string",
                      "description": "The location name."
                    },
                    "environment_id": {
                      "type": "integer",
                      "description": "The game's numeric environment ID."
                    },
                    "rotation_minutes": {
                      "type": "integer",
                      "description": "How long one full rotation takes."
                    },
                    "current": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string",
                          "description": "The stage, e.g. `Low Tide`, `Winter`, or `Count/Countess`."
                        },
                        "note": {
                          "type": "string",
                          "description": "Only for a stage the location passes through twice a rotation: `rising` or `falling`."
                        },
                        "power_type": {
                          "type": "string",
                          "description": "Seasonal Garden only: the power type the season favors."
                        },
                        "starts_at": {
                          "type": "string",
                          "format": "date-time",
                          "description": "When the stage starts."
                        },
                        "ends_at": {
                          "type": "string",
                          "format": "date-time",
                          "description": "When the stage ends."
                        },
                        "starts_in_minutes": {
                          "type": "integer",
                          "description": "Minutes until it starts, rounded up; 0 for the current stage."
                        },
                        "ends_in_minutes": {
                          "type": "integer",
                          "description": "Minutes until it ends, rounded up."
                        }
                      },
                      "description": "The stage the location is in."
                    },
                    "upcoming": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string",
                            "description": "The stage, e.g. `Low Tide`, `Winter`, or `Count/Countess`."
                          },
                          "note": {
                            "type": "string",
                            "description": "Only for a stage the location passes through twice a rotation: `rising` or `falling`."
                          },
                          "power_type": {
                            "type": "string",
                            "description": "Seasonal Garden only: the power type the season favors."
                          },
                          "starts_at": {
                            "type": "string",
                            "format": "date-time",
                            "description": "When the stage starts."
                          },
                          "ends_at": {
                            "type": "string",
                            "format": "date-time",
                            "description": "When the stage ends."
                          },
                          "starts_in_minutes": {
                            "type": "integer",
                            "description": "Minutes until it starts, rounded up; 0 for the current stage."
                          },
                          "ends_in_minutes": {
                            "type": "integer",
                            "description": "Minutes until it ends, rounded up."
                          }
                        }
                      },
                      "description": "The stages that follow, in order, through one full rotation. The last is the next time the current stage comes round."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`at` isn't a date"
          },
          "404": {
            "description": "The location doesn't rotate on a timer"
          }
        },
        "x-example": "/timers/seasonal_garden?at=2026-10-11T12:00:00Z",
        "x-example-response": "{\n  \"id\": \"seasonal_garden\",\n  \"name\": \"Seasonal Garden\",\n  \"environment_id\": 31,\n  \"rotation_minutes\": 19200,\n  \"current\": {\n    \"name\": \"Summer\",\n    \"power_type\": \"tactical\",\n    \"starts_at\": \"2026-10-10T16:00:00.000Z\",\n    \"ends_at\": \"2026-10-14T00:00:00.000Z\",\n    \"starts_in_minutes\": 0,\n    \"ends_in_minutes\": 3600\n  },\n  \"upcoming\": [\n    {\n      \"name\": \"Fall\",\n      \"power_type\": \"shadow\",\n      \"starts_at\": \"2026-10-14T00:00:00.000Z\",\n      \"ends_at\": \"2026-10-17T08:00:00.000Z\",\n      \"starts_in_minutes\": 3600,\n      \"ends_in_minutes\": 8400\n    },\n    {\n      \"name\": \"Winter\",\n      \"power_type\": \"hydro\",\n      \"starts_at\": \"2026-10-17T08:00:00.000Z\",\n      \"ends_at\": \"2026-10-20T16:00:00.000Z\",\n      \"starts_in_minutes\": 8400,\n      \"ends_in_minutes\": 13200\n    },\n    {\n      \"name\": \"Spring\",\n      \"power_type\": \"physical\",\n      \"starts_at\": \"2026-10-20T16:00:00.000Z\",\n      \"ends_at\": \"2026-10-24T00:00:00.000Z\",\n      \"starts_in_minutes\": 13200,\n      \"ends_in_minutes\": 18000\n    },\n    {\n      \"name\": \"Summer\",\n      \"power_type\": \"tactical\",\n      \"starts_at\": \"2026-10-24T00:00:00.000Z\",\n      \"ends_at\": \"2026-10-27T08:00:00.000Z\",\n      \"starts_in_minutes\": 18000,\n      \"ends_in_minutes\": 22800\n    }\n  ]\n}",
        "x-nav": "One location"
      }
    },
    "/consult-scrambles": {
      "get": {
        "summary": "Consult Scrambles",
        "tags": [
          "Scrambles"
        ],
        "responses": {
          "200": {
            "description": "A random Scrambles quote",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "### Response\n\nA single quote as plain text.",
        "x-example": "/consult-scrambles",
        "x-nav": "Consult Scrambles"
      }
    },
    "/sb": {
      "get": {
        "summary": "Get the SUPER|brie+ price",
        "description": "The latest SUPER|brie+ price on [MarketHunt](https://markethunt.win), in gold, as plain text. Cached for 12 hours. `0` if MarketHunt has no price or can't be reached.",
        "tags": [
          "MarketHunt"
        ],
        "responses": {
          "200": {
            "description": "SUPER|brie+ market price",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-example": "/sb",
        "x-example-response": "17241",
        "x-nav": "SUPER|brie+ price"
      }
    },
    "/gift-links": {
      "get": {
        "summary": "Get gift links",
        "description": "Recently shared gift links, newest first. Cached for 15 minutes.",
        "tags": [
          "Gift Links"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer"
            },
            "description": "Maximum number of links to return. Defaults to 25, capped at 250."
          },
          {
            "name": "expired",
            "in": "query",
            "schema": {
              "type": "boolean"
            },
            "description": "Include expired gifts when set to `true`, `1`, or `yes`. Defaults to `false`."
          }
        ],
        "responses": {
          "200": {
            "description": "Gift links",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer",
                      "description": "Number of matching links before `limit` is applied."
                    },
                    "links": {
                      "type": "array",
                      "description": "The matching links, newest first."
                    },
                    "links[].id": {
                      "type": "string",
                      "description": "Stable identifier for the link."
                    },
                    "links[].messageId": {
                      "type": "string",
                      "description": "ID of the Discord announcement containing the link."
                    },
                    "links[].timestamp": {
                      "type": "integer",
                      "description": "Time the announcement was posted, as a Unix timestamp in milliseconds."
                    },
                    "links[].parsed": {
                      "type": "object",
                      "description": "Values parsed from the announcement, including `code`, `url`, `reward`, `finder`, and `finderName`."
                    },
                    "links[].gift": {
                      "type": "object",
                      "description": "Gift details from MouseHunt, including `name`, `image`, `quantity`, `expiresAt`, `id`, `hash`, and `url`. Details that could not be retrieved are `null`."
                    },
                    "links[].expired": {
                      "type": "boolean",
                      "description": "Whether the gift's expiration time has passed."
                    }
                  }
                }
              }
            }
          }
        },
        "x-example-response": "{\n  \"count\": 42,\n  \"links\": [\n    {\n      \"id\": \"1234567890-6ikkbr\",\n      \"messageId\": \"1234567890\",\n      \"timestamp\": 1783706400000,\n      \"parsed\": {\n        \"code\": \"6ikkbr\",\n        \"url\": \"https://mshnt.ca/6ikkbr\",\n        \"reward\": \"5 Chrome Bits\",\n        \"finder\": \"About24Pandas\",\n        \"finderName\": \"About24Pandas\"\n      },\n      \"gift\": {\n        \"name\": \"5 Chrome Bits\",\n        \"image\": \"https://www.mousehuntgame.com/images/items/stats/large/example.png\",\n        \"quantity\": 5,\n        \"expiresAt\": 1784311200000,\n        \"id\": \"483392733\",\n        \"hash\": \"example\",\n        \"url\": \"https://www.mousehuntgame.com/claimgift.php?gift_id=483392733&gift_hash=example\"\n      },\n      \"expired\": false\n    }\n  ]\n}",
        "x-nav": "Gift links",
        "x-example": "/gift-links?limit=2"
      }
    },
    "/markethunt-chart/{chart}": {
      "get": {
        "summary": "Get a price chart",
        "description": "Replace `:chart` with a MarketHunt item ID; a `.png` suffix is optional. For a compact chart, add `-small` to the ID or pass the `small` query parameter.\n\n### Response\n\nA PNG image (`image/png`), or `404` if MarketHunt doesn't recognize the item ID.",
        "tags": [
          "MarketHunt"
        ],
        "parameters": [
          {
            "name": "chart",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "MarketHunt item ID, optionally followed by `-small` or `.png`."
          },
          {
            "name": "small",
            "in": "query",
            "schema": {
              "type": "boolean"
            },
            "description": "Render the compact chart. Any value turns it on, even `small=false`."
          }
        ],
        "responses": {
          "200": {
            "description": "MarketHunt price chart",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        },
        "x-example-response": "HTTP/1.1 200 OK\nContent-Type: image/png\nCache-Control: public, max-age=86400\n\n<PNG image data>",
        "x-nav": "Price chart",
        "x-example": "/markethunt-chart/114"
      }
    },
    "/markethunt/items/{id}": {
      "get": {
        "summary": "Get an item's price history",
        "description": "An item's daily [MarketHunt](https://markethunt.win) prices for the last year, with a summary. Replace `:id` with an item ID or type. The year ends on MarketHunt's latest row, and days MarketHunt has no row for are left out.\n\nThe summary always covers the whole year, whatever `from` and `to` are. Prices are cached for 6 hours. If MarketHunt can't be reached, the last cached prices are served with an `X-Data-Stale: true` header.",
        "tags": [
          "MarketHunt"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Item ID or type, e.g. `114` or `super_brie_cheese`."
          },
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "First date to include, as `YYYY-MM-DD`. Dates before the year start at the year's first day."
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Last date to include, as `YYYY-MM-DD`. Defaults to the latest row."
          },
          {
            "name": "summary",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "only"
              ]
            },
            "description": "`only` leaves out `data`."
          }
        ],
        "responses": {
          "200": {
            "description": "The item's price history",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "item",
                    "range",
                    "summary"
                  ],
                  "properties": {
                    "item": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "integer"
                        },
                        "type": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "is_tradable": {
                          "type": [
                            "boolean",
                            "null"
                          ],
                          "description": "Whether the item can currently be traded, according to MarketHunt."
                        }
                      }
                    },
                    "range": {
                      "type": "object",
                      "description": "The dates `data` covers.",
                      "properties": {
                        "from": {
                          "type": "string",
                          "format": "date"
                        },
                        "to": {
                          "type": "string",
                          "format": "date"
                        }
                      }
                    },
                    "summary": {
                      "type": "object",
                      "properties": {
                        "latest": {
                          "type": "object",
                          "properties": {
                            "date": {
                              "type": "string",
                              "format": "date"
                            },
                            "price": {
                              "type": "integer",
                              "description": "Price in gold."
                            },
                            "sb_price": {
                              "type": "number",
                              "description": "Price in SUPER|brie+."
                            },
                            "volume": {
                              "type": [
                                "integer",
                                "null"
                              ],
                              "description": "Units traded. `null` on days MarketHunt has no volume for."
                            }
                          },
                          "description": "The latest row."
                        },
                        "change": {
                          "type": "object",
                          "description": "The change since 7, 30, and 90 days before the latest row, compared with the last row on or before that day. `null` when the year has no row that early.",
                          "properties": {
                            "7d": {
                              "type": [
                                "object",
                                "null"
                              ],
                              "properties": {
                                "price": {
                                  "type": "integer",
                                  "description": "The earlier price."
                                },
                                "diff": {
                                  "type": "integer",
                                  "description": "Latest price minus the earlier price."
                                },
                                "pct": {
                                  "type": "number",
                                  "description": "`diff` as a percentage of the earlier price, to two decimals."
                                }
                              }
                            },
                            "30d": {
                              "type": [
                                "object",
                                "null"
                              ],
                              "properties": {
                                "price": {
                                  "type": "integer",
                                  "description": "The earlier price."
                                },
                                "diff": {
                                  "type": "integer",
                                  "description": "Latest price minus the earlier price."
                                },
                                "pct": {
                                  "type": "number",
                                  "description": "`diff` as a percentage of the earlier price, to two decimals."
                                }
                              }
                            },
                            "90d": {
                              "type": [
                                "object",
                                "null"
                              ],
                              "properties": {
                                "price": {
                                  "type": "integer",
                                  "description": "The earlier price."
                                },
                                "diff": {
                                  "type": "integer",
                                  "description": "Latest price minus the earlier price."
                                },
                                "pct": {
                                  "type": "number",
                                  "description": "`diff` as a percentage of the earlier price, to two decimals."
                                }
                              }
                            }
                          }
                        },
                        "volume_30d_avg": {
                          "type": [
                            "integer",
                            "null"
                          ],
                          "description": "Average daily volume over the last 30 days, skipping days without volume."
                        },
                        "high": {
                          "type": "object",
                          "properties": {
                            "date": {
                              "type": "string",
                              "format": "date"
                            },
                            "price": {
                              "type": "integer"
                            }
                          },
                          "description": "The year's highest price. On a tie, the most recent."
                        },
                        "low": {
                          "type": "object",
                          "properties": {
                            "date": {
                              "type": "string",
                              "format": "date"
                            },
                            "price": {
                              "type": "integer"
                            }
                          },
                          "description": "The year's lowest price. On a tie, the most recent."
                        }
                      }
                    },
                    "data": {
                      "type": "array",
                      "description": "Daily rows in `range`, oldest first.",
                      "items": {
                        "type": "object",
                        "properties": {
                          "date": {
                            "type": "string",
                            "format": "date"
                          },
                          "price": {
                            "type": "integer",
                            "description": "Price in gold."
                          },
                          "sb_price": {
                            "type": "number",
                            "description": "Price in SUPER|brie+."
                          },
                          "volume": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Units traded. `null` on days MarketHunt has no volume for."
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidQuery"
          },
          "404": {
            "description": "Unknown item (`not_found`), or an item that isn't on the marketplace (`not_on_market`)"
          },
          "503": {
            "description": "MarketHunt can't be reached and nothing is cached (`upstream_unavailable`)"
          }
        },
        "x-example": "/markethunt/items/114",
        "x-nav": "Price history",
        "x-example-response": "{\n  \"item\": {\n    \"id\": 114,\n    \"type\": \"super_brie_cheese\",\n    \"name\": \"SUPER|brie+\",\n    \"is_tradable\": true\n  },\n  \"range\": {\n    \"from\": \"2025-10-10\",\n    \"to\": \"2026-10-09\"\n  },\n  \"summary\": {\n    \"latest\": {\n      \"date\": \"2026-10-09\",\n      \"price\": 17241,\n      \"sb_price\": 1,\n      \"volume\": 52683\n    },\n    \"change\": {\n      \"7d\": {\n        \"price\": 17156,\n        \"diff\": 85,\n        \"pct\": 0.5\n      },\n      \"30d\": {\n        \"price\": 16606,\n        \"diff\": 635,\n        \"pct\": 3.82\n      },\n      \"90d\": {\n        \"price\": 16129,\n        \"diff\": 1112,\n        \"pct\": 6.89\n      }\n    },\n    \"volume_30d_avg\": 48224,\n    \"high\": {\n      \"date\": \"2025-10-12\",\n      \"price\": 19006\n    },\n    \"low\": {\n      \"date\": \"2026-10-03\",\n      \"price\": 14647\n    }\n  },\n  \"data\": [\n    { \"date\": \"2025-10-10\", \"price\": 18987, \"sb_price\": 1, \"volume\": 55348 },\n    { \"date\": \"2025-10-11\", \"price\": 18991, \"sb_price\": 1, \"volume\": 60153 },\n    ...\n  ]\n}"
      }
    },
    "/setup-namer": {
      "post": {
        "summary": "Name a setup",
        "description": "Suggests a name for a trap setup. Send the setup as JSON in the request body.",
        "tags": [
          "MouseHunt Improved"
        ],
        "responses": {
          "200": {
            "description": "Name a hunting setup",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        },
        "x-nav": "Setup namer",
        "x-internal": true
      }
    },
    "/mh-improved/versions": {
      "get": {
        "summary": "Get MouseHunt Improved store versions",
        "description": "The latest MouseHunt Improved version on each browser store, when that version was first seen (`since`), and when the store was last checked (`checked`). Refreshed every two hours.",
        "tags": [
          "Versions"
        ],
        "responses": {
          "200": {
            "description": "MouseHunt Improved store versions",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        },
        "x-example": "/mh-improved/versions",
        "x-example-response": "{\n  \"chrome\": {\n    \"version\": \"0.102.0\",\n    \"since\": \"2026-10-10T03:07:21.433Z\",\n    \"checked\": \"2026-10-10T16:00:29.455Z\"\n  },\n  \"firefox\": {\n    \"version\": \"0.102.0\",\n    \"since\": \"2026-10-10T03:07:21.433Z\",\n    \"checked\": \"2026-10-10T16:00:29.455Z\"\n  },\n  \"userscript\": {\n    \"version\": \"0.102.0\",\n    \"since\": \"2026-10-10T03:07:21.433Z\",\n    \"checked\": \"2026-10-10T16:00:29.455Z\"\n  }\n}",
        "x-nav": "MouseHunt Improved versions",
        "x-internal": true
      }
    },
    "/mice-attraction-rates": {
      "x-data-file": true,
      "get": {
        "summary": "Get mice attraction rates",
        "description": "Community-sourced attraction rates ([mhct.win](https://mhct.win/)) for each mouse, broken down by location and cheese. Rates are percentages.",
        "tags": [
          "Mice"
        ],
        "responses": {
          "200": {
            "description": "Attraction rates by mouse, then location and cheese",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "[type]": {
                      "type": "object",
                      "description": "Keyed by mouse type. Each value is an object keyed by location."
                    },
                    "[type][location]": {
                      "type": "object",
                      "description": "Keyed by location slug. Each value is an object keyed by cheese, with the attraction rate (percent) as the value."
                    }
                  }
                }
              }
            }
          }
        },
        "x-example": "/mice-attraction-rates",
        "x-nav": "Attraction rates",
        "x-internal": true
      }
    },
    "/mouse-loot-meta": {
      "x-data-file": true,
      "get": {
        "summary": "Get loot data details",
        "description": "The date the data runs through, the thresholds, and counts of the rows that were left out.",
        "tags": [
          "Loot"
        ],
        "responses": {
          "200": {
            "description": "Data date, thresholds, and counts of omitted rows",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        },
        "x-example": "/mouse-loot-meta",
        "x-nav": "Loot data details"
      }
    },
    "/brift-mice-per-mist-level": {
      "x-data-file": true,
      "get": {
        "summary": "Get Burroughs Rift mice",
        "tags": [
          "Burroughs Rift Mice"
        ],
        "responses": {
          "200": {
            "description": "Burroughs Rift mice by mist tier and cheese",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "[tier]": {
                      "type": "object",
                      "description": "Keyed by mist tier (`tier_0`–`tier_3`)."
                    },
                    "[tier][cheese]": {
                      "type": "array",
                      "description": "Keyed by cheese variant (`string`, `terra`, `polluted`)."
                    },
                    "[tier][cheese][].id": {
                      "type": "string",
                      "description": "Mouse type (slug)."
                    },
                    "[tier][cheese][].name": {
                      "type": "string",
                      "description": "Mouse name."
                    },
                    "[tier][cheese][].image": {
                      "type": "string",
                      "description": "Mouse image filename."
                    }
                  }
                }
              }
            }
          }
        },
        "x-example": "/brift-mice-per-mist-level",
        "x-nav": "Burroughs Rift by tier"
      }
    },
    "/airships": {
      "x-data-file": true,
      "get": {
        "summary": "Get airship parts",
        "tags": [
          "Airship Parts"
        ],
        "responses": {
          "200": {
            "description": "Floating Islands airship parts",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "description": "Part type (slug)."
                      },
                      "name": {
                        "type": "string",
                        "description": "Part name."
                      },
                      "category": {
                        "type": "string",
                        "description": "Part category (e.g. `hull`)."
                      },
                      "image": {
                        "type": "string",
                        "description": "Part image URL."
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-example": "/airships",
        "x-nav": "Airship parts"
      }
    },
    "/map/community": {
      "get": {
        "summary": "Get community map data",
        "description": "`old` lists the IDs of inactive community maps.",
        "tags": [
          "Maps"
        ],
        "responses": {
          "200": {
            "description": "Community treasure map data",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        },
        "x-example": "/map/community",
        "x-nav": "Community map data"
      }
    },
    "/map/scrolls": {
      "get": {
        "summary": "Get scrolls to maps",
        "description": "Maps each scroll case to the treasure maps it can open, with the MHCT ID for each map.",
        "tags": [
          "Maps"
        ],
        "responses": {
          "200": {
            "description": "The maps each scroll case can open",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "[scroll]": {
                      "type": "array",
                      "description": "Keyed by scroll case type (slug)."
                    },
                    "[scroll][].name": {
                      "type": "string",
                      "description": "Map name."
                    },
                    "[scroll][].mhctId": {
                      "type": "integer",
                      "description": "MHCT ID for the map."
                    }
                  }
                }
              }
            }
          }
        },
        "x-example": "/map/scrolls",
        "x-nav": "Scrolls to maps"
      }
    },
    "/cre-mice-groups": {
      "x-data-file": true,
      "get": {
        "summary": "Get CRE mice groups",
        "description": "Groups of related mice used by the catch rate estimator.",
        "tags": [
          "Mice"
        ],
        "responses": {
          "200": {
            "description": "Mouse groups for the catch rate estimator",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "[group]": {
                      "type": "array",
                      "description": "Keyed by group slug (e.g. `dragon`); each value is an array of mouse types."
                    }
                  }
                }
              }
            }
          }
        },
        "x-example": "/cre-mice-groups",
        "x-nav": "CRE groups"
      }
    },
    "/effs": {
      "x-data-file": true,
      "get": {
        "summary": "Get mice effectiveness values",
        "description": "Power type effectiveness percentages for each mouse, from the [Minimum Luck Values](https://docs.google.com/spreadsheets/d/13hKjNDFTFR3rTkmQzyi3d4ZDOlQJUvTfWPDQemmFW_Y/edit#gid=824520716) spreadsheet.\n\n> [`/effs-raw`](https://api.mouse.rip/effs-raw) has the unprocessed data, keyed by mouse name.",
        "tags": [
          "Mice"
        ],
        "responses": {
          "200": {
            "description": "Power type effectiveness for every mouse",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "integer",
                        "description": "Mouse ID."
                      },
                      "type": {
                        "type": "string",
                        "description": "Mouse type (slug)."
                      },
                      "name": {
                        "type": "string",
                        "description": "Mouse name."
                      },
                      "effectivenesses": {
                        "type": "object",
                        "description": "Effectiveness value per power type (`power`, `arcane`, `draconic`, `forgotten`, `hydro`, `parental`, `physical`, `shadow`, `tactical`, `law`, `rift`)."
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-example": "/effs",
        "x-nav": "Effectiveness values"
      }
    },
    "/minlucks": {
      "x-data-file": true,
      "get": {
        "summary": "Get mice minlucks",
        "description": "The minimum luck that guarantees a catch with each power type, from the [Minimum Luck Values](https://docs.google.com/spreadsheets/d/13hKjNDFTFR3rTkmQzyi3d4ZDOlQJUvTfWPDQemmFW_Y/edit#gid=824520716) spreadsheet.\n\n> [`/minlucks-raw`](https://api.mouse.rip/minlucks-raw) has the unprocessed data, keyed by mouse name.",
        "tags": [
          "Mice"
        ],
        "responses": {
          "200": {
            "description": "Minimum luck for every mouse",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "integer",
                        "description": "Mouse ID."
                      },
                      "type": {
                        "type": "string",
                        "description": "Mouse type (slug)."
                      },
                      "name": {
                        "type": "string",
                        "description": "Mouse name."
                      },
                      "minlucks": {
                        "type": "object",
                        "description": "Minluck per power type (`arcane`, `draconic`, `forgotten`, `hydro`, `physical`, `shadow`, `tactical`, `law`, `rift`). `0` means the mouse cannot be caught with that power type."
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-example": "/minlucks",
        "x-nav": "Mouse minluck"
      }
    },
    "/wisdom": {
      "x-data-file": true,
      "get": {
        "summary": "Get mice wisdom",
        "description": "Wisdom for each mouse, from the [MH Wisdom Values](https://docs.google.com/spreadsheets/d/1nzD6iiHauMMwD2eHBuAyRziYJtCVnNwSYzCKbBnrRgc/edit#gid=1426419522) spreadsheet.\n\n> [`/wisdom-raw`](https://api.mouse.rip/wisdom-raw) has the unprocessed data, keyed by mouse name.",
        "tags": [
          "Mice"
        ],
        "responses": {
          "200": {
            "description": "Wisdom for every mouse",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "integer",
                        "description": "Mouse ID."
                      },
                      "type": {
                        "type": "string",
                        "description": "Mouse type (slug)."
                      },
                      "name": {
                        "type": "string",
                        "description": "Mouse name."
                      },
                      "wisdom": {
                        "type": "integer",
                        "description": "Mouse wisdom."
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-example": "/wisdom",
        "x-nav": "Mouse wisdom"
      }
    },
    "/mice-groups": {
      "x-data-file": true,
      "get": {
        "summary": "Get mice groups",
        "description": "Every mouse group, with its description, banner image, and `mouse_ids`.",
        "tags": [
          "Mice"
        ],
        "responses": {
          "200": {
            "description": "Mouse groups",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "string",
                        "description": "Mouse group ID."
                      },
                      "name": {
                        "type": "string",
                        "description": "Mouse group name."
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-example": "/mice-groups",
        "x-nav": "Groups"
      }
    },
    "/mice-regions": {
      "x-data-file": true,
      "get": {
        "summary": "Get mice regions",
        "description": "Every region and the `mouse_ids` of its mice.",
        "tags": [
          "Mice"
        ],
        "responses": {
          "200": {
            "description": "Mice by region",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "string",
                        "description": "Mouse region ID."
                      },
                      "name": {
                        "type": "string",
                        "description": "Mouse region name."
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-example": "/mice-regions",
        "x-nav": "Regions"
      }
    },
    "/mice-thumbnails": {
      "x-data-file": true,
      "get": {
        "summary": "Get mice thumbnails",
        "description": "A lightweight list of every mouse and its image URLs.",
        "tags": [
          "Mice"
        ],
        "responses": {
          "200": {
            "description": "Mouse thumbnails",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "integer",
                        "description": "Mouse ID."
                      },
                      "type": {
                        "type": "string",
                        "description": "Mouse type (slug)."
                      },
                      "thumb": {
                        "type": "string",
                        "description": "Thumbnail image URL."
                      },
                      "large": {
                        "type": "string",
                        "description": "Large image URL."
                      },
                      "square": {
                        "type": "string",
                        "description": "Square image URL."
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-example": "/mice-thumbnails",
        "x-nav": "Thumbnails"
      }
    },
    "/mice-silhouettes": {
      "x-data-file": true,
      "get": {
        "summary": "Get mice silhouettes",
        "description": "Every mouse's silhouette image URLs, plus its full-art image.",
        "tags": [
          "Mice"
        ],
        "responses": {
          "200": {
            "description": "Mouse silhouettes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "integer",
                        "description": "Mouse ID."
                      },
                      "type": {
                        "type": "string",
                        "description": "Mouse type (slug)."
                      },
                      "large": {
                        "type": "string",
                        "description": "Large silhouette image URL."
                      },
                      "medium": {
                        "type": "string",
                        "description": "Medium silhouette image URL."
                      },
                      "art": {
                        "type": "string",
                        "description": "Full-art (non-silhouette) image URL."
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-example": "/mice-silhouettes",
        "x-nav": "Silhouettes"
      }
    },
    "/environments": {
      "get": {
        "summary": "Get all environments",
        "description": "With no query string, returns every permanent location. Any query (filters, `q`, `sort`, `fields`, `limit`, and so on) searches permanent and event locations together and adds `is_event` and `event` to each record.\n\n> This endpoint supports filtering, searching, sorting, pagination, and\n> field selection via query parameters — see\n> [Search & Querying](/search#query-parameters). Sort by `environment_id`, `id`, `name`, `order`, `region`, `status`, or `title`.",
        "tags": [
          "Environments"
        ],
        "responses": {
          "200": {
            "description": "Environments",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "string",
                        "description": "Location slug, e.g. `meadow`."
                      },
                      "name": {
                        "type": "string",
                        "description": "The environment name."
                      },
                      "article": {
                        "type": "string",
                        "description": "The name with its article, e.g. \"the Meadow\"."
                      },
                      "image": {
                        "type": "string",
                        "description": "Image URL."
                      },
                      "headerImage": {
                        "type": "string",
                        "description": "Header image URL."
                      },
                      "icon": {
                        "type": "string",
                        "description": "Icon URL."
                      },
                      "region": {
                        "type": "string",
                        "description": "Region slug, e.g. `gnawnia`."
                      },
                      "order": {
                        "type": "integer",
                        "description": "Display order."
                      },
                      "title": {
                        "type": "string",
                        "description": "Hunter title required to travel here, e.g. `novice`."
                      },
                      "title_formatted": {
                        "type": "string",
                        "description": "Display name of the required title."
                      },
                      "environment_id": {
                        "type": "integer",
                        "description": "The numeric environment ID used by the game."
                      },
                      "status": {
                        "type": "string",
                        "description": "Whether the environment is currently `active` or `inactive`."
                      },
                      "description": {
                        "type": "string",
                        "description": "The environment description, as plain text."
                      },
                      "is_event": {
                        "type": "boolean",
                        "description": "Whether this is an event location. Only in query results."
                      },
                      "event": {
                        "type": "string",
                        "description": "The event an event location belongs to, e.g. `gwh`, or `null`. Only in query results."
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidQuery"
          }
        },
        "x-example": "/environments?region=gnawnia&fields=id,name,environment_id",
        "x-nav": "All environments",
        "parameters": [
          {
            "$ref": "#/components/parameters/CollectionQuery"
          }
        ]
      }
    },
    "/environments/{id}": {
      "get": {
        "summary": "Get an environment",
        "description": "One location, permanent or event. Replace `:id` with the location's slug (e.g. `meadow`), its numeric environment ID (e.g. `18`), or its name.",
        "tags": [
          "Environments"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Location slug, numeric environment ID, or name."
          },
          {
            "$ref": "#/components/parameters/CollectionQuery"
          }
        ],
        "responses": {
          "200": {
            "description": "The location",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "Location slug, e.g. `meadow`."
                    },
                    "name": {
                      "type": "string",
                      "description": "The environment name."
                    },
                    "article": {
                      "type": "string",
                      "description": "The name with its article, e.g. \"the Meadow\"."
                    },
                    "image": {
                      "type": "string",
                      "description": "Image URL."
                    },
                    "headerImage": {
                      "type": "string",
                      "description": "Header image URL."
                    },
                    "icon": {
                      "type": "string",
                      "description": "Icon URL."
                    },
                    "region": {
                      "type": "string",
                      "description": "Region slug, e.g. `gnawnia`."
                    },
                    "order": {
                      "type": "integer",
                      "description": "Display order."
                    },
                    "title": {
                      "type": "string",
                      "description": "Hunter title required to travel here, e.g. `novice`."
                    },
                    "title_formatted": {
                      "type": "string",
                      "description": "Display name of the required title."
                    },
                    "environment_id": {
                      "type": "integer",
                      "description": "The numeric environment ID used by the game."
                    },
                    "status": {
                      "type": "string",
                      "description": "Whether the environment is currently `active` or `inactive`."
                    },
                    "description": {
                      "type": "string",
                      "description": "The environment description, as plain text."
                    },
                    "is_event": {
                      "type": "boolean",
                      "description": "Whether this is an event location."
                    },
                    "event": {
                      "type": "string",
                      "description": "The event an event location belongs to, e.g. `gwh`, or `null`."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidQuery"
          },
          "404": {
            "description": "Location not found"
          }
        },
        "x-example": "/environments/meadow",
        "x-nav": "Environment by ID/name"
      }
    },
    "/environments-events": {
      "x-data-file": true,
      "get": {
        "summary": "Get event environments",
        "description": "Event locations, each with the `event` it belongs to.",
        "tags": [
          "Environments"
        ],
        "responses": {
          "200": {
            "description": "Event environments",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "string",
                        "description": "Location slug, e.g. `meadow`."
                      },
                      "name": {
                        "type": "string",
                        "description": "The environment name."
                      },
                      "article": {
                        "type": "string",
                        "description": "The name with its article, e.g. \"the Meadow\"."
                      },
                      "image": {
                        "type": "string",
                        "description": "Image URL."
                      },
                      "headerImage": {
                        "type": "string",
                        "description": "Header image URL."
                      },
                      "icon": {
                        "type": "string",
                        "description": "Icon URL."
                      },
                      "region": {
                        "type": "string",
                        "description": "Region slug, e.g. `gnawnia`."
                      },
                      "order": {
                        "type": "integer",
                        "description": "Display order."
                      },
                      "event": {
                        "type": "string",
                        "description": "The event this location belongs to, e.g. `gwh`."
                      },
                      "title": {
                        "type": "string",
                        "description": "Hunter title required to travel here, e.g. `novice`."
                      },
                      "title_formatted": {
                        "type": "string",
                        "description": "Display name of the required title."
                      },
                      "environment_id": {
                        "type": "integer",
                        "description": "The numeric environment ID used by the game."
                      },
                      "status": {
                        "type": "string",
                        "description": "Whether the environment is currently `active` or `inactive`."
                      },
                      "description": {
                        "type": "string",
                        "description": "The environment description, as plain text."
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-example": "/environments-events",
        "x-nav": "Event environments"
      }
    },
    "/m400-locations": {
      "x-data-file": true,
      "get": {
        "summary": "Get M400 locations",
        "description": "Keyed by location slug. Each value is the location's name followed by the names of its mice.",
        "tags": [
          "Environments"
        ],
        "responses": {
          "200": {
            "description": "M400 locations and mice",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "location": {
                      "type": "string",
                      "description": "The location ID."
                    },
                    "mice": {
                      "type": "array",
                      "description": "The array of mice in the location."
                    }
                  }
                }
              }
            }
          }
        },
        "x-example": "/m400-locations",
        "x-nav": "M400 locations"
      }
    },
    "/items-slim": {
      "x-data-file": true,
      "get": {
        "summary": "Get slim items",
        "description": "Every item with only its identifying fields and images; a smaller alternative to `/items`.",
        "tags": [
          "Items"
        ],
        "responses": {
          "200": {
            "description": "Items with fewer fields",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "integer",
                        "description": "Item ID."
                      },
                      "type": {
                        "type": "string",
                        "description": "Item type (slug)."
                      },
                      "name": {
                        "type": "string",
                        "description": "Item name."
                      },
                      "classification": {
                        "type": "string",
                        "description": "Item classification."
                      },
                      "tags": {
                        "type": "array",
                        "description": "Item tags."
                      },
                      "images": {
                        "type": "object",
                        "description": "Image URLs (`thumbnail`, `best`, `upscaled`)."
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-example": "/items-slim",
        "x-nav": "Slim items"
      }
    },
    "/items-tradable": {
      "x-data-file": true,
      "get": {
        "summary": "Get tradable items",
        "description": "A lightweight list of every item that can be traded.",
        "tags": [
          "Items"
        ],
        "responses": {
          "200": {
            "description": "Tradable items",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "integer",
                        "description": "Item ID."
                      },
                      "type": {
                        "type": "string",
                        "description": "Item type (slug)."
                      },
                      "name": {
                        "type": "string",
                        "description": "Item name."
                      },
                      "image": {
                        "type": "string",
                        "description": "Item image URL."
                      },
                      "truncated_name": {
                        "type": "string",
                        "description": "Truncated item name."
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-example": "/items-tradable",
        "x-nav": "Tradable items"
      }
    },
    "/item-abbreviations": {
      "x-data-file": true,
      "get": {
        "summary": "Get item abbreviations",
        "description": "The names hunters use for items, keyed by item type. A term can name more than one item: some are shared abbreviations (`ff` is four cheeses) and some name a group (`charm` matches 12 weapons and bases, `hal` the four High Altitude Loot items). `/search` matches these terms.",
        "tags": [
          "Items"
        ],
        "responses": {
          "200": {
            "description": "Search terms by item type",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "description": "Item type to its search terms, e.g. `\"super_brie_cheese\": [\"sb\", \"sb+\"]`."
                }
              }
            }
          }
        },
        "x-example": "/item-abbreviations",
        "x-nav": "Abbreviations"
      }
    },
    "/item-thumbnails": {
      "x-data-file": true,
      "get": {
        "summary": "Get item thumbnails",
        "description": "A lightweight list of every item and its image URLs.",
        "tags": [
          "Items"
        ],
        "responses": {
          "200": {
            "description": "Item thumbnails",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "integer",
                        "description": "Item ID."
                      },
                      "type": {
                        "type": "string",
                        "description": "Item type (slug)."
                      },
                      "image": {
                        "type": "string",
                        "description": "Item image URL."
                      },
                      "thumb": {
                        "type": "string",
                        "description": "Thumbnail image URL."
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-example": "/item-thumbnails",
        "x-nav": "Thumbnails"
      }
    },
    "/items-names-to-ids": {
      "x-data-file": true,
      "get": {
        "summary": "Get item names to IDs",
        "description": "A lookup map of item display name to item ID.",
        "tags": [
          "Items"
        ],
        "responses": {
          "200": {
            "description": "Item IDs by name",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "[name]": {
                      "type": "integer",
                      "description": "Keyed by item display name, with the item ID as the value."
                    }
                  }
                }
              }
            }
          }
        },
        "x-example": "/items-names-to-ids",
        "x-nav": "Names to IDs"
      }
    },
    "/journals-environment-mapping": {
      "x-data-file": true,
      "get": {
        "summary": "Get journal themes by environment",
        "description": "An object mapping each location type to its journal theme. Only locations with their own theme are included.",
        "tags": [
          "Journals"
        ],
        "responses": {
          "200": {
            "description": "Journal themes by environment",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "environment": {
                      "type": "string",
                      "description": "Location type (the key)."
                    },
                    "theme": {
                      "type": "string",
                      "description": "Journal theme, e.g. `theme_western`."
                    }
                  }
                }
              }
            }
          }
        },
        "x-example": "/journals-environment-mapping",
        "x-nav": "Journal themes by environment"
      }
    },
    "/journals-events": {
      "x-data-file": true,
      "get": {
        "summary": "Get journal themes by event",
        "description": "An object mapping each event to its journal themes.",
        "tags": [
          "Journals"
        ],
        "responses": {
          "200": {
            "description": "Journal themes by event",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "event": {
                      "type": "string",
                      "description": "Event key, e.g. `birthday`."
                    },
                    "themes": {
                      "type": "array",
                      "description": "Journal themes for the event, e.g. `theme_birthday_six`."
                    }
                  }
                }
              }
            }
          }
        },
        "x-example": "/journals-events",
        "x-nav": "Journal themes by event"
      }
    },
    "/library-assignments": {
      "x-data-file": true,
      "get": {
        "summary": "Get Library Assignment details",
        "description": "An object of assignment sets, keyed by assignment set type.",
        "tags": [
          "Library Assignments"
        ],
        "responses": {
          "200": {
            "description": "Library Assignment details",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "key": {
                      "type": "string",
                      "description": "Assignment set type (the key), e.g. `library_intro_research_assignment_convertible`."
                    },
                    "name": {
                      "type": "string",
                      "description": "Assignment set name."
                    },
                    "cost": {
                      "type": "integer",
                      "description": "Cost to unlock the assignment set."
                    },
                    "rewardPoints": {
                      "type": "integer",
                      "description": "Reward points granted for the set."
                    },
                    "rewards": {
                      "type": "array",
                      "description": "Reward names."
                    },
                    "assignments": {
                      "type": "array"
                    },
                    "assignments[].name": {
                      "type": "string",
                      "description": "Assignment name. Can be empty."
                    },
                    "assignments[].tasks": {
                      "type": "array"
                    },
                    "assignments[].tasks[].title": {
                      "type": "string",
                      "description": "Task heading, e.g. `All seven of the following:`. Can be empty."
                    },
                    "assignments[].tasks[].text": {
                      "type": "array",
                      "description": "Requirement lines, e.g. `1 Bookborn Mouse`."
                    }
                  }
                }
              }
            }
          }
        },
        "x-nav": "Library assignments",
        "x-example": "/library-assignments"
      }
    },
    "/relic-hunter-hints": {
      "x-data-file": true,
      "get": {
        "summary": "Get Relic Hunter Hints",
        "description": "Hints for each Relic Hunter location, keyed by location ID.",
        "tags": [
          "Relic Hunter"
        ],
        "responses": {
          "200": {
            "description": "Relic Hunter hints by location",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "location": {
                      "type": "string",
                      "description": "The location ID."
                    },
                    "hints": {
                      "type": "array",
                      "description": "The array of hints for the location."
                    }
                  }
                }
              }
            }
          }
        },
        "x-example": "/relic-hunter-hints",
        "x-nav": "Location hints"
      }
    },
    "/scrambles": {
      "x-data-file": true,
      "get": {
        "summary": "Get Scrambles quotes",
        "description": "### Response\n\nAn array of quote strings.",
        "tags": [
          "Scrambles"
        ],
        "responses": {
          "200": {
            "description": "All Scrambles quotes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array"
                }
              }
            }
          }
        },
        "x-example": "/scrambles",
        "x-nav": "All quotes"
      }
    },
    "/trap-special-effects": {
      "x-data-file": true,
      "get": {
        "summary": "Get trap special effects",
        "tags": [
          "Trap Special Effects"
        ],
        "responses": {
          "200": {
            "description": "Bases with special effects, globally and by location",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "all": {
                      "type": "array",
                      "description": "Base types with a special effect anywhere."
                    },
                    "[location]": {
                      "type": "array",
                      "description": "Keyed by location slug. Base types with a special effect at that location."
                    }
                  }
                }
              }
            }
          }
        },
        "x-example": "/trap-special-effects",
        "x-nav": "Trap special effects"
      }
    },
    "/mhct/mappings": {
      "get": {
        "summary": "Get MHCT mappings",
        "description": "Game IDs and type slugs mapped to the IDs MHCT uses.",
        "tags": [
          "MHCT"
        ],
        "responses": {
          "200": {
            "description": "HitGrab to MHCT ID mappings",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "mice": {
                      "type": "object",
                      "description": "Mouse ID → MHCT mouse ID."
                    },
                    "items": {
                      "type": "object",
                      "description": "Item ID → MHCT item ID."
                    },
                    "type": {
                      "type": "object",
                      "description": "Type slug → ID mappings."
                    }
                  }
                }
              }
            }
          }
        },
        "x-example": "/mhct/mappings",
        "x-nav": "Mappings"
      }
    },
    "/mhct/convertibles": {
      "get": {
        "summary": "Get all convertibles",
        "description": "Every convertible item and its possible contents. For one convertible, use [`/mhct/convertibles/:id`](#get-convertible-contents).",
        "tags": [
          "MHCT"
        ],
        "responses": {
          "200": {
            "description": "Convertible contents from MHCT",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "integer",
                        "description": "Item ID."
                      },
                      "type": {
                        "type": "string",
                        "description": "Item type (slug)."
                      },
                      "mhct_id": {
                        "type": "integer",
                        "description": "MHCT item ID."
                      },
                      "name": {
                        "type": "string",
                        "description": "Item name."
                      },
                      "convertibles": {
                        "type": "array",
                        "description": "Possible rewards, each with `item`, `min_item_quantity`, `max_item_quantity`, `single_opens`, and `times_with_any`."
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-example": "/mhct/convertibles",
        "x-nav": "All convertibles"
      }
    },
    "/mhct/reverse-convertibles": {
      "get": {
        "summary": "Get reverse convertibles",
        "description": "The inverse of [`/mhct/convertibles`](#get-all-convertibles) — for each reward item, the convertibles it can come from.",
        "tags": [
          "MHCT"
        ],
        "responses": {
          "200": {
            "description": "The convertibles each item comes from",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "string",
                        "description": "Item ID."
                      },
                      "type": {
                        "type": "string",
                        "description": "Item type (slug)."
                      },
                      "mhct_id": {
                        "type": "integer",
                        "description": "MHCT item ID."
                      },
                      "name": {
                        "type": "string",
                        "description": "Item name."
                      },
                      "convertibles": {
                        "type": "array",
                        "description": "Convertibles this item drops from, each with `convertible`, `total`, `total_items`, `single_opens`, `times_with_any`, and quantity fields."
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-example": "/mhct/reverse-convertibles",
        "x-nav": "Reverse convertibles"
      }
    },
    "/mhct/mapper": {
      "get": {
        "summary": "Get mapper",
        "description": "Every treasure map and the mice that appear on it, with how often.",
        "tags": [
          "MHCT"
        ],
        "responses": {
          "200": {
            "description": "Treasure map data from MHCT",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "mhct_id": {
                        "type": "integer",
                        "description": "MHCT map ID."
                      },
                      "name": {
                        "type": "string",
                        "description": "Map name."
                      },
                      "mice": {
                        "type": "array",
                        "description": "Mice on the map, each with `id`, `type`, `name`, `rate` (out of 10,000), `seen`, and `total`."
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-example": "/mhct/mapper",
        "x-nav": "Mapper"
      }
    },
    "/mhct/reverse-mapper": {
      "get": {
        "summary": "Get reverse mapper",
        "description": "For each mouse, the maps it can appear on along with appearance rates.",
        "tags": [
          "MHCT"
        ],
        "responses": {
          "200": {
            "description": "The maps each mouse appears on",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "integer",
                        "description": "Mouse ID."
                      },
                      "type": {
                        "type": "string",
                        "description": "Mouse type (slug)."
                      },
                      "mhct_id": {
                        "type": "integer",
                        "description": "MHCT mouse ID."
                      },
                      "name": {
                        "type": "string",
                        "description": "Mouse name."
                      },
                      "maps": {
                        "type": "array",
                        "description": "Maps the mouse appears on, each with `map`, `rate` (out of 10,000), `seen`, and `total`."
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-example": "/mhct/reverse-mapper",
        "x-nav": "Reverse mapper"
      }
    },
    "/marketplace-hidden-items": {
      "x-data-file": true,
      "get": {
        "summary": "Get hidden Marketplace items",
        "description": "Items MouseHunt Improved hides in the Marketplace, each with `id` and `name`.",
        "tags": [
          "Items"
        ],
        "responses": {
          "200": {
            "description": "Items MouseHunt Improved hides in the Marketplace",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array"
                }
              }
            }
          }
        },
        "x-example": "/marketplace-hidden-items",
        "x-nav": "Hidden Marketplace items"
      }
    },
    "/upscaled-images": {
      "x-data-file": true,
      "get": {
        "summary": "Get upscaled images",
        "description": "Higher resolution or transparent versions of game images, keyed by the original image's path under `https://www.mousehuntgame.com/images/`.",
        "tags": [
          "Items"
        ],
        "responses": {
          "200": {
            "description": "Higher resolution versions of game images",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        },
        "x-example": "/upscaled-images",
        "x-nav": "Upscaled images"
      }
    },
    "/openapi": {
      "x-data-file": true,
      "get": {
        "summary": "Get the OpenAPI spec",
        "description": "The API contract as an OpenAPI 3.1 document: every endpoint, its parameters and response shapes, and every data file. Also available at `/openapi.json`.",
        "tags": [
          "Versions"
        ],
        "responses": {
          "200": {
            "description": "This OpenAPI document",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        },
        "x-example": "/openapi",
        "x-nav": "OpenAPI spec"
      }
    },
    "/map/groups": {
      "get": {
        "summary": "Treasure map mouse groups (legacy)",
        "description": "The `map-groups.json` data file, served as-is. Kept for existing clients; not shown in the docs.",
        "x-internal": true,
        "responses": {
          "200": {
            "description": "Treasure map mouse groups (legacy)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/ultimate-checkmark": {
      "x-data-file": true,
      "get": {
        "summary": "Ultimate Checkmark categories (legacy)",
        "description": "The `ultimate-checkmark.json` data file, served as-is. Kept for existing clients; not shown in the docs.",
        "x-internal": true,
        "responses": {
          "200": {
            "description": "Ultimate Checkmark categories (legacy)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array"
                }
              }
            }
          }
        }
      }
    },
    "/mhct-item/{id}": {
      "get": {
        "summary": "Older name for /mhct/item/:id",
        "description": "The same as `/mhct/item/:id`. Kept for existing clients; not shown in the docs.",
        "tags": [
          "MHCT"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Item ID or type, optionally followed by an MHCT time filter, e.g. `114-1_month`."
          }
        ],
        "x-internal": true,
        "responses": {
          "200": {
            "description": "The same as `/mhct/item/:id`"
          }
        }
      }
    },
    "/mhct-redirect/{id}": {
      "get": {
        "summary": "Older name for /mhct/redirect/:id",
        "description": "The same as `/mhct/redirect/:id`. Kept for existing clients; not shown in the docs.",
        "tags": [
          "MHCT"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Mouse ID or type, optionally followed by an MHCT time filter, e.g. `948-3_months` or `948-hlwn_22`. Defaults to all time."
          }
        ],
        "x-internal": true,
        "responses": {
          "200": {
            "description": "The same as `/mhct/redirect/:id`"
          }
        }
      }
    },
    "/mhct-redirect-item/{id}": {
      "get": {
        "summary": "Older name for /mhct/redirect/item/:id",
        "description": "The same as `/mhct/redirect/item/:id`. Kept for existing clients; not shown in the docs.",
        "tags": [
          "MHCT"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Item ID or type, optionally followed by an MHCT time filter, e.g. `114-1_month`."
          }
        ],
        "x-internal": true,
        "responses": {
          "200": {
            "description": "The same as `/mhct/redirect/item/:id`"
          }
        }
      }
    },
    "/convertible/{id}": {
      "get": {
        "summary": "Older name for /mhct/convertibles/:id",
        "description": "The same as `/mhct/convertibles/:id`. Kept for existing clients; not shown in the docs.",
        "tags": [
          "MHCT"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Item ID or type."
          }
        ],
        "x-internal": true,
        "responses": {
          "200": {
            "description": "The same as `/mhct/convertibles/:id`"
          }
        }
      }
    },
    "/maps-for-mouse/{id}": {
      "get": {
        "summary": "Older name for /map/mouse/:id",
        "description": "The same as `/map/mouse/:id`. Kept for existing clients; not shown in the docs.",
        "tags": [
          "Maps"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Mouse ID or type."
          },
          {
            "name": "include_retired",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            },
            "description": "Include retired content: maps and items MHCT marks `(Retired)`, and items the game marks `inactive` or `removed`. Left out by default."
          }
        ],
        "x-internal": true,
        "responses": {
          "200": {
            "description": "The same as `/map/mouse/:id`"
          }
        }
      }
    },
    "/map-relations": {
      "get": {
        "summary": "Older name for /map/relations",
        "description": "The same as `/map/relations`. Kept for existing clients; not shown in the docs.",
        "tags": [
          "Maps"
        ],
        "x-internal": true,
        "responses": {
          "200": {
            "description": "The same as `/map/relations`"
          }
        }
      }
    },
    "/map-relations/{id}": {
      "get": {
        "summary": "Older name for /map/relations/:id",
        "description": "The same as `/map/relations/:id`. Kept for existing clients; not shown in the docs.",
        "tags": [
          "Maps"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Scroll case, chest, or map."
          }
        ],
        "x-internal": true,
        "responses": {
          "200": {
            "description": "The same as `/map/relations/:id`"
          }
        }
      }
    },
    "/community-map-data": {
      "x-data-file": true,
      "get": {
        "summary": "Older name for /map/community",
        "description": "The same as `/map/community`. Kept for existing clients; not shown in the docs.",
        "tags": [
          "Maps"
        ],
        "x-internal": true,
        "responses": {
          "200": {
            "description": "The same as `/map/community`"
          }
        }
      }
    },
    "/scrolls-to-maps": {
      "x-data-file": true,
      "get": {
        "summary": "Older name for /map/scrolls",
        "description": "The same as `/map/scrolls`. Kept for existing clients; not shown in the docs.",
        "tags": [
          "Maps"
        ],
        "x-internal": true,
        "responses": {
          "200": {
            "description": "The same as `/map/scrolls`"
          }
        }
      }
    },
    "/mhct-mappings": {
      "x-data-file": true,
      "get": {
        "summary": "Older name for /mhct/mappings",
        "description": "The same as `/mhct/mappings`. Kept for existing clients; not shown in the docs.",
        "tags": [
          "MHCT"
        ],
        "x-internal": true,
        "responses": {
          "200": {
            "description": "The same as `/mhct/mappings`"
          }
        }
      }
    },
    "/mhct-convertibles": {
      "x-data-file": true,
      "get": {
        "summary": "Older name for /mhct/convertibles",
        "description": "The same as `/mhct/convertibles`. Kept for existing clients; not shown in the docs.",
        "tags": [
          "MHCT"
        ],
        "x-internal": true,
        "responses": {
          "200": {
            "description": "The same as `/mhct/convertibles`"
          }
        }
      }
    },
    "/mhct-reverse-convertibles": {
      "x-data-file": true,
      "get": {
        "summary": "Older name for /mhct/reverse-convertibles",
        "description": "The same as `/mhct/reverse-convertibles`. Kept for existing clients; not shown in the docs.",
        "tags": [
          "MHCT"
        ],
        "x-internal": true,
        "responses": {
          "200": {
            "description": "The same as `/mhct/reverse-convertibles`"
          }
        }
      }
    },
    "/mhct-mapper": {
      "x-data-file": true,
      "get": {
        "summary": "Older name for /mhct/mapper",
        "description": "The same as `/mhct/mapper`. Kept for existing clients; not shown in the docs.",
        "tags": [
          "MHCT"
        ],
        "x-internal": true,
        "responses": {
          "200": {
            "description": "The same as `/mhct/mapper`"
          }
        }
      }
    },
    "/mhct-reverse-mapper": {
      "x-data-file": true,
      "get": {
        "summary": "Older name for /mhct/reverse-mapper",
        "description": "The same as `/mhct/reverse-mapper`. Kept for existing clients; not shown in the docs.",
        "tags": [
          "MHCT"
        ],
        "x-internal": true,
        "responses": {
          "200": {
            "description": "The same as `/mhct/reverse-mapper`"
          }
        }
      }
    },
    "/map-groups": {
      "x-data-file": true,
      "get": {
        "summary": "Older name for /map/groups",
        "description": "The same as `/map/groups`. Kept for existing clients; not shown in the docs.",
        "x-internal": true,
        "responses": {
          "200": {
            "description": "The same as `/map/groups`"
          }
        }
      }
    }
  },
  "components": {
    "pathItems": {
      "AttractionMeta": {
        "get": {
          "summary": "Attraction source provenance, sample sizes, coverage and thresholds",
          "responses": {
            "200": {
              "description": "Source timestamps, thresholds, exclusions, selected population counts, and population metadata keyed by location, stage, cheese and charm.",
              "content": {
                "application/json": {
                  "schema": {
                    "type": "object",
                    "required": [
                      "mh_tools",
                      "mhct",
                      "population_counts",
                      "populations"
                    ]
                  }
                }
              }
            }
          }
        }
      },
      "Attraction": {
        "get": {
          "summary": "Query attraction rates by location, stage, cheese, charm, and mouse",
          "description": "MH-Tools populations take precedence; MHCT fills missing setups. See `/attraction/meta` for provenance and sample sizes. Filters combine with AND across dimensions and OR within repeated parameters. Keeps the full hierarchy and original percentages; no matches returns `{}`. Empty values return `400`.",
          "parameters": [
            {
              "name": "location",
              "in": "query",
              "description": "Environment slug, e.g. bazaar or cursed_city. Case-insensitive. Repeat this parameter for multiple values; commas are literal.",
              "style": "form",
              "explode": true,
              "schema": {
                "type": "array",
                "items": {
                  "type": "string",
                  "minLength": 1
                }
              }
            },
            {
              "name": "stage",
              "in": "query",
              "description": "Exact stage name, or - for no stage. URL-encode spaces and punctuation. Case-insensitive. Repeat this parameter for multiple values; commas are literal.",
              "style": "form",
              "explode": true,
              "schema": {
                "type": "array",
                "items": {
                  "type": "string",
                  "minLength": 1
                }
              }
            },
            {
              "name": "cheese",
              "in": "query",
              "description": "Cheese type slug. Case-insensitive. Repeat this parameter for multiple values; commas are literal.",
              "style": "form",
              "explode": true,
              "schema": {
                "type": "array",
                "items": {
                  "type": "string",
                  "minLength": 1
                }
              }
            },
            {
              "name": "charm",
              "in": "query",
              "description": "Charm type slug, or - for no charm. Case-insensitive. Repeat this parameter for multiple values; commas are literal.",
              "style": "form",
              "explode": true,
              "schema": {
                "type": "array",
                "items": {
                  "type": "string",
                  "minLength": 1
                }
              }
            },
            {
              "name": "mouse",
              "in": "query",
              "description": "Mouse type slug. Case-insensitive. Repeat this parameter for multiple values; commas are literal.",
              "style": "form",
              "explode": true,
              "schema": {
                "type": "array",
                "items": {
                  "type": "string",
                  "minLength": 1
                }
              }
            },
            {
              "name": "v",
              "in": "query",
              "description": "Optional cache token; not a filter.",
              "schema": {
                "type": "string"
              }
            }
          ],
          "responses": {
            "200": {
              "description": "Location → stage → cheese → charm → mouse → percentage.",
              "headers": {
                "ETag": {
                  "schema": {
                    "type": "string"
                  }
                }
              },
              "content": {
                "application/json": {
                  "schema": {
                    "type": "object",
                    "description": "Keyed by location.",
                    "additionalProperties": {
                      "type": "object",
                      "description": "Keyed by stage.",
                      "additionalProperties": {
                        "type": "object",
                        "description": "Keyed by cheese.",
                        "additionalProperties": {
                          "type": "object",
                          "description": "Keyed by charm.",
                          "additionalProperties": {
                            "type": "object",
                            "description": "Keyed by mouse.",
                            "additionalProperties": {
                              "type": "number",
                              "minimum": 0,
                              "maximum": 100
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            },
            "304": {
              "description": "Unchanged response (If-None-Match)."
            },
            "400": {
              "$ref": "#/components/responses/InvalidQuery"
            },
            "503": {
              "description": "Attraction dataset unavailable."
            }
          }
        }
      },
      "Items": {
        "get": {
          "summary": "List and query items",
          "parameters": [
            {
              "$ref": "#/components/parameters/CollectionQuery"
            }
          ],
          "responses": {
            "200": {
              "$ref": "#/components/responses/ItemCollection"
            },
            "400": {
              "$ref": "#/components/responses/InvalidQuery"
            }
          }
        }
      },
      "Item": {
        "get": {
          "summary": "Get an item by numeric ID or type slug",
          "parameters": [
            {
              "$ref": "#/components/parameters/Id"
            },
            {
              "$ref": "#/components/parameters/CollectionQuery"
            }
          ],
          "responses": {
            "200": {
              "$ref": "#/components/responses/Item"
            },
            "400": {
              "$ref": "#/components/responses/InvalidQuery"
            },
            "404": {
              "description": "Item not found"
            }
          }
        }
      },
      "Mice": {
        "get": {
          "summary": "List and query mice",
          "parameters": [
            {
              "$ref": "#/components/parameters/CollectionQuery"
            }
          ],
          "responses": {
            "200": {
              "$ref": "#/components/responses/MouseCollection"
            },
            "400": {
              "$ref": "#/components/responses/InvalidQuery"
            }
          }
        }
      },
      "Mouse": {
        "get": {
          "summary": "Get a mouse by numeric ID or type slug",
          "parameters": [
            {
              "$ref": "#/components/parameters/Id"
            },
            {
              "$ref": "#/components/parameters/CollectionQuery"
            }
          ],
          "responses": {
            "200": {
              "$ref": "#/components/responses/Mouse"
            },
            "400": {
              "$ref": "#/components/responses/InvalidQuery"
            },
            "404": {
              "description": "Mouse not found"
            }
          }
        }
      }
    },
    "parameters": {
      "Id": {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        },
        "description": "Numeric ID or type slug."
      },
      "CollectionQuery": {
        "name": "q",
        "in": "query",
        "schema": {
          "type": "string"
        },
        "description": "Case-insensitive partial text search."
      },
      "SearchQuery": {
        "name": "q",
        "in": "query",
        "required": true,
        "schema": {
          "type": "string"
        },
        "description": "Case-insensitive partial search term."
      },
      "SearchTypes": {
        "name": "types",
        "in": "query",
        "schema": {
          "type": "string",
          "example": "item,mouse"
        },
        "description": "Comma-separated: `item`, `location`, `mouse`. Defaults to all three."
      },
      "SearchLimit": {
        "name": "limit",
        "in": "query",
        "schema": {
          "type": "integer",
          "minimum": 0,
          "maximum": 50,
          "default": 10
        },
        "description": "Maximum number of results, 0 to 50. Defaults to 10."
      }
    },
    "responses": {
      "ItemCollection": {
        "description": "Item collection. Use `meta=true` for the paginated envelope.",
        "headers": {
          "ETag": {
            "schema": {
              "type": "string"
            }
          },
          "X-Total-Count": {
            "schema": {
              "type": "integer"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "type": "array",
              "items": {
                "$ref": "#/components/schemas/Item"
              }
            }
          }
        }
      },
      "MouseCollection": {
        "description": "Mouse collection. Use `meta=true` for the paginated envelope.",
        "headers": {
          "ETag": {
            "schema": {
              "type": "string"
            }
          },
          "X-Total-Count": {
            "schema": {
              "type": "integer"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "type": "array",
              "items": {
                "$ref": "#/components/schemas/Mouse"
              }
            }
          }
        }
      },
      "Item": {
        "type": "object",
        "required": [
          "id",
          "name",
          "type"
        ],
        "properties": {
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "classification": {
            "type": "string"
          },
          "description": {
            "type": "string"
          }
        },
        "additionalProperties": true,
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Item"
            }
          }
        }
      },
      "Mouse": {
        "type": "object",
        "required": [
          "id",
          "name",
          "type"
        ],
        "properties": {
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "group": {
            "type": "string"
          },
          "subgroup": {
            "type": "string"
          },
          "points": {
            "type": "integer"
          },
          "gold": {
            "type": "integer"
          }
        },
        "additionalProperties": true,
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Mouse"
            }
          }
        }
      },
      "Facets": {
        "type": "object",
        "required": [
          "facets",
          "meta"
        ],
        "properties": {
          "facets": {
            "type": "object",
            "additionalProperties": {
              "type": "array",
              "items": {
                "type": "object",
                "required": [
                  "count",
                  "value"
                ],
                "properties": {
                  "count": {
                    "type": "integer"
                  },
                  "value": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "meta": {
            "type": "object",
            "properties": {
              "total": {
                "type": "integer"
              }
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "facets": {
                  "type": "object",
                  "description": "Keyed by facet name. Each value is an array of `{ count, value }` pairs, sorted by count."
                },
                "meta": {
                  "type": "object",
                  "description": "Contains `total`, the number of records in the collection."
                }
              }
            }
          }
        }
      },
      "InvalidQuery": {
        "description": "Invalid query parameter",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "Item": {
        "type": "object",
        "required": [
          "id",
          "name",
          "type"
        ],
        "properties": {
          "id": {
            "type": "integer"
          },
          "type": {
            "type": "string",
            "description": "Item type (slug)."
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "classification": {
            "type": "string",
            "description": "e.g. `bait`, `weapon`, `trinket`."
          },
          "tags": {
            "type": "array"
          },
          "environment": {
            "type": "array",
            "description": "Location types where the item is available."
          },
          "images": {
            "type": "object",
            "description": "Item image URLs."
          },
          "is_limited_edition": {
            "type": "boolean"
          },
          "is_givable": {
            "type": "boolean",
            "description": "Whether the item can be given to other hunters."
          },
          "is_tradable": {
            "type": "boolean"
          },
          "is_convertible": {
            "type": "boolean",
            "description": "Whether the item can be opened/converted."
          },
          "is_smashable": {
            "type": "boolean",
            "description": "Whether the item breaks down into parts with the Hunter’s Hammer."
          },
          "is_potion": {
            "type": "boolean"
          },
          "is_skin": {
            "type": "boolean",
            "description": "Whether the item is a trap skin."
          },
          "is_charm": {
            "type": "boolean"
          },
          "is_quantity_limited": {
            "type": "boolean"
          },
          "has_stats": {
            "type": "object",
            "description": "Item stats (power, luck, etc.) when applicable."
          },
          "parts": {
            "type": "object",
            "description": "Parts the item breaks down into when smashed. Empty for items that can’t be smashed."
          },
          "quantity_limit": {
            "type": "integer",
            "description": "Most of the item a hunter can hold, or `0` for no limit."
          },
          "category": {
            "type": "string",
            "description": "e.g. `Cheese`, `Trap Parts`. Only present on some items."
          },
          "status": {
            "type": "string",
            "description": "`active`, `inactive`, or `removed`. Only present on some items."
          },
          "action_verb": {
            "type": "string",
            "description": "Verb on the item's action button, e.g. `Open`. Only present on some items."
          },
          "button_text": {
            "type": "string",
            "description": "Text on the item’s action button. Only present on some items."
          },
          "message": {
            "type": "string",
            "description": "Plain-text message shown when the item is used. Only present on some items."
          },
          "page_text_front": {
            "type": "string",
            "description": "Plain-text front of a torn page or similar item. Pairs with `page_text_back`, and with `images.page_front` / `images.page_back`."
          },
          "required_title": {
            "type": "string",
            "description": "Minimum hunter title needed for the item. Display name in `required_title_formatted`."
          },
          "consume_method": {
            "type": "string",
            "description": "How a charm gets used up: `always`, `catch`, `custom`, `encounter`, `fail_to_attract`, `fail_to_catch`, or `stale_or_encounter`. The game's wording is in `consume_method_formatted`."
          },
          "golden_shield_seconds": {
            "type": "integer",
            "description": "Golden Shield time the item grants, in seconds. Readable version (e.g. `1 month`) in `golden_shield_seconds_formatted`."
          },
          "recipes": {
            "type": "array",
            "description": "Potion recipes (`input`, `output`, `gold_cost`, `title_required`). Only present on potions; [`/potions`](/potions) has the same data with item IDs."
          }
        },
        "additionalProperties": true
      },
      "Mouse": {
        "type": "object",
        "required": [
          "id",
          "name",
          "type"
        ],
        "properties": {
          "id": {
            "type": "integer"
          },
          "type": {
            "type": "string",
            "description": "Mouse type (slug)."
          },
          "name": {
            "type": "string"
          },
          "abbreviated_name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "points": {
            "type": "integer",
            "description": "Points awarded for catching the mouse."
          },
          "points_formatted": {
            "type": "string",
            "description": "Points, comma-formatted."
          },
          "gold": {
            "type": "integer",
            "description": "Gold awarded for catching the mouse."
          },
          "gold_formatted": {
            "type": "string",
            "description": "Gold, comma-formatted."
          },
          "group": {
            "type": "string",
            "description": "Group name, e.g. `Mountain Mice`."
          },
          "group_id": {
            "type": "string",
            "description": "Group type, e.g. `mountain`."
          },
          "subgroup": {
            "type": "string",
            "description": "Subgroup name. Empty if none."
          },
          "subgroup_id": {
            "type": "string",
            "description": "Subgroup type. Empty if none."
          },
          "images": {
            "type": "object",
            "properties": {
              "thumbnail": {
                "type": "string"
              },
              "silhouette_thumbnail": {
                "type": "string"
              },
              "medium": {
                "type": "string"
              },
              "silhouette_medium": {
                "type": "string"
              },
              "large": {
                "type": "string"
              },
              "silhouette_large": {
                "type": "string"
              },
              "square": {
                "type": "string"
              },
              "is_landscape": {
                "type": "boolean"
              }
            }
          },
          "has_weaknesses": {
            "type": "boolean",
            "description": "Whether the mouse has any effective weaknesses."
          },
          "weaknesses": {
            "type": "object",
            "properties": {
              "effective": {
                "type": "array",
                "description": "Power types the mouse is weak to."
              }
            }
          },
          "environments": {
            "type": "array",
            "description": "Location types where the mouse is found, e.g. `mountain`."
          },
          "minlucks": {
            "type": "object",
            "properties": {
              "arcane": {
                "type": "integer"
              },
              "draconic": {
                "type": "integer"
              },
              "forgotten": {
                "type": "integer"
              },
              "hydro": {
                "type": "integer"
              },
              "physical": {
                "type": "integer"
              },
              "shadow": {
                "type": "integer"
              },
              "tactical": {
                "type": "integer"
              },
              "law": {
                "type": "integer"
              },
              "rift": {
                "type": "integer"
              }
            }
          },
          "wisdom": {
            "type": "integer",
            "description": "Wisdom gained for catching the mouse."
          },
          "effectivenesses": {
            "type": "object",
            "properties": {
              "power": {
                "type": "integer",
                "description": "The mouse's power."
              },
              "arcane": {
                "type": "integer"
              },
              "draconic": {
                "type": "integer"
              },
              "forgotten": {
                "type": "integer"
              },
              "hydro": {
                "type": "integer"
              },
              "physical": {
                "type": "integer"
              },
              "shadow": {
                "type": "integer"
              },
              "tactical": {
                "type": "integer"
              },
              "law": {
                "type": "integer"
              },
              "rift": {
                "type": "integer"
              }
            }
          }
        },
        "additionalProperties": true
      },
      "SearchResponse": {
        "type": "object",
        "required": [
          "data",
          "meta"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "id",
                "name",
                "resource",
                "type"
              ],
              "properties": {
                "id": {
                  "type": "integer"
                },
                "image": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "resource": {
                  "enum": [
                    "item",
                    "mouse"
                  ]
                },
                "type": {
                  "type": "string"
                }
              }
            }
          },
          "meta": {
            "type": "object",
            "properties": {
              "count": {
                "type": "integer"
              },
              "limit": {
                "type": "integer"
              },
              "total": {
                "type": "integer"
              }
            }
          }
        }
      },
      "Facets": {
        "type": "object",
        "required": [
          "facets",
          "meta"
        ],
        "properties": {
          "facets": {
            "type": "object",
            "additionalProperties": {
              "type": "array",
              "items": {
                "type": "object",
                "required": [
                  "count",
                  "value"
                ],
                "properties": {
                  "count": {
                    "type": "integer"
                  },
                  "value": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "meta": {
            "type": "object",
            "properties": {
              "total": {
                "type": "integer"
              }
            }
          }
        }
      },
      "Status": {
        "type": "object",
        "required": [
          "capabilities",
          "datasets",
          "status"
        ],
        "properties": {
          "status": {
            "const": "ok"
          },
          "capabilities": {
            "type": "object",
            "additionalProperties": {
              "type": "boolean"
            }
          },
          "datasets": {
            "type": "object",
            "additionalProperties": {
              "type": "object",
              "properties": {
                "count": {
                  "type": "integer"
                },
                "version": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            }
          }
        }
      },
      "MouseLoot": {
        "type": "object",
        "required": [
          "location",
          "item_id",
          "item_name",
          "catches",
          "drop_likelihood",
          "drops_per_catch",
          "avg_qty",
          "min",
          "max",
          "baseline",
          "lift"
        ],
        "properties": {
          "location": {
            "type": "string",
            "description": "MHCT location name."
          },
          "item_id": {
            "type": "integer"
          },
          "item_name": {
            "type": "string"
          },
          "catches": {
            "type": "integer",
            "description": "Catches of the mouse at the location."
          },
          "drop_likelihood": {
            "type": "number",
            "description": "Percentage of catches that dropped the item."
          },
          "drops_per_catch": {
            "type": "number",
            "description": "Total quantity dropped ÷ catches."
          },
          "avg_qty": {
            "type": "number",
            "description": "Average quantity per drop."
          },
          "min": {
            "type": "integer",
            "description": "Smallest quantity in a single drop."
          },
          "max": {
            "type": "integer",
            "description": "Largest quantity in a single drop."
          },
          "baseline": {
            "type": "number",
            "description": "Average `drop_likelihood` for the item across the mice at the location, as a percentage."
          },
          "lift": {
            "type": "number",
            "description": "`drop_likelihood` ÷ `baseline`. High for mouse-specific loot."
          }
        }
      },
      "ItemDropper": {
        "type": "object",
        "required": [
          "mouse_id",
          "mouse_name",
          "location",
          "catches",
          "drop_likelihood",
          "drops_per_catch",
          "avg_qty",
          "min",
          "max",
          "baseline",
          "lift"
        ],
        "properties": {
          "mouse_id": {
            "type": "integer"
          },
          "mouse_name": {
            "type": "string"
          },
          "location": {
            "type": "string",
            "description": "MHCT location name."
          },
          "catches": {
            "type": "integer",
            "description": "Catches of the mouse at the location."
          },
          "drop_likelihood": {
            "type": "number",
            "description": "Percentage of catches that dropped the item."
          },
          "drops_per_catch": {
            "type": "number",
            "description": "Total quantity dropped ÷ catches."
          },
          "avg_qty": {
            "type": "number",
            "description": "Average quantity when the item dropped."
          },
          "min": {
            "type": "integer",
            "description": "Smallest quantity in a single drop."
          },
          "max": {
            "type": "integer",
            "description": "Largest quantity in a single drop."
          },
          "baseline": {
            "type": "number",
            "description": "Average `drop_likelihood` for the item across the mice at the location, as a percentage."
          },
          "lift": {
            "type": "number",
            "description": "`drop_likelihood` ÷ `baseline`."
          }
        }
      },
      "Title": {
        "type": "object",
        "required": [
          "id",
          "order",
          "name"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Title type, e.g. `master`."
          },
          "order": {
            "type": "integer",
            "description": "Order from Novice upwards."
          },
          "title_id": {
            "type": "integer",
            "description": "The game's numeric title ID."
          },
          "name": {
            "type": "string",
            "description": "Display name, e.g. `Lord/Lady`."
          },
          "name_female": {
            "type": "string",
            "description": "Name for female hunters."
          },
          "name_male": {
            "type": "string",
            "description": "Name for male hunters."
          },
          "icon": {
            "type": "string"
          },
          "icon_border": {
            "type": "string",
            "description": "The icon with a border, as shown in the game."
          },
          "crafting_slots": {
            "type": "integer",
            "description": "How many items can be combined while crafting."
          },
          "description": {
            "type": "string",
            "description": "What reaching the title unlocks, one line per point."
          }
        }
      },
      "PowerType": {
        "type": "object",
        "required": [
          "id",
          "type",
          "name"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Lowercase name, e.g. `hydro`, as used by items and mastery data."
          },
          "type": {
            "type": "string",
            "description": "The game's code, e.g. `hdr`."
          },
          "name": {
            "type": "string",
            "description": "Display name, e.g. `Hydro`."
          },
          "icon": {
            "type": "string"
          }
        }
      },
      "Scoreboard": {
        "type": "object",
        "required": [
          "id",
          "name",
          "group",
          "weekly"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Scoreboard ID, as the game uses it."
          },
          "name": {
            "type": "string",
            "description": "Display name."
          },
          "group": {
            "type": "string",
            "description": "Group the board is listed under, e.g. `General` or `Mouse Stats - Iceberg`."
          },
          "weekly": {
            "type": "boolean",
            "description": "Whether the board also has a weekly ranking."
          }
        }
      },
      "ItemRef": {
        "type": "object",
        "required": [
          "id",
          "type",
          "name"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "description": "Item ID, or `0` if the item isn't known."
          },
          "type": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "quantity": {
            "type": "integer"
          }
        }
      },
      "Recipe": {
        "type": "object",
        "required": [
          "type",
          "name",
          "result",
          "quantity"
        ],
        "properties": {
          "type": {
            "type": "string",
            "description": "Recipe type."
          },
          "name": {
            "type": "string",
            "description": "Recipe name."
          },
          "status": {
            "type": "string",
            "description": "`active` or `inactive`."
          },
          "image": {
            "type": "string"
          },
          "result": {
            "$ref": "#/components/schemas/ItemRef",
            "description": "The item the recipe makes."
          },
          "quantity": {
            "type": "integer",
            "description": "How many of the item one craft makes."
          },
          "max_inventory_quantity": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Most of the item a hunter can hold, or 0 for no limit."
          },
          "allow_instant_unlock": {
            "type": "boolean"
          },
          "unlock": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "minimum": {
                "type": "integer",
                "description": "How many of the tasks must be completed."
              },
              "tasks": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "mode": {
                      "type": "string",
                      "description": "e.g. `catch`, `lootdrop`, `baitstale`, `add_item`."
                    },
                    "number": {
                      "type": "integer",
                      "description": "How many times the task must be done."
                    },
                    "requirements": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "kind": {
                            "type": "string",
                            "description": "`mouse`, `weapon`, `base`, `bait`, `loot`, or `add_item`."
                          },
                          "id": {
                            "type": "integer",
                            "description": "Item or mouse ID, or 0 for `any`."
                          },
                          "type": {
                            "type": "string",
                            "description": "Item or mouse type, or `any`."
                          },
                          "name": {
                            "type": "string",
                            "description": "Item or mouse name."
                          }
                        }
                      },
                      "description": "What counts toward the task, e.g. catching a mouse or using a bait."
                    }
                  }
                }
              }
            },
            "description": "What unlocks the recipe, or `null` if it doesn't need unlocking."
          }
        }
      },
      "StorePack": {
        "type": "object",
        "required": [
          "type",
          "name",
          "items",
          "platforms"
        ],
        "properties": {
          "type": {
            "type": "string",
            "description": "Pack type."
          },
          "name": {
            "type": "string",
            "description": "Pack name."
          },
          "description": {
            "type": "string"
          },
          "image": {
            "type": "string"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ItemRef"
            },
            "description": "What the pack contains."
          },
          "golden_shield_seconds": {
            "type": "integer",
            "description": "Golden Shield time the pack adds, in seconds."
          },
          "limited_purchase_quantity": {
            "type": [
              "integer",
              "null"
            ],
            "description": "How many a hunter can buy, or 0 for no limit."
          },
          "display_order": {
            "type": "integer",
            "description": "Order in the store."
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Store tags, e.g. `best_value`."
          },
          "platforms": {
            "type": "object",
            "additionalProperties": {
              "type": "object",
              "properties": {
                "sku": {
                  "type": "string"
                },
                "price": {
                  "type": "string"
                },
                "categories": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              }
            },
            "description": "Price and SKU on each app store (`apple`, `google`)."
          }
        }
      },
      "AttractionPopulation": {
        "type": "object",
        "required": [
          "location",
          "stage",
          "cheese",
          "charm",
          "source",
          "mice"
        ],
        "properties": {
          "location": {
            "type": "string",
            "description": "Location type."
          },
          "location_name": {
            "type": "string"
          },
          "stage": {
            "type": "string",
            "description": "Stage name, or `-` for no stage."
          },
          "cheese": {
            "type": "string",
            "description": "Cheese type."
          },
          "cheese_name": {
            "type": "string"
          },
          "charm": {
            "type": "string",
            "description": "Charm type, or `-` for no charm."
          },
          "charm_name": {
            "type": "string",
            "description": "Charm name, empty for no charm."
          },
          "source": {
            "type": "string",
            "enum": [
              "mh-tools",
              "mhct"
            ],
            "description": "`mh-tools` or `mhct`."
          },
          "sample_size": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Hunts the rates are based on; `null` when the source doesn't report it."
          },
          "rate": {
            "type": "number",
            "description": "That mouse's attraction rate as a percentage. Only present when filtering by `mouse`."
          },
          "mice": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "type": {
                  "type": "string",
                  "description": "Mouse type."
                },
                "name": {
                  "type": "string",
                  "description": "Mouse name."
                },
                "rate": {
                  "type": "number",
                  "description": "Attraction rate as a percentage."
                }
              }
            },
            "description": "The mice attracted, highest rate first."
          }
        }
      },
      "Shop": {
        "type": "object",
        "required": [
          "id",
          "name",
          "items"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Location type."
          },
          "name": {
            "type": "string",
            "description": "Location name."
          },
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "id",
                "type",
                "name",
                "category",
                "gold_cost"
              ],
              "properties": {
                "id": {
                  "type": "integer"
                },
                "type": {
                  "type": "string",
                  "description": "Item type."
                },
                "name": {
                  "type": "string",
                  "description": "Item name."
                },
                "category": {
                  "type": "string",
                  "description": "The shop tab."
                },
                "gold_cost": {
                  "type": "integer",
                  "description": "Price in gold."
                },
                "refund": {
                  "type": "integer",
                  "description": "Gold refunded when the item is sold back."
                },
                "item_costs": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ItemRef"
                  },
                  "description": "Items it costs, besides gold."
                },
                "requirements": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ItemRef"
                  },
                  "description": "Items the hunter must own, including adventure progress items such as `complete_queso_river`."
                }
              }
            },
            "description": "What the shop sells."
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "const": "invalid_query"
              },
              "message": {
                "type": "string"
              }
            }
          }
        }
      }
    }
  }
}
