{
  "openapi": "3.1.0",
  "info": {
    "title": "Snowpack",
    "version": "1.0.0",
    "summary": "Mountain conditions, surveyed ski terrain, and United States weather, payable by the call in USDC.",
    "description": "Snowpack answers for a place. For a mountain that means the avalanche danger by aspect and elevation with its issuing zone, active alerts in full, land ownership beneath the point, the nearest reporting instrument, and the surveyed runs, lifts, buildings and forest of sixty-three ski resorts built from lidar where it has been flown. For anywhere in the United States it means a full weather report: current conditions, forty-eight hours ahead, ten days, and any active severe weather alerts.\n\nEvery answer can be bought one at a time over x402, with no account and no key. Avalanche danger, alerts, ski patrol lines and SOS are free to everyone whether they pay or not, because safety is not a product.\n\nAND THE WEATHER HAS A FREE CALL. GET /api/weather with no key and no payment answers the basics for any American place: the temperature, what it feels like, the wind and its bearing, the condition in words, and every active alert in full. The payment adds the week, the next forty-eight hours and every other figure.",
    "x-guidance": "Pay per call with x402: request the endpoint, take the 402, sign the authorization, request again with the payment header. Add ?pay=x402 to be told the price before paying.\n\nGET /api/weather?place=<any United States city, county, state or postcode> is the broadest: it answers for any American place by name at 0.01 USD, and answers the BASICS for nothing at all. A call with no key and no payment returns the place, the temperature, what it feels like, the wind and its bearing, the condition in words, and every active severe weather alert in full, because safety is never behind the paywall. The payment adds the week, the next forty-eight hours, the air and every other figure.\nGET /api/atlas?lat=&lon= or ?tile=z/x/y is the mountain answer.\nPOST /api/x402 {\"buy\":\"pro\"|\"api\"} buys a key instead, if you would rather hold one.\n\nThere are 2006 individually named and priced answers. GET /api/x402?offset=&limit= walks the catalogue, ?resource=<id> fetches one, ?resort=<id> filters to a mountain. Place names for weather are an open family: the catalogue lists the states and the large cities, and any other American place name works at the same price.",
    "contact": {
      "email": "api@snowpack.fyi",
      "url": "https://snowpack.fyi/docs/x402"
    },
    "license": {
      "name": "Proprietary"
    }
  },
  "servers": [
    {
      "url": "https://snowpack.fyi"
    }
  ],
  "x-catalogue": {
    "total": 2006,
    "index": "https://snowpack.fyi/api/x402",
    "page": "https://snowpack.fyi/api/x402?offset=0&limit=100",
    "byId": "https://snowpack.fyi/api/x402?resource=<id>"
  },
  "paths": {
    "/api/snow": {
      "get": {
        "operationId": "snow",
        "summary": "The snow tracker: every mountain ranked by new snow, base or what is coming",
        "description": "The snow tracker: every mountain in the catalogue, ranked by new snow in the last 24 hours, the last 7 days, base depth or the snow coming in the next day, by state, each figure labelled measured or modelled with its station and its age, and a mountain's own history. Without a key or a payment the answer is the headline sentence and the top five; a key or a one-cent payment opens the whole ranking, the state filter and a mountain's history. A single mountain's own row (?resort=) is always free. Inches, feet and Fahrenheit.",
        "tags": [
          "Snow"
        ],
        "x-payment-info": {
          "price": {
            "mode": "fixed",
            "currency": "USD",
            "amount": "0.010000"
          },
          "protocols": [
            {
              "x402": {}
            }
          ]
        },
        "parameters": [
          {
            "name": "view",
            "in": "query",
            "required": false,
            "description": "today (new snow in the last 24 hours, the default), week (7 days), base (depth), tomorrow (the next 24 hours) or season (since the first of October).",
            "schema": {
              "type": "string",
              "example": "today"
            }
          },
          {
            "name": "state",
            "in": "query",
            "required": false,
            "description": "A state or province, by name or code, for example \"Utah\" or \"CO\".",
            "schema": {
              "type": "string",
              "example": "Utah"
            }
          },
          {
            "name": "resort",
            "in": "query",
            "required": false,
            "description": "One mountain by id, for example \"alta\": its own row, free; with a key, its history too.",
            "schema": {
              "type": "string",
              "example": "alta"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "How many rows, up to every mountain.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 63,
              "example": 63
            }
          },
          {
            "name": "pay",
            "in": "query",
            "required": false,
            "description": "Set to x402 to be answered 402 with the price rather than served.",
            "schema": {
              "type": "string",
              "example": "x402"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The ranking",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SnowTracker"
                }
              }
            }
          },
          "402": {
            "description": "Payment Required"
          }
        }
      }
    },
    "/api/weather": {
      "get": {
        "operationId": "weather",
        "summary": "Weather anywhere in the United States, by name or by coordinate",
        "description": "A full weather report for an American place: current conditions with feels-like, wind chill and heat index, dew point, humidity, cloud, pressure and UV; forty-eight hours ahead; ten days of highs, lows, wind and sun times; and any active severe weather alerts in full. Ask by place name (a city, a county, a state, a postcode, a landmark) or by coordinate. Fahrenheit, miles per hour, inches and inches of mercury.\n\nA CALL WITH NO KEY AND NO PAYMENT IS ANSWERED, not refused: 200 with the place, the temperature, what it feels like, the wind and its bearing, the condition in words, whether it is daylight, and every active severe weather alert IN FULL. Safety is never behind the paywall. The answer carries tier: \"free\".\n\nA key or a payment adds the rest: the next forty-eight hours, ten days of highs, lows, wind, sun times and moon, the pressure, humidity, dew point, cloud and ultraviolet index, the air, the forecaster's paragraph, and how far apart the two analyses are. That answer carries tier: \"full\".\n\nAND THE POINT. A paid answer carries the reconciled figure: what the analyses computed, corrected by the instruments actually standing near that coordinate, with each of them named, what it read, how far away and how far above it stands, how old the reading is, and which were refused and in what words. A measured temperature inversion is reported when there is one. Where nothing is reporting, the point is absent rather than the analysis under a new name.",
        "tags": [
          "Weather"
        ],
        "x-payment-info": {
          "price": {
            "mode": "fixed",
            "currency": "USD",
            "amount": "0.010000"
          },
          "protocols": [
            {
              "x402": {}
            }
          ]
        },
        "parameters": [
          {
            "name": "place",
            "in": "query",
            "required": false,
            "description": "Any place in the United States, for example \"Denver, Colorado\", \"Harris County, Texas\" or \"Vermont\".",
            "schema": {
              "type": "string",
              "example": "Denver, Colorado"
            }
          },
          {
            "name": "lat",
            "in": "query",
            "required": false,
            "description": "Latitude in degrees, if asking by coordinate instead of by name.",
            "schema": {
              "type": "number",
              "format": "double",
              "minimum": -90,
              "maximum": 90,
              "example": 39.7392
            }
          },
          {
            "name": "lon",
            "in": "query",
            "required": false,
            "description": "Longitude in degrees.",
            "schema": {
              "type": "number",
              "format": "double",
              "minimum": -180,
              "maximum": 180,
              "example": -104.9903
            }
          },
          {
            "name": "pay",
            "in": "query",
            "required": false,
            "description": "Set to x402 to be answered 402 with the price rather than served.",
            "schema": {
              "type": "string",
              "example": "x402"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The report. tier: \"free\" with no key or payment, tier: \"full\" with one.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WeatherReport"
                }
              }
            }
          },
          "402": {
            "description": "Payment Required, only when ?pay=x402 asks to be told the price"
          },
          "404": {
            "description": "No such place in the United States"
          }
        }
      }
    },
    "/api/atlas": {
      "get": {
        "operationId": "atlas",
        "summary": "The atlas answer for a coordinate or a slippy tile",
        "description": "The whole atlas answer: avalanche danger by aspect and elevation with its issuing zone, active alerts in full, land ownership and boundary beneath the point, and the nearest reporting instrument.",
        "tags": [
          "Mountain"
        ],
        "x-payment-info": {
          "price": {
            "mode": "fixed",
            "currency": "USD",
            "amount": "0.020000"
          },
          "protocols": [
            {
              "x402": {}
            }
          ]
        },
        "parameters": [
          {
            "name": "lat",
            "in": "query",
            "required": false,
            "description": "Latitude in degrees.",
            "schema": {
              "type": "number",
              "format": "double",
              "minimum": -90,
              "maximum": 90,
              "example": 40.581
            }
          },
          {
            "name": "lon",
            "in": "query",
            "required": false,
            "description": "Longitude in degrees.",
            "schema": {
              "type": "number",
              "format": "double",
              "minimum": -180,
              "maximum": 180,
              "example": -111.655
            }
          },
          {
            "name": "tile",
            "in": "query",
            "required": false,
            "description": "A slippy tile as z/x/y, answered at the tile centre and cached by tile.",
            "schema": {
              "type": "string",
              "example": "12/845/1550"
            }
          },
          {
            "name": "pay",
            "in": "query",
            "required": false,
            "description": "Set to x402 to be answered 402 with the price rather than served.",
            "schema": {
              "type": "string",
              "example": "x402"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The atlas answer",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AtlasAnswer"
                }
              }
            }
          },
          "402": {
            "description": "Payment Required"
          }
        }
      }
    },
    "/api/resort": {
      "get": {
        "operationId": "resort",
        "summary": "The conditions card for one of the sixty-three resorts",
        "description": "The resort card: conditions, the forecast, the elevation bands and their provenance.",
        "tags": [
          "Mountain"
        ],
        "x-payment-info": {
          "price": {
            "mode": "fixed",
            "currency": "USD",
            "amount": "0.010000"
          },
          "protocols": [
            {
              "x402": {}
            }
          ]
        },
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "The resort id, for example \"alta\" or \"revelstoke\".",
            "schema": {
              "type": "string",
              "example": "alta"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The card",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "resort": {
                      "type": "string"
                    },
                    "conditions": {
                      "type": "object"
                    },
                    "bands": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "tier": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "resort"
                  ]
                }
              }
            }
          },
          "402": {
            "description": "Payment Required"
          }
        }
      }
    },
    "/api/features": {
      "get": {
        "operationId": "features",
        "summary": "The surveyed geometry of a resort",
        "description": "The surveyed geometry: runs with their difficulty and name, lifts with their type and stations, buildings, forest stands, roads and water. Open to everyone, no key and no payment.",
        "tags": [
          "Mountain"
        ],
        "security": [],
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "The resort id.",
            "schema": {
              "type": "string",
              "example": "alta"
            }
          },
          {
            "name": "radiusMi",
            "in": "query",
            "required": false,
            "description": "Radius in miles around the resort centre. Anything outside just under a mile to about seven and a half is clamped to it.",
            "schema": {
              "type": "number",
              "format": "double",
              "minimum": 0.95,
              "maximum": 7.5,
              "example": 3.73
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The survey",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "runs": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "lifts": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "buildings": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "forest": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  },
                  "required": [
                    "runs",
                    "lifts"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/dem": {
      "get": {
        "operationId": "dem",
        "summary": "One elevation tile",
        "description": "One elevation tile, lidar-derived where it has been flown. Open to everyone, no key and no payment.",
        "tags": [
          "Terrain"
        ],
        "security": [],
        "parameters": [
          {
            "name": "z",
            "in": "query",
            "required": true,
            "description": "Zoom.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 22,
              "example": 13
            }
          },
          {
            "name": "x",
            "in": "query",
            "required": true,
            "description": "Tile column.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "example": 1690
            }
          },
          {
            "name": "y",
            "in": "query",
            "required": true,
            "description": "Tile row.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "example": 3101
            }
          },
          {
            "name": "s",
            "in": "query",
            "required": false,
            "description": "Encoding: terrarium or mapboxrgb.",
            "schema": {
              "type": "string",
              "example": "terrarium"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A PNG elevation tile",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          }
        }
      }
    },
    "/api/station": {
      "get": {
        "operationId": "station",
        "summary": "One instrument, with its own readings",
        "description": "Everything one instrument is publishing right now: every figure it reports with its own unit, the sky it sees, the raw observation those figures were decoded from, where it stands and how high, and how much of the network reads it.",
        "tags": [
          "Instruments"
        ],
        "x-payment-info": {
          "price": {
            "mode": "fixed",
            "currency": "USD",
            "amount": "0.010000"
          },
          "protocols": [
            {
              "x402": {}
            }
          ]
        },
        "parameters": [
          {
            "name": "state",
            "in": "query",
            "required": true,
            "description": "The two letter state the instrument stands in.",
            "schema": {
              "type": "string",
              "example": "ut"
            }
          },
          {
            "name": "family",
            "in": "query",
            "required": true,
            "description": "Which network owns it: asos, rwis, dcp, coop or cocorahs.",
            "schema": {
              "type": "string",
              "example": "asos"
            }
          },
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "The instrument's own identifier in that network.",
            "schema": {
              "type": "string",
              "example": "KSLC"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The instrument and what it is reporting",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "network": {
                      "type": "string"
                    },
                    "family": {
                      "type": "string"
                    },
                    "state": {
                      "type": "string"
                    },
                    "at": {
                      "type": "object",
                      "description": "Where it stands: lat, lon, elevationFt, county and what it stands at."
                    },
                    "readings": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      },
                      "description": "Every figure it is publishing, each with its own unit."
                    },
                    "sky": {
                      "type": "object",
                      "description": "The sky it sees, where it reports one."
                    },
                    "observation": {
                      "type": "object",
                      "description": "The raw report those figures were decoded from."
                    },
                    "observedAt": {
                      "type": "string",
                      "description": "When the instrument took the reading."
                    },
                    "fetchedAt": {
                      "type": "string",
                      "description": "When this service read it, which is a different instant."
                    }
                  },
                  "required": [
                    "id",
                    "network",
                    "state"
                  ]
                }
              }
            }
          },
          "402": {
            "description": "Payment Required"
          },
          "404": {
            "description": "No instrument of that id in that state and family"
          }
        }
      }
    },
    "/api/fleet": {
      "get": {
        "operationId": "fleet",
        "summary": "The whole network in one answer",
        "description": "The whole network in one answer: every mountain named and placed, the 24 hour snowfall with its provenance, both reporting instruments with their distance, height and any reason a reading was set aside, the Snowpack Instrument lead in front of them, and the ranking. Priced at a discount to its parts on purpose: sixty-three resort cards bought one at a time is 63 cents and this is 25, because the whole picture costs one cached sweep rather than sixty-three.",
        "tags": [
          "Snow"
        ],
        "x-payment-info": {
          "price": {
            "mode": "fixed",
            "currency": "USD",
            "amount": "0.250000"
          },
          "protocols": [
            {
              "x402": {}
            }
          ]
        },
        "parameters": [],
        "responses": {
          "200": {
            "description": "Every mountain, ranked",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "generatedAt": {
                      "type": "string"
                    },
                    "resorts": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "coverage": {
                      "type": "object",
                      "description": "How many were reached, how many answered, and what was set aside with the reason."
                    }
                  },
                  "required": [
                    "resorts"
                  ]
                }
              }
            }
          },
          "402": {
            "description": "Payment Required"
          }
        }
      }
    },
    "/api/hires": {
      "get": {
        "operationId": "hires",
        "summary": "A fine elevation patch around a point",
        "description": "A high-resolution elevation patch around the point, at the finest posting the chain will answer.",
        "tags": [
          "Terrain"
        ],
        "x-payment-info": {
          "price": {
            "mode": "fixed",
            "currency": "USD",
            "amount": "0.010000"
          },
          "protocols": [
            {
              "x402": {}
            }
          ]
        },
        "parameters": [
          {
            "name": "lat",
            "in": "query",
            "required": true,
            "description": "Latitude.",
            "schema": {
              "type": "number",
              "format": "double",
              "minimum": -90,
              "maximum": 90,
              "example": 40.581
            }
          },
          {
            "name": "lon",
            "in": "query",
            "required": true,
            "description": "Longitude.",
            "schema": {
              "type": "number",
              "format": "double",
              "minimum": -180,
              "maximum": 180,
              "example": -111.655
            }
          },
          {
            "name": "spanFt",
            "in": "query",
            "required": false,
            "description": "Width of the patch in feet. Anything outside 210 to 3,360 is clamped to it, and the 402 names the coordinate asked for and the width that will actually be served, saying so where the clamp moved it.",
            "schema": {
              "type": "integer",
              "minimum": 210,
              "maximum": 3360,
              "example": 1680
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The patch",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "width": {
                      "type": "integer"
                    },
                    "height": {
                      "type": "integer"
                    },
                    "postM": {
                      "type": "number"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "number"
                      }
                    }
                  },
                  "required": [
                    "width",
                    "height"
                  ]
                }
              }
            }
          },
          "402": {
            "description": "Payment Required"
          }
        }
      }
    },
    "/api/conditions": {
      "get": {
        "operationId": "conditions",
        "summary": "One compact reading for every mountain in the catalogue, in a single request",
        "description": "A small row per ski area: its identity, its current conditions and its latest instrument reading. This exists so that sweeping a region does not mean one request per mountain, which from a phone on a lift is sixty-three round trips. Free, and deliberately small: enough to colour a map and label a marker, not a replacement for a per-mountain call. Inches, feet and Fahrenheit.",
        "tags": [
          "Snow"
        ],
        "security": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Every mountain, compactly",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConditionsRoll"
                }
              }
            }
          }
        }
      }
    },
    "/api/geocode": {
      "get": {
        "operationId": "geocode",
        "summary": "Turn a typed place into a coordinate, or a coordinate into a place",
        "description": "The same lookup the product's own search uses, so a name that resolves here opens the same place in the app. Give ?q to search, or ?lat and ?lon to name a point. Free.",
        "tags": [
          "Places"
        ],
        "security": [],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Free text to search for, for example \"Alta, Utah\".",
            "schema": {
              "type": "string",
              "example": "Alta, Utah"
            }
          },
          {
            "name": "lat",
            "in": "query",
            "required": false,
            "description": "Decimal degrees north, for a reverse lookup. Use with lon.",
            "schema": {
              "type": "number",
              "format": "double",
              "minimum": -90,
              "maximum": 90,
              "example": 40.5883
            }
          },
          {
            "name": "lon",
            "in": "query",
            "required": false,
            "description": "Decimal degrees east, negative in the Americas. Use with lat.",
            "schema": {
              "type": "number",
              "format": "double",
              "minimum": -180,
              "maximum": 180,
              "example": -111.6372
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The place, or the places that matched"
          },
          "400": {
            "description": "Neither a query nor a coordinate pair was given"
          }
        }
      }
    },
    "/api/boundaries": {
      "get": {
        "operationId": "boundaries",
        "summary": "State and country boundaries as GeoJSON",
        "description": "Political boundaries for drawing a map that can be read: without them a relief map with place dots on it is a texture with confetti on it. Free.",
        "tags": [
          "Places"
        ],
        "security": [],
        "parameters": [
          {
            "name": "set",
            "in": "query",
            "required": true,
            "description": "Which boundaries. The two the service holds; anything else is refused and the refusal names these.",
            "schema": {
              "type": "string",
              "enum": [
                "states",
                "countries"
              ],
              "example": "states"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A GeoJSON FeatureCollection",
            "content": {
              "application/geo+json": {
                "schema": {
                  "$ref": "#/components/schemas/FeatureCollection"
                }
              }
            }
          },
          "400": {
            "description": "set was missing or was not one of states or countries"
          }
        }
      }
    },
    "/api/license": {
      "get": {
        "operationId": "license",
        "summary": "Ask whether a key is good, and what tier it opens",
        "description": "Verification is a signature check at the edge, so it costs nothing and adds no latency to a client's boot. The answer also says whether this deployment can verify anything at all, which matters: a key that fails on a configured service is a bad key, and a key that fails on an unconfigured one is a service that has not been switched on, and those need different things from the caller. A revoked key reads as not ok here, the same as at every gate. Free.",
        "tags": [
          "Keys"
        ],
        "security": [],
        "parameters": [
          {
            "name": "key",
            "in": "query",
            "required": false,
            "description": "The key to check. It may also be sent as an Authorization bearer token.",
            "schema": {
              "type": "string",
              "example": "sp1..."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "What the key opens",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "description": "Whether the key verifies and is not revoked."
                    },
                    "tier": {
                      "type": "string",
                      "description": "pro or api, present only when ok."
                    },
                    "configured": {
                      "type": "boolean",
                      "description": "Whether this deployment holds any way to verify a key."
                    }
                  },
                  "required": [
                    "ok",
                    "configured"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/x402": {
      "get": {
        "operationId": "catalogue",
        "summary": "What is for sale, and every answer in it, one at a time",
        "description": "Free to read. Without parameters it states the terms and the catalogue total. With ?offset and ?limit it pages through all 2006 individually priced answers; ?resource=<id> fetches one; ?resort=<id> filters to a mountain.",
        "tags": [
          "Catalogue"
        ],
        "security": [],
        "parameters": [
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Where in the catalogue to start.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "example": 0
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "How many entries, to 500.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "example": 100
            }
          },
          {
            "name": "resource",
            "in": "query",
            "required": false,
            "description": "One product by its own id.",
            "schema": {
              "type": "string",
              "example": "alta.features"
            }
          },
          {
            "name": "resort",
            "in": "query",
            "required": false,
            "description": "Only this resort’s products.",
            "schema": {
              "type": "string",
              "example": "alta"
            }
          },
          {
            "name": "kind",
            "in": "query",
            "required": false,
            "description": "Only this kind of answer.",
            "schema": {
              "type": "string",
              "example": "weather"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The catalogue"
          }
        }
      },
      "post": {
        "operationId": "buyKey",
        "summary": "Buy a Pro or API key in USDC",
        "description": "Pro is 3.99 USDC once and never expires. The API key is 5.99 USDC for thirty days and also unlocks Pro in the app. Both mint the same signed key the card checkout mints.",
        "tags": [
          "Catalogue"
        ],
        "x-payment-info": {
          "price": {
            "mode": "dynamic",
            "currency": "USD",
            "min": "3.99",
            "max": "5.99"
          },
          "protocols": [
            {
              "x402": {}
            }
          ]
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "buy": {
                    "type": "string",
                    "enum": [
                      "pro",
                      "api"
                    ],
                    "description": "Which key to buy."
                  }
                },
                "required": [
                  "buy"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "key": {
                      "type": "string"
                    },
                    "tier": {
                      "type": "string"
                    },
                    "expires": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "key",
                    "tier"
                  ]
                }
              }
            }
          },
          "402": {
            "description": "Payment Required"
          }
        }
      }
    },
    "/openapi.json": {
      "get": {
        "operationId": "openapi",
        "summary": "This document",
        "tags": [
          "Catalogue"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "This document"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "SnowTracker": {
        "type": "object",
        "description": "The ranking. Without a key or a payment the rows stop after five and `locked` counts the rest; with one, `rows` is every mountain the view covers.",
        "properties": {
          "snow": {
            "type": "integer",
            "description": "The answer's own version, 1."
          },
          "status": {
            "type": "string",
            "description": "live when the sweep reached its instruments, and says so plainly when it did not."
          },
          "at": {
            "type": "string",
            "description": "When the ranking was computed, in ISO 8601."
          },
          "view": {
            "type": "string",
            "description": "Which ranking this is: today, week, base, tomorrow or season."
          },
          "metric": {
            "type": "string",
            "description": "The field the rows are sorted by, for example new24h."
          },
          "views": {
            "type": "array",
            "description": "Every view this route answers.",
            "items": {
              "type": "string"
            }
          },
          "headline": {
            "type": "string",
            "description": "The ranking in one sentence, already written."
          },
          "units": {
            "type": "object",
            "description": "The unit every figure below is in.",
            "properties": {
              "snow": {
                "type": "string",
                "description": "in"
              },
              "depth": {
                "type": "string",
                "description": "in"
              },
              "temperature": {
                "type": "string",
                "description": "F"
              },
              "elevation": {
                "type": "string",
                "description": "ft"
              }
            },
            "additionalProperties": true
          },
          "season": {
            "type": "object",
            "description": "Where the season count starts.",
            "properties": {
              "since": {
                "type": "string",
                "description": "The date the season total counts from."
              }
            },
            "additionalProperties": true
          },
          "coverage": {
            "$ref": "#/components/schemas/Coverage"
          },
          "total": {
            "type": "integer",
            "description": "How many mountains the view covers."
          },
          "record": {
            "type": "object",
            "description": "What the stored record holds behind this answer.",
            "properties": {
              "hours": {
                "type": "integer"
              },
              "covered": {
                "type": "integer"
              },
              "observations": {
                "type": "integer"
              },
              "ageHours": {
                "type": "number"
              }
            },
            "additionalProperties": true
          },
          "instrumentLevel": {
            "type": "object",
            "description": "How each instrument is graded, and the grades themselves.",
            "properties": {
              "by": {
                "type": "string",
                "description": "What the grade is computed from."
              },
              "levels": {
                "type": "array",
                "description": "The grades, in order.",
                "items": {
                  "type": "string"
                }
              },
              "note": {
                "type": "string",
                "description": "What the grade does and does not mean."
              }
            },
            "additionalProperties": true
          },
          "states": {
            "type": "array",
            "description": "Every state and province with a mountain in the catalogue.",
            "items": {
              "type": "string"
            }
          },
          "state": {
            "type": [
              "string",
              "null"
            ],
            "description": "The state filter in force, or null for the whole catalogue."
          },
          "access": {
            "type": "string",
            "description": "head when the rows are trimmed, and the full ranking when they are not."
          },
          "catalogue": {
            "type": "array",
            "description": "Every mountain by id and name, so a trimmed answer still names what it did not show.",
            "items": {
              "type": "object",
              "description": "One mountain's identity.",
              "properties": {
                "id": {
                  "type": "string",
                  "description": ""
                },
                "name": {
                  "type": "string",
                  "description": ""
                },
                "state": {
                  "type": "string",
                  "description": ""
                },
                "region": {
                  "type": "string",
                  "description": ""
                }
              },
              "additionalProperties": true
            }
          },
          "rows": {
            "type": "array",
            "description": "The ranking itself, best first.",
            "items": {
              "$ref": "#/components/schemas/SnowRow"
            }
          },
          "locked": {
            "type": "integer",
            "description": "How many rows were withheld. Absent when none were."
          },
          "more": {
            "type": "string",
            "description": "What a key or a payment opens. Absent when nothing is withheld."
          }
        },
        "required": [
          "snow",
          "view",
          "rows"
        ],
        "additionalProperties": true
      },
      "SnowRow": {
        "type": "object",
        "description": "One mountain in the ranking. Inches, feet and Fahrenheit throughout.",
        "properties": {
          "rank": {
            "type": "integer"
          },
          "id": {
            "type": "string",
            "description": "The mountain's id, which addresses it on every other route."
          },
          "name": {
            "type": "string",
            "description": ""
          },
          "region": {
            "type": "string",
            "description": ""
          },
          "state": {
            "type": "string",
            "description": ""
          },
          "country": {
            "type": "string",
            "description": ""
          },
          "elevFt": {
            "type": "number",
            "description": "Summit elevation in feet."
          },
          "lat": {
            "type": "number",
            "description": ""
          },
          "lon": {
            "type": "number",
            "description": ""
          },
          "depthIn": {
            "type": "number",
            "description": "Base depth in inches."
          },
          "new24h": {
            "type": "number",
            "description": "New snow in the last 24 hours, in inches."
          },
          "new72h": {
            "type": "number",
            "description": "New snow in the last 72 hours, in inches."
          },
          "new7d": {
            "type": "number",
            "description": "New snow in the last 7 days, in inches."
          },
          "seasonIn": {
            "type": "number",
            "description": "Season total since the first of October, in inches."
          },
          "next24h": {
            "type": "number",
            "description": "The snow expected in the next 24 hours, in inches."
          },
          "next72h": {
            "type": "number",
            "description": "The snow expected in the next 72 hours, in inches."
          },
          "nowIn": {
            "type": "number",
            "description": "What is falling now, in inches an hour."
          },
          "snowing": {
            "type": "boolean"
          },
          "tempF": {
            "type": "number",
            "description": ""
          },
          "sweIn": {
            "type": "number",
            "description": "Snow water equivalent, in inches."
          },
          "densityPct": {
            "type": "number",
            "description": "How dense the pack is, as a percentage."
          },
          "trend": {
            "type": "string",
            "description": "Whether the pack is building, holding or going."
          },
          "source": {
            "type": "string",
            "description": "Where the figure came from: measured at an instrument, or computed."
          },
          "contributors": {
            "type": "array",
            "description": "Every instrument that spoke for this row.",
            "items": {
              "type": "object"
            }
          },
          "station": {
            "type": "string",
            "description": "The instrument the headline figure was read from."
          },
          "model": {
            "type": "object",
            "description": "The computed figure beside the measured one, with when it was computed.",
            "additionalProperties": true
          },
          "agree": {
            "type": "object",
            "description": "How far the two are apart, and whether that is explained by where they stand.",
            "additionalProperties": true
          },
          "confidence": {
            "type": "number",
            "description": "How much of the figure is measured rather than computed."
          },
          "danger": {
            "type": "object",
            "description": "The avalanche rating where a centre issues one for this ground.",
            "additionalProperties": true
          }
        },
        "required": [
          "id",
          "name"
        ],
        "additionalProperties": true
      },
      "Coverage": {
        "type": "object",
        "description": "How many were reached, how many answered, and what was set aside with the reason. Every field is optional and which of them appear depends on which sweep produced the answer: the snow tracker counts its backups, the compact roll reports whether it is degraded.",
        "properties": {
          "resorts": {
            "type": "integer"
          },
          "stations": {
            "type": "integer"
          },
          "reached": {
            "type": "integer",
            "description": "How many instruments answered."
          },
          "measured": {
            "type": "integer",
            "description": "How many mountains carry a measured figure."
          },
          "modelled": {
            "type": "integer",
            "description": "How many carry a computed one instead."
          },
          "failures": {
            "type": "object",
            "description": "Each instrument that did not answer, against the reason.",
            "additionalProperties": true
          },
          "backupsAsked": {
            "type": "integer",
            "description": "How many second instruments were asked because the first was silent."
          },
          "steppedIn": {
            "type": "integer",
            "description": "How many of those backups ended up carrying the figure."
          },
          "withBackup": {
            "type": "integer",
            "description": "How many mountains have a second instrument at all."
          },
          "degraded": {
            "type": "boolean",
            "description": "True when enough of the sweep failed that the answer is thinner than usual."
          }
        },
        "additionalProperties": true
      },
      "WeatherReport": {
        "type": "object",
        "description": "The report for one place. tier is \"free\" with no key and no payment, and then `now` carries the temperature, what it feels like, the wind and the condition, alerts ride in full because safety is never behind the paywall, and the week, the hours, the air, the paragraph and the reconciled point are absent. tier is \"full\" with a key or a payment, and every field below is present.",
        "properties": {
          "weather": {
            "type": "integer",
            "description": "The answer's own version, 1."
          },
          "tier": {
            "type": "string",
            "enum": [
              "free",
              "full"
            ]
          },
          "place": {
            "type": "object",
            "description": "The place the report is for.",
            "properties": {
              "name": {
                "type": "string",
                "description": ""
              },
              "label": {
                "type": "string",
                "description": "The place written out as a reader would say it."
              },
              "kind": {
                "type": "string",
                "description": "What kind of place it is."
              },
              "county": {
                "type": "string",
                "description": ""
              },
              "state": {
                "type": "string",
                "description": ""
              },
              "postcode": {
                "type": "string",
                "description": ""
              },
              "lat": {
                "type": "number",
                "description": ""
              },
              "lon": {
                "type": "number",
                "description": ""
              },
              "timezone": {
                "type": "string",
                "description": ""
              }
            },
            "required": [
              "lat",
              "lon"
            ],
            "additionalProperties": true
          },
          "now": {
            "type": "object",
            "description": "The present moment. Fahrenheit, miles per hour, inches and inches of mercury.",
            "properties": {
              "observedAt": {
                "type": "string",
                "description": ""
              },
              "weatherCode": {
                "type": "integer",
                "description": "The WMO code the condition was read from."
              },
              "condition": {
                "type": "string",
                "description": "The condition as a machine-stable word."
              },
              "says": {
                "type": "string",
                "description": "The same condition as a reader would say it."
              },
              "temperatureF": {
                "type": "number",
                "description": ""
              },
              "feelsLikeF": {
                "type": "number",
                "description": ""
              },
              "windChillF": {
                "type": "number",
                "description": "Present only below 50 F with wind, because it means nothing above that."
              },
              "heatIndexF": {
                "type": "number",
                "description": "Present only at or above 80 F, for the same reason."
              },
              "dewPointF": {
                "type": "number",
                "description": ""
              },
              "humidityPct": {
                "type": "number",
                "description": ""
              },
              "cloudCoverPct": {
                "type": "number",
                "description": ""
              },
              "precipitationIn": {
                "type": "number",
                "description": ""
              },
              "windMph": {
                "type": "number",
                "description": ""
              },
              "windGustMph": {
                "type": "number",
                "description": ""
              },
              "windFromDeg": {
                "type": "number",
                "description": ""
              },
              "windFrom": {
                "type": "string",
                "description": "The bearing in compass words."
              },
              "pressureInHg": {
                "type": "number",
                "description": ""
              },
              "surfacePressureInHg": {
                "type": "number",
                "description": ""
              },
              "uvIndex": {
                "type": "number",
                "description": ""
              },
              "daylight": {
                "type": "boolean"
              }
            },
            "additionalProperties": true
          },
          "hourly": {
            "type": "array",
            "description": "The next forty-eight hours. Paid.",
            "items": {
              "type": "object",
              "description": "One hour.",
              "properties": {
                "at": {
                  "type": "string",
                  "description": ""
                },
                "temperatureF": {
                  "type": "number",
                  "description": ""
                },
                "precipitationChancePct": {
                  "type": "number",
                  "description": ""
                },
                "weatherCode": {
                  "type": "integer"
                },
                "condition": {
                  "type": "string",
                  "description": ""
                }
              },
              "additionalProperties": true
            }
          },
          "daily": {
            "type": "array",
            "description": "Ten days. Paid.",
            "items": {
              "type": "object",
              "description": "One day.",
              "properties": {
                "date": {
                  "type": "string",
                  "description": ""
                },
                "weatherCode": {
                  "type": "integer"
                },
                "highF": {
                  "type": "number",
                  "description": ""
                },
                "lowF": {
                  "type": "number",
                  "description": ""
                },
                "precipitationChancePct": {
                  "type": "number",
                  "description": ""
                },
                "condition": {
                  "type": "string",
                  "description": ""
                },
                "says": {
                  "type": "string",
                  "description": ""
                },
                "windMaxMph": {
                  "type": "number",
                  "description": ""
                },
                "windFromDeg": {
                  "type": "number",
                  "description": ""
                },
                "windFrom": {
                  "type": "string",
                  "description": ""
                },
                "uvIndexMax": {
                  "type": "number",
                  "description": ""
                },
                "sunrise": {
                  "type": "string",
                  "description": ""
                },
                "sunset": {
                  "type": "string",
                  "description": ""
                },
                "moonPhase": {
                  "type": "object",
                  "description": "The moon that night.",
                  "additionalProperties": true
                }
              },
              "additionalProperties": true
            }
          },
          "alerts": {
            "type": "array",
            "description": "Every active severe weather alert, in full, free.",
            "items": {
              "type": "object"
            }
          },
          "alertsStatus": {
            "type": "string",
            "enum": [
              "live",
              "unavailable"
            ],
            "description": "An empty list and an unreachable service look identical and mean opposite things, so this says which."
          },
          "air": {
            "type": "object",
            "description": "The air, where it is reported. Paid.",
            "additionalProperties": true
          },
          "airStatus": {
            "type": "string",
            "enum": [
              "live",
              "unavailable"
            ]
          },
          "narrative": {
            "type": "object",
            "description": "The forecaster's own paragraph. Paid.",
            "additionalProperties": true
          },
          "narrativeStatus": {
            "type": "string",
            "enum": [
              "live",
              "unavailable"
            ]
          },
          "forecastCheck": {
            "type": "object",
            "description": "How far apart the two analyses are at this moment, and whether that gap is explained. Paid.",
            "additionalProperties": true
          },
          "point": {
            "type": "object",
            "description": "The reconciled figure: the analysis corrected by the instruments standing near the coordinate, each named, with what it read, how far away and how far above it stands, how old the reading is, and which were refused and in what words. Absent rather than empty when nothing was found, because a point built from nothing is the analysis under a new name. Paid.",
            "additionalProperties": true
          },
          "units": {
            "type": "object",
            "description": "The unit every figure is in.",
            "properties": {
              "temperature": {
                "type": "string",
                "description": "F"
              },
              "wind": {
                "type": "string",
                "description": "mph"
              },
              "precipitation": {
                "type": "string",
                "description": "in"
              },
              "pressure": {
                "type": "string",
                "description": "inHg"
              }
            },
            "additionalProperties": true
          },
          "fetchedAt": {
            "type": "string",
            "description": ""
          },
          "more": {
            "type": "string",
            "description": "What a key or a payment opens. Present on the free answer only."
          },
          "hint": {
            "type": "string",
            "description": "The address that quotes the price for this exact call. Present on the free answer only."
          }
        },
        "required": [
          "weather",
          "tier",
          "place",
          "now",
          "alerts"
        ],
        "additionalProperties": true
      },
      "AtlasAnswer": {
        "type": "object",
        "description": "Everything known about one point: the avalanche danger by aspect and elevation with its issuing zone, active alerts in full, the land beneath it, and the nearest reporting instrument. Without a key or a payment the answer carries tier \"free\" and the instrument, the elevation bands and the lead are absent.",
        "properties": {
          "atlas": {
            "type": "integer",
            "description": "The answer's own version, 1."
          },
          "tier": {
            "type": "string",
            "enum": [
              "free"
            ],
            "description": "Present on the free answer only."
          },
          "place": {
            "type": "object",
            "description": "The point, on the shared grid it was cached at.",
            "properties": {
              "lat": {
                "type": "number",
                "description": ""
              },
              "lon": {
                "type": "number",
                "description": ""
              }
            },
            "required": [
              "lat",
              "lon"
            ],
            "additionalProperties": true
          },
          "tile": {
            "type": "object",
            "description": "The slippy tile this answer belongs to.",
            "properties": {
              "z": {
                "type": "integer"
              },
              "x": {
                "type": "integer"
              },
              "y": {
                "type": "integer"
              }
            },
            "additionalProperties": true
          },
          "bounds": {
            "type": "array",
            "description": "The asked tile's own bounds, west, south, east, north. Present only when a tile was asked for.",
            "items": {
              "type": "number"
            }
          },
          "avyLevel": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 1,
            "maximum": 5,
            "description": "The danger rating of record, 1 to 5."
          },
          "avyLabel": {
            "type": "string",
            "description": "That rating in the centre's own words."
          },
          "avyZone": {
            "type": "string",
            "description": "The forecast zone the point falls in."
          },
          "avyCenter": {
            "type": "string",
            "description": "The centre that issues for that zone."
          },
          "avyLink": {
            "type": "string",
            "description": "The centre's own bulletin, so a reader can go and read it."
          },
          "avyTravelAdvice": {
            "type": "string",
            "description": "The centre's travel advice for the rating."
          },
          "avyExpires": {
            "type": "string",
            "description": "When the bulletin stops being current."
          },
          "avyMatched": {
            "type": "string",
            "enum": [
              "inside",
              "nearest"
            ],
            "description": "inside when the point falls in the zone, nearest when the closest zone within about forty miles was used."
          },
          "avyRatings": {
            "type": "object",
            "description": "The rose: a rating for each aspect in each elevation band. Mirrored from the rating of record unless the centre publishes a real rose, and never invented.",
            "additionalProperties": true
          },
          "avySources": {
            "type": "array",
            "description": "Every source asked for the danger, and whether it answered.",
            "items": {
              "type": "object"
            }
          },
          "landOwner": {
            "type": "string",
            "description": "Who owns the ground."
          },
          "landManager": {
            "type": "string",
            "description": "Who manages it."
          },
          "landSource": {
            "type": "string",
            "description": "Which survey said so."
          },
          "landSources": {
            "type": "array",
            "description": "Every survey asked, and whether it answered.",
            "items": {
              "type": "object"
            }
          },
          "observation": {
            "type": "object",
            "description": "The nearest instrument actually reporting, with what it read and how far off it stands. Paid.",
            "additionalProperties": true
          },
          "alerts": {
            "type": "array",
            "description": "Every active alert over the point, in full, free.",
            "items": {
              "type": "object"
            }
          },
          "fetchedAt": {
            "type": "string",
            "description": ""
          }
        },
        "required": [
          "atlas",
          "place"
        ],
        "additionalProperties": true
      },
      "ConditionsRoll": {
        "type": "object",
        "description": "One small row per mountain, keyed by the mountain's id: enough to colour a map and label a marker, and deliberately not a replacement for a per-mountain call. Inches, feet and Fahrenheit.",
        "properties": {
          "generatedAt": {
            "type": "string",
            "description": "When the sweep ran."
          },
          "resorts": {
            "type": "object",
            "description": "Every mountain by id, each against its own row.",
            "additionalProperties": true
          },
          "coverage": {
            "$ref": "#/components/schemas/Coverage"
          }
        },
        "required": [
          "generatedAt",
          "resorts",
          "coverage"
        ],
        "additionalProperties": true
      },
      "FeatureCollection": {
        "type": "object",
        "description": "A GeoJSON FeatureCollection, to RFC 7946.",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "FeatureCollection"
            ]
          },
          "features": {
            "type": "array",
            "description": "The boundaries themselves.",
            "items": {
              "type": "object",
              "description": "A GeoJSON Feature.",
              "properties": {
                "type": {
                  "type": "string",
                  "enum": [
                    "Feature"
                  ]
                },
                "properties": {
                  "type": "object",
                  "description": "What the boundary is called.",
                  "additionalProperties": true
                },
                "geometry": {
                  "type": "object",
                  "description": "Its geometry, as GeoJSON.",
                  "additionalProperties": true
                }
              },
              "required": [
                "type",
                "geometry"
              ],
              "additionalProperties": true
            }
          }
        },
        "required": [
          "type",
          "features"
        ],
        "additionalProperties": true
      }
    },
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "A Snowpack key, sent as Authorization: Bearer sp1... It is a bearer credential: whoever holds it can spend against it, so it belongs on a server and not in a page."
      },
      "keyQuery": {
        "type": "apiKey",
        "in": "query",
        "name": "key",
        "description": "The same key as a query parameter, for a client that cannot set a header. Prefer the Authorization header: a key in a URL is written down by every log it passes through."
      }
    }
  },
  "security": [
    {
      "bearerAuth": []
    },
    {
      "keyQuery": []
    },
    {}
  ]
}