{"openapi":"3.1.0","info":{"title":"Pollen Monitor API","version":"2.2.1","description":"Public, read-only pollen, species, forecast, map, weather, and air-quality data for supported US cities. Pollen concentrations are modeled by Ambee in grains/m³. Risk labels use category-specific National Allergy Bureau thresholds."},"servers":[{"url":"https://pollenmonitor.dev","description":"Pollen Monitor production API"}],"externalDocs":{"description":"Human-readable API documentation","url":"https://pollenmonitor.dev/docs/api"},"x-mcp-server":{"description":"Public, read-only Model Context Protocol server.","transport":"streamable-http","url":"https://pollenmonitor.dev/mcp","documentation":"https://pollenmonitor.dev/docs/mcp"},"tags":[{"name":"Discovery","description":"Find supported cities and available observation dates."},{"name":"Pollen","description":"Retrieve historical and forecast pollen concentrations and risks."},{"name":"Map","description":"Retrieve compact cross-city GeoJSON for map and spatial use."},{"name":"Weather","description":"Retrieve daily weather and air-quality observations."}],"paths":{"/api/cities":{"get":{"operationId":"listCities","summary":"List supported cities","description":"Use the returned slug as the city parameter in pollen, forecast, and weather requests.","tags":["Discovery"],"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl --fail --silent --show-error 'https://pollenmonitor.dev/api/cities'"},{"lang":"JavaScript","label":"JavaScript","source":"const response = await fetch('https://pollenmonitor.dev/api/cities');\nif (!response.ok) throw new Error(`HTTP ${response.status}`);\nconst data = await response.json();"},{"lang":"Python","label":"Python","source":"import requests\n\nresponse = requests.get('https://pollenmonitor.dev/api/cities', timeout=15)\nresponse.raise_for_status()\ndata = response.json()"}],"responses":{"200":{"description":"Alphabetized supported cities.","content":{"application/json":{"schema":{"type":"object","required":["cities"],"properties":{"cities":{"type":"array","items":{"$ref":"#/components/schemas/City"}}}},"examples":{"success":{"summary":"Supported city names and slugs","value":{"cities":[{"name":"Berkeley","slug":"berkeley"},{"name":"Denver","slug":"denver"}]}}}}}},"500":{"$ref":"#/components/responses/Error"}}}},"/api/available-dates":{"get":{"operationId":"listAvailablePollenDates","summary":"List dates with pollen observations","description":"Returns UTC dates newest first.","tags":["Discovery"],"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl --fail --silent --show-error 'https://pollenmonitor.dev/api/available-dates'"},{"lang":"JavaScript","label":"JavaScript","source":"const response = await fetch('https://pollenmonitor.dev/api/available-dates');\nif (!response.ok) throw new Error(`HTTP ${response.status}`);\nconst data = await response.json();"},{"lang":"Python","label":"Python","source":"import requests\n\nresponse = requests.get('https://pollenmonitor.dev/api/available-dates', timeout=15)\nresponse.raise_for_status()\ndata = response.json()"}],"responses":{"200":{"description":"Available UTC dates.","content":{"application/json":{"schema":{"type":"object","required":["dates"],"properties":{"dates":{"type":"array","items":{"$ref":"#/components/schemas/Date"}}}},"examples":{"success":{"summary":"Newest available dates","value":{"dates":["2026-08-26","2026-08-25"]}}}}}},"500":{"$ref":"#/components/responses/Error"}}}},"/api/latest-date":{"get":{"operationId":"getLatestPollenDate","summary":"Get the latest pollen observation date","tags":["Discovery"],"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl --fail --silent --show-error 'https://pollenmonitor.dev/api/latest-date'"},{"lang":"JavaScript","label":"JavaScript","source":"const response = await fetch('https://pollenmonitor.dev/api/latest-date');\nif (!response.ok) throw new Error(`HTTP ${response.status}`);\nconst data = await response.json();"},{"lang":"Python","label":"Python","source":"import requests\n\nresponse = requests.get('https://pollenmonitor.dev/api/latest-date', timeout=15)\nresponse.raise_for_status()\ndata = response.json()"}],"responses":{"200":{"description":"Latest UTC observation date.","content":{"application/json":{"schema":{"type":"object","required":["date"],"properties":{"date":{"$ref":"#/components/schemas/Date"}}},"examples":{"success":{"summary":"Latest available date","value":{"date":"2026-08-26"}}}}}},"500":{"$ref":"#/components/responses/Error"}}}},"/api/pollen":{"get":{"operationId":"getPollen","summary":"Get pollen by city or date","description":"Provide city alone for up to 720 daily averages, city and date for hourly readings on that UTC date, or date alone for a compact cross-city summary. Unsupported city slugs return 404 with pointers to /api/cities and the MCP list_cities tool.","tags":["Pollen"],"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl --fail --silent --show-error 'https://pollenmonitor.dev/api/pollen?city=berkeley&date=2026-08-25'"},{"lang":"JavaScript","label":"JavaScript","source":"const response = await fetch('https://pollenmonitor.dev/api/pollen?city=berkeley&date=2026-08-25');\nif (!response.ok) throw new Error(`HTTP ${response.status}`);\nconst data = await response.json();"},{"lang":"Python","label":"Python","source":"import requests\n\nresponse = requests.get('https://pollenmonitor.dev/api/pollen?city=berkeley&date=2026-08-25', timeout=15)\nresponse.raise_for_status()\ndata = response.json()"}],"parameters":[{"$ref":"#/components/parameters/City"},{"$ref":"#/components/parameters/OptionalDate"}],"responses":{"200":{"description":"Pollen results. The row shape depends on the supplied parameters.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/HourlyPollenResponse"},{"$ref":"#/components/schemas/DailyPollenResponse"},{"$ref":"#/components/schemas/CrossCityPollenResponse"}]},"examples":{"hourly":{"summary":"Hourly observations for one city-day","value":{"city":"berkeley","date":"2026-08-25","rows":[{"ts":"2026-08-25T18:00:00.000Z","tree":20,"grass":4,"weed":29,"total":53,"species":{"Tree":{"Elm":20,"Oak":0},"Grass":{"Grass":4},"Weed":{"Ragweed":29}},"risk_tree":"Moderate","risk_grass":"Low","risk_weed":"Moderate","timezone":"America/Los_Angeles"}]}},"daily":{"summary":"Daily city history","value":{"city":"berkeley","rows":[{"date":"2026-08-25","tree":18,"grass":3,"weed":21,"total":42,"species":{"Tree":{"Elm":18,"Oak":0},"Grass":{"Grass":3},"Weed":{"Ragweed":21}},"risk_tree":"Moderate","risk_grass":"Low","risk_weed":"Moderate","timezone":"America/Los_Angeles"}]}},"crossCity":{"summary":"Cross-city summary for one date","value":{"date":"2026-08-25","rows":[{"city":"berkeley","date":"2026-08-25","count":53,"source":"ambee","is_forecast":false,"max_weed":29}]}}}}}},"400":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/UnsupportedCity"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/pollen-range":{"get":{"operationId":"getPollenRange","summary":"Get pollen over a custom time range","description":"Returns a flat, consistent row shape for hourly observations or daily averages. Set aggregate=day for daily values. Unknown aggregate values return 400. The upper time bound is exclusive.","tags":["Pollen"],"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl --fail --silent --show-error 'https://pollenmonitor.dev/api/pollen-range?from=2026-08-20&to=2026-08-27&city=berkeley&aggregate=day&limit=500'"},{"lang":"JavaScript","label":"JavaScript","source":"const response = await fetch('https://pollenmonitor.dev/api/pollen-range?from=2026-08-20&to=2026-08-27&city=berkeley&aggregate=day&limit=500');\nif (!response.ok) throw new Error(`HTTP ${response.status}`);\nconst data = await response.json();"},{"lang":"Python","label":"Python","source":"import requests\n\nresponse = requests.get('https://pollenmonitor.dev/api/pollen-range?from=2026-08-20&to=2026-08-27&city=berkeley&aggregate=day&limit=500', timeout=15)\nresponse.raise_for_status()\ndata = response.json()"}],"parameters":[{"name":"from","in":"query","required":true,"description":"Inclusive start date or RFC 3339 timestamp.","schema":{"oneOf":[{"$ref":"#/components/schemas/Date"},{"$ref":"#/components/schemas/DateTime"}]},"example":"2026-08-20"},{"name":"to","in":"query","required":true,"description":"Exclusive end date or RFC 3339 timestamp.","schema":{"oneOf":[{"$ref":"#/components/schemas/Date"},{"$ref":"#/components/schemas/DateTime"}]},"example":"2026-08-27"},{"name":"city","in":"query","required":false,"description":"Comma-separated city slugs. Omit for all cities.","schema":{"type":"string"},"example":"berkeley,denver"},{"name":"aggregate","in":"query","required":false,"schema":{"type":"string","enum":["none","day"],"default":"none"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":50000,"default":20000}}],"responses":{"200":{"description":"Hourly or daily pollen range results.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PollenRangeResponse"},"examples":{"success":{"summary":"Daily pollen rows in a bounded range","value":{"from":"2026-08-20T00:00:00.000Z","to":"2026-08-27T00:00:00.000Z","cities":["berkeley"],"aggregate":"day","rows":[{"city":"berkeley","periodStart":"2026-08-25T00:00:00.000Z","tree":18,"grass":3,"weed":21,"total":42,"timezone":"America/Los_Angeles","species":{"Tree":{"Elm":18,"Oak":0},"Grass":{"Grass":3},"Weed":{"Ragweed":21}},"risk_tree":"Moderate","risk_grass":"Low","risk_weed":"Moderate"}]}}}}}},"400":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/UnsupportedCity"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/map-data":{"get":{"operationId":"getPollenMapData","summary":"Get cross-city pollen GeoJSON","description":"Returns one compact point feature per city with daily maximum tree, grass, weed, and ragweed values and NAB risk properties. Includes a three-day daily-maximum series but not full species blobs.","tags":["Map"],"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl --fail --silent --show-error 'https://pollenmonitor.dev/api/map-data?date=latest'"},{"lang":"JavaScript","label":"JavaScript","source":"const response = await fetch('https://pollenmonitor.dev/api/map-data?date=latest');\nif (!response.ok) throw new Error(`HTTP ${response.status}`);\nconst data = await response.json();"},{"lang":"Python","label":"Python","source":"import requests\n\nresponse = requests.get('https://pollenmonitor.dev/api/map-data?date=latest', timeout=15)\nresponse.raise_for_status()\ndata = response.json()"}],"parameters":[{"name":"date","in":"query","required":false,"description":"UTC date or latest. Defaults to latest.","schema":{"oneOf":[{"$ref":"#/components/schemas/Date"},{"type":"string","const":"latest"}]}}],"responses":{"200":{"description":"GeoJSON FeatureCollection with a resolved date.","content":{"application/geo+json":{"schema":{"$ref":"#/components/schemas/MapFeatureCollection"},"examples":{"success":{"summary":"Daily category maxima for one city","value":{"type":"FeatureCollection","date":"2026-08-25","aggregation":"daily-category-maxima","features":[{"type":"Feature","properties":{"city":"berkeley","value_basis":"daily-category-maxima","count":53,"tree":20,"grass":4,"weed":29,"ragweed":29,"max_weed":29,"risk_tree":"Moderate","risk_grass":"Low","risk_weed":"Moderate","risk_ragweed":"Moderate","sev_tree":2,"sev_grass":1,"sev_weed":2,"sev_ragweed":2,"sev_total":2,"timezone":"America/Los_Angeles","series":[{"date":"2026-08-25","tree":20,"grass":4,"weed":29,"ragweed":29,"risk_tree":"Moderate","risk_grass":"Low","risk_weed":"Moderate","risk_ragweed":"Moderate","timezone":"America/Los_Angeles"}]},"geometry":{"type":"Point","coordinates":[-122.273,37.8715]}}]}}}}}},"400":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/forecast":{"get":{"operationId":"getPollenForecast","summary":"Get a city’s 48-hour pollen forecast","description":"Returns cached or fresh Ambee hourly forecasts with species values when available and NAB risk labels. If an upstream refresh fails while cached rows exist, returns the cache with stale=true instead of failing the request.","tags":["Pollen"],"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl --fail --silent --show-error 'https://pollenmonitor.dev/api/forecast?city=berkeley'"},{"lang":"JavaScript","label":"JavaScript","source":"const response = await fetch('https://pollenmonitor.dev/api/forecast?city=berkeley');\nif (!response.ok) throw new Error(`HTTP ${response.status}`);\nconst data = await response.json();"},{"lang":"Python","label":"Python","source":"import requests\n\nresponse = requests.get('https://pollenmonitor.dev/api/forecast?city=berkeley', timeout=15)\nresponse.raise_for_status()\ndata = response.json()"}],"parameters":[{"$ref":"#/components/parameters/RequiredCity"}],"responses":{"200":{"description":"Hourly pollen forecast.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForecastResponse"},"examples":{"success":{"summary":"Cached hourly forecast","value":{"city":"berkeley","source":"cache","stale":false,"fetchedAt":"2026-08-26T03:00:00.000Z","rows":[{"ts":"2026-08-26T04:00:00.000Z","tree":22,"grass":4,"weed":31,"total":57,"species":{"Tree":{"Elm":22},"Grass":{"Grass":4},"Weed":{"Ragweed":31}},"risk_tree":"Moderate","risk_grass":"Low","risk_weed":"Moderate","tz":"America/Los_Angeles"}]}},"staleFallback":{"summary":"Stale cache served after an upstream refresh failure","value":{"city":"berkeley","source":"cache","stale":true,"fetchedAt":"2026-08-26T03:00:00.000Z","rows":[{"ts":"2026-08-26T04:00:00.000Z","tree":22,"grass":4,"weed":31,"total":57,"species":{"Tree":{"Elm":22},"Grass":{"Grass":4},"Weed":{"Ragweed":31}},"risk_tree":"Moderate","risk_grass":"Low","risk_weed":"Moderate","tz":"America/Los_Angeles"}]}}}}}},"400":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/UnsupportedCity"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/weather":{"get":{"operationId":"getWeather","summary":"Get daily weather and air quality","description":"Provide city alone for up to 365 days, city and date for one city-day, or date alone for a compact cross-city snapshot. Unavailable measurements are omitted.","tags":["Weather"],"x-codeSamples":[{"lang":"Shell","label":"curl","source":"curl --fail --silent --show-error 'https://pollenmonitor.dev/api/weather?city=berkeley&date=2026-08-25'"},{"lang":"JavaScript","label":"JavaScript","source":"const response = await fetch('https://pollenmonitor.dev/api/weather?city=berkeley&date=2026-08-25');\nif (!response.ok) throw new Error(`HTTP ${response.status}`);\nconst data = await response.json();"},{"lang":"Python","label":"Python","source":"import requests\n\nresponse = requests.get('https://pollenmonitor.dev/api/weather?city=berkeley&date=2026-08-25', timeout=15)\nresponse.raise_for_status()\ndata = response.json()"}],"parameters":[{"$ref":"#/components/parameters/City"},{"$ref":"#/components/parameters/OptionalDate"}],"responses":{"200":{"description":"Daily weather and air-quality rows.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WeatherResponse"},"examples":{"success":{"summary":"Weather and air quality for one city-day","value":{"city":"berkeley","date":"2026-08-25","rows":[{"city_slug":"berkeley","date":"2026-08-25","timezone":"America/Los_Angeles","temp_min_c":13.2,"temp_max_c":22.8,"humidity":61,"wind_speed_ms":4.1,"weather_main":"Clear","aqi":2,"aqi_pm2_5":8.4,"source":"openweather","created_at":"2026-08-26T19:20:45.398159+00:00"}]}}}}}},"400":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/UnsupportedCity"},"500":{"$ref":"#/components/responses/Error"}}}}},"components":{"parameters":{"City":{"name":"city","in":"query","required":false,"description":"URL-safe city slug from /api/cities.","schema":{"type":"string"},"example":"berkeley"},"RequiredCity":{"name":"city","in":"query","required":true,"description":"URL-safe city slug from /api/cities.","schema":{"type":"string"},"example":"berkeley"},"OptionalDate":{"name":"date","in":"query","required":false,"description":"UTC calendar date.","schema":{"$ref":"#/components/schemas/Date"}}},"responses":{"Error":{"description":"Request or service error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"invalidParameter":{"summary":"Invalid request parameter","value":{"error":"Invalid parameter 'date': expected a valid date in YYYY-MM-DD format"}},"serviceUnavailable":{"summary":"Sanitized service failure","value":{"error":"Unable to load data"}}}}}},"UnsupportedCity":{"description":"The requested city slug is not supported. Resolve a valid slug through /api/cities or the MCP list_cities tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnsupportedCityError"},"examples":{"unsupportedCity":{"summary":"Unknown city slug","value":{"error":"Unsupported city 'atlantis'. Use GET /api/cities or the MCP list_cities tool to choose a supported city.","code":"UNSUPPORTED_CITY","city":"atlantis","supportedCities":"/api/cities","mcpTool":"list_cities"}}}}}}},"schemas":{"Date":{"type":"string","format":"date","example":"2026-08-25"},"DateTime":{"type":"string","format":"date-time","example":"2026-08-25T18:00:00.000Z"},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"string"}}},"UnsupportedCityError":{"type":"object","required":["error","code","city","supportedCities","mcpTool"],"properties":{"error":{"type":"string","example":"Unsupported city 'atlantis'. Use GET /api/cities or the MCP list_cities tool to choose a supported city."},"code":{"type":"string","enum":["UNSUPPORTED_CITY"]},"city":{"type":"string","example":"atlantis"},"supportedCities":{"type":"string","const":"/api/cities"},"mcpTool":{"type":"string","const":"list_cities"}}},"City":{"type":"object","required":["name","slug"],"properties":{"name":{"type":"string","example":"Berkeley"},"slug":{"type":"string","example":"berkeley"}}},"PollenRisk":{"type":["string","null"],"enum":["None","Low","Moderate","High","Very High",null]},"Species":{"type":["object","null"],"description":"Category names mapped to allergen names and modeled grains/m³. Hourly rows pass the provider payload through verbatim, which may include plain-number categories such as \"Others\".","additionalProperties":{"oneOf":[{"type":"object","additionalProperties":{"type":"number"}},{"type":"number"}]},"example":{"Tree":{"Elm":20,"Oak":0},"Grass":{"Grass":4},"Weed":{"Ragweed":29},"Others":2}},"HourlyPollen":{"type":"object","required":["ts","tree","grass","weed","total","species","risk_tree","risk_grass","risk_weed","timezone"],"properties":{"ts":{"$ref":"#/components/schemas/DateTime"},"tree":{"type":["number","null"]},"grass":{"type":["number","null"]},"weed":{"type":["number","null"]},"total":{"type":"number"},"species":{"$ref":"#/components/schemas/Species"},"risk_tree":{"$ref":"#/components/schemas/PollenRisk"},"risk_grass":{"$ref":"#/components/schemas/PollenRisk"},"risk_weed":{"$ref":"#/components/schemas/PollenRisk"},"timezone":{"type":["string","null"]}}},"DailyPollen":{"type":"object","required":["date","tree","grass","weed","total","species","risk_tree","risk_grass","risk_weed","timezone"],"properties":{"date":{"$ref":"#/components/schemas/Date"},"tree":{"type":["number","null"]},"grass":{"type":["number","null"]},"weed":{"type":["number","null"]},"total":{"type":["number","null"]},"species":{"$ref":"#/components/schemas/Species"},"risk_tree":{"$ref":"#/components/schemas/PollenRisk"},"risk_grass":{"$ref":"#/components/schemas/PollenRisk"},"risk_weed":{"$ref":"#/components/schemas/PollenRisk"},"timezone":{"type":["string","null"]}}},"HourlyPollenResponse":{"type":"object","required":["city","date","rows"],"properties":{"city":{"type":"string"},"date":{"$ref":"#/components/schemas/Date"},"rows":{"type":"array","items":{"$ref":"#/components/schemas/HourlyPollen"}}}},"DailyPollenResponse":{"type":"object","required":["city","rows"],"properties":{"city":{"type":"string"},"rows":{"type":"array","items":{"$ref":"#/components/schemas/DailyPollen"}}}},"CrossCityPollenResponse":{"type":"object","required":["date","rows"],"properties":{"date":{"$ref":"#/components/schemas/Date"},"rows":{"type":"array","items":{"type":"object","required":["city","date","count","source","is_forecast","max_weed"],"properties":{"city":{"type":"string"},"date":{"$ref":"#/components/schemas/Date"},"count":{"type":"number"},"source":{"type":"string","const":"ambee"},"is_forecast":{"type":"boolean","const":false},"max_weed":{"type":"number"}}}}}},"PollenRangeResponse":{"type":"object","required":["from","to","cities","aggregate","rows"],"properties":{"from":{"$ref":"#/components/schemas/DateTime"},"to":{"$ref":"#/components/schemas/DateTime"},"cities":{"type":"array","items":{"type":"string"}},"aggregate":{"type":"string","enum":["none","day"]},"rows":{"type":"array","items":{"$ref":"#/components/schemas/PollenRangeRow"}}}},"PollenRangeRow":{"type":"object","required":["city","periodStart","tree","grass","weed","total","timezone","species","risk_tree","risk_grass","risk_weed"],"properties":{"city":{"type":"string"},"periodStart":{"$ref":"#/components/schemas/DateTime"},"tree":{"type":["number","null"]},"grass":{"type":["number","null"]},"weed":{"type":["number","null"]},"total":{"type":["number","null"]},"timezone":{"type":["string","null"]},"species":{"$ref":"#/components/schemas/Species"},"risk_tree":{"$ref":"#/components/schemas/PollenRisk"},"risk_grass":{"$ref":"#/components/schemas/PollenRisk"},"risk_weed":{"$ref":"#/components/schemas/PollenRisk"}}},"MapDay":{"type":"object","required":["date","tree","grass","weed","ragweed","risk_tree","risk_grass","risk_weed","risk_ragweed","timezone"],"properties":{"date":{"$ref":"#/components/schemas/Date"},"tree":{"type":["number","null"]},"grass":{"type":["number","null"]},"weed":{"type":["number","null"]},"ragweed":{"type":["number","null"]},"risk_tree":{"$ref":"#/components/schemas/PollenRisk"},"risk_grass":{"$ref":"#/components/schemas/PollenRisk"},"risk_weed":{"$ref":"#/components/schemas/PollenRisk"},"risk_ragweed":{"$ref":"#/components/schemas/PollenRisk"},"timezone":{"type":["string","null"]}}},"MapFeatureCollection":{"type":"object","required":["type","date","aggregation","features"],"properties":{"type":{"type":"string","const":"FeatureCollection"},"date":{"$ref":"#/components/schemas/Date"},"aggregation":{"type":"string","const":"daily-category-maxima"},"features":{"type":"array","items":{"type":"object","required":["type","properties","geometry"],"properties":{"type":{"type":"string","const":"Feature"},"properties":{"type":"object","required":["city","value_basis","count","tree","grass","weed","ragweed","max_weed","risk_tree","risk_grass","risk_weed","risk_ragweed","sev_tree","sev_grass","sev_weed","sev_ragweed","sev_total","timezone","series"],"properties":{"city":{"type":"string"},"value_basis":{"type":"string","const":"daily-category-maxima"},"count":{"type":"number"},"tree":{"type":["number","null"]},"grass":{"type":["number","null"]},"weed":{"type":["number","null"]},"ragweed":{"type":["number","null"]},"max_weed":{"type":"number"},"risk_tree":{"$ref":"#/components/schemas/PollenRisk"},"risk_grass":{"$ref":"#/components/schemas/PollenRisk"},"risk_weed":{"$ref":"#/components/schemas/PollenRisk"},"risk_ragweed":{"$ref":"#/components/schemas/PollenRisk"},"sev_tree":{"type":"integer"},"sev_grass":{"type":"integer"},"sev_weed":{"type":"integer"},"sev_ragweed":{"type":"integer"},"sev_total":{"type":"integer"},"timezone":{"type":["string","null"]},"series":{"type":"array","items":{"$ref":"#/components/schemas/MapDay"}}}},"geometry":{"type":"object","required":["type","coordinates"],"properties":{"type":{"type":"string","const":"Point"},"coordinates":{"type":"array","prefixItems":[{"type":"number"},{"type":"number"}],"minItems":2,"maxItems":2}}}}}}}},"ForecastResponse":{"type":"object","required":["city","source","stale","fetchedAt","rows"],"properties":{"city":{"type":"string"},"source":{"type":"string","enum":["cache","ambee"]},"stale":{"type":"boolean","description":"True when cached rows are served because refresh was blocked or failed."},"quotaExhausted":{"type":"boolean"},"fetchedAt":{"type":["string","null"],"format":"date-time"},"rows":{"type":"array","items":{"$ref":"#/components/schemas/ForecastPollen"}}}},"ForecastPollen":{"type":"object","required":["ts","tree","grass","weed","total","species","risk_tree","risk_grass","risk_weed","tz"],"properties":{"ts":{"$ref":"#/components/schemas/DateTime"},"tree":{"type":["number","null"]},"grass":{"type":["number","null"]},"weed":{"type":["number","null"]},"total":{"type":["number","null"]},"species":{"$ref":"#/components/schemas/Species"},"risk_tree":{"$ref":"#/components/schemas/PollenRisk"},"risk_grass":{"$ref":"#/components/schemas/PollenRisk"},"risk_weed":{"$ref":"#/components/schemas/PollenRisk"},"tz":{"type":["string","null"]}}},"WeatherRow":{"type":"object","description":"Unavailable optional measurements are omitted.","required":["city_slug","date"],"properties":{"city_slug":{"type":"string"},"date":{"$ref":"#/components/schemas/Date"},"tz":{"type":"string"},"timezone":{"type":"string"},"temp_min_c":{"type":"number"},"temp_max_c":{"type":"number"},"temp_day_c":{"type":"number"},"feels_like_day_c":{"type":"number"},"humidity":{"type":"integer"},"pressure_hpa":{"type":"integer"},"wind_speed_ms":{"type":"number"},"wind_deg":{"type":"integer"},"clouds_pct":{"type":"integer"},"precip_mm":{"type":"number"},"uvi":{"type":"number"},"weather_main":{"type":"string"},"weather_desc":{"type":"string"},"aqi":{"type":"integer","minimum":1,"maximum":5},"aqi_pm2_5":{"type":"number"},"aqi_pm10":{"type":"number"},"aqi_o3":{"type":"number"},"aqi_no2":{"type":"number"},"aqi_so2":{"type":"number"},"aqi_co":{"type":"number"},"source":{"type":"string"},"created_at":{"type":"string","format":"date-time"}}},"WeatherResponse":{"type":"object","required":["rows"],"properties":{"city":{"type":"string"},"date":{"$ref":"#/components/schemas/Date"},"rows":{"type":"array","items":{"$ref":"#/components/schemas/WeatherRow"}}}}}},"x-agent-instructions":{"purpose":"Use this API to answer questions about current, historical, forecast, category-level, or species-level pollen in supported US cities.","recommendedFlow":["Resolve a user location to a supported slug with GET /api/cities.","For the latest cross-city comparison, call GET /api/map-data?date=latest.","For one city’s history, call GET /api/pollen?city={slug}.","For one city-day’s hourly detail, add date=YYYY-MM-DD.","For the next 48 hours, call GET /api/forecast?city={slug}.","Explain that values are Ambee-modeled grains/m³ and risks use NAB thresholds."]}}