{"openapi":"3.1.0","jsonSchemaDialect":"https://json-schema.org/draft/2020-12/schema","info":{"title":"Strata Weather API","version":"1.0.0-pilot","description":"Keyed weather, observed radar, alerts, historical observations, route context, and evidence-backed risk endpoints.","contact":{"name":"Strata Weather API operations"}},"servers":[{"url":"https://www.strataweather.app","description":"Current deployment"}],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"tags":[{"name":"Weather"},{"name":"Layers"},{"name":"Routes"},{"name":"Risk"},{"name":"Webhooks"}],"paths":{"/api/v1/weather/bundle":{"get":{"tags":["Weather"],"summary":"Get point weather bundle","parameters":[{"name":"lat","in":"query","required":true,"schema":{"type":"number","minimum":-90,"maximum":90}},{"name":"lon","in":"query","required":true,"schema":{"type":"number","minimum":-180,"maximum":180}}],"responses":{"200":{"$ref":"#/components/responses/Success"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"502":{"$ref":"#/components/responses/Error"},"503":{"$ref":"#/components/responses/Error"}}}},"/api/v1/alerts":{"get":{"tags":["Weather"],"summary":"Get active official alerts","parameters":[{"name":"lat","in":"query","required":true,"schema":{"type":"number","minimum":-90,"maximum":90}},{"name":"lon","in":"query","required":true,"schema":{"type":"number","minimum":-180,"maximum":180}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":50}}],"responses":{"200":{"$ref":"#/components/responses/Success"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"502":{"$ref":"#/components/responses/Error"},"503":{"$ref":"#/components/responses/Error"}}}},"/api/v1/astro":{"get":{"tags":["Weather"],"summary":"Get the astro almanac at a point","parameters":[{"name":"lat","in":"query","required":true,"schema":{"type":"number","minimum":-90,"maximum":90}},{"name":"lon","in":"query","required":true,"schema":{"type":"number","minimum":-180,"maximum":180}},{"name":"date","in":"query","required":false,"schema":{"type":"string","format":"date"}},{"name":"days","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":31}}],"responses":{"200":{"$ref":"#/components/responses/Success"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"502":{"$ref":"#/components/responses/Error"},"503":{"$ref":"#/components/responses/Error"}},"description":"Deterministic solar windows (sunrise/sunset, golden and blue hour), day-length trend, moon state, and upcoming meteor-shower peaks and eclipses. Pure NOAA solar geometry plus a static yearly-refresh event almanac — no observations or forecasts. Day boundary is solar-local, derived from longitude. days=2..31 appends compact per-day solar and moon summaries (followingDays)."}},"/api/v1/historical/day":{"get":{"tags":["Weather"],"summary":"Get an archived station-day observation","parameters":[{"name":"lat","in":"query","required":true,"schema":{"type":"number","minimum":-90,"maximum":90}},{"name":"lon","in":"query","required":true,"schema":{"type":"number","minimum":-180,"maximum":180}},{"name":"date","in":"query","required":true,"schema":{"type":"string","format":"date"}}],"responses":{"200":{"$ref":"#/components/responses/Success"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"502":{"$ref":"#/components/responses/Error"},"503":{"$ref":"#/components/responses/Error"}},"description":"Returns NOAA GHCN-Daily observations from the nearest ingested U.S. Climate Normals reference station. Dates must be complete UTC days from 1950-01-01 onward."}},"/api/v1/layers/latest":{"get":{"tags":["Layers"],"summary":"Get latest production layer","parameters":[{"name":"kind","in":"query","required":true,"schema":{"type":"string"}},{"name":"source","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"$ref":"#/components/responses/Success"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"502":{"$ref":"#/components/responses/Error"},"503":{"$ref":"#/components/responses/Error"}}}},"/api/v1/layers/history":{"get":{"tags":["Layers"],"summary":"Get production layer history","parameters":[{"name":"kind","in":"query","required":true,"schema":{"type":"string"}},{"name":"source","in":"query","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":96}},{"name":"from","in":"query","required":false,"schema":{"type":"string"}},{"name":"to","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"$ref":"#/components/responses/Success"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"502":{"$ref":"#/components/responses/Error"},"503":{"$ref":"#/components/responses/Error"}}}},"/api/v1/route/weather":{"post":{"tags":["Routes"],"summary":"Evaluate weather along a route","parameters":[],"responses":{"200":{"$ref":"#/components/responses/Success"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"502":{"$ref":"#/components/responses/Error"},"503":{"$ref":"#/components/responses/Error"}},"description":"Returns existing point bundles plus optional segment distance, alerts, AQI, freshness, and decision context. Usage cost equals point count.","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/RoutePointsRequest"},{"$ref":"#/components/schemas/RouteCoordinatesRequest"}]}}}}}},"/api/v1/risk/property":{"get":{"tags":["Risk"],"summary":"Get property risk evidence","parameters":[{"name":"lat","in":"query","required":true,"schema":{"type":"number","minimum":-90,"maximum":90}},{"name":"lon","in":"query","required":true,"schema":{"type":"number","minimum":-180,"maximum":180}},{"name":"areaKey","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"$ref":"#/components/responses/Success"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"502":{"$ref":"#/components/responses/Error"},"503":{"$ref":"#/components/responses/Error"}},"description":"Requires a pro API key and a production risk artifact."}},"/api/v1/minutecast":{"get":{"tags":["Probabilistic"],"summary":"Get next-hour precipitation steps and summary from the Flow nowcast","parameters":[{"name":"lat","in":"query","required":true,"schema":{"type":"number","minimum":-90,"maximum":90}},{"name":"lon","in":"query","required":true,"schema":{"type":"number","minimum":-180,"maximum":180}}],"responses":{"200":{"$ref":"#/components/responses/Success"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"502":{"$ref":"#/components/responses/Error"},"503":{"$ref":"#/components/responses/Error"}}}},"/api/v1/forecast/probabilistic":{"get":{"tags":["Probabilistic"],"summary":"Get calibrated fused quantiles (p10/p50/p90) and exceedance probabilities per lead","parameters":[{"name":"lat","in":"query","required":true,"schema":{"type":"number","minimum":-90,"maximum":90}},{"name":"lon","in":"query","required":true,"schema":{"type":"number","minimum":-180,"maximum":180}},{"name":"variable","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"$ref":"#/components/responses/Success"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"502":{"$ref":"#/components/responses/Error"},"503":{"$ref":"#/components/responses/Error"}}}},"/api/v1/indices":{"get":{"tags":["Indices"],"summary":"Get operational index series (road icing, outdoor work, energy demand, event comfort)","parameters":[{"name":"lat","in":"query","required":true,"schema":{"type":"number","minimum":-90,"maximum":90}},{"name":"lon","in":"query","required":true,"schema":{"type":"number","minimum":-180,"maximum":180}},{"name":"indexId","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"$ref":"#/components/responses/Success"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"502":{"$ref":"#/components/responses/Error"},"503":{"$ref":"#/components/responses/Error"}}}},"/api/v1/insights/timeline":{"get":{"tags":["Indices"],"summary":"Get band-crossing insight events derived from the operational index series","parameters":[{"name":"lat","in":"query","required":true,"schema":{"type":"number","minimum":-90,"maximum":90}},{"name":"lon","in":"query","required":true,"schema":{"type":"number","minimum":-180,"maximum":180}}],"responses":{"200":{"$ref":"#/components/responses/Success"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"502":{"$ref":"#/components/responses/Error"},"503":{"$ref":"#/components/responses/Error"}}}},"/api/v1/verticals":{"get":{"tags":["Indices"],"summary":"Get vertical templates: endpoint, index, layer, and trigger presets per sector","parameters":[],"responses":{"200":{"$ref":"#/components/responses/Success"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"502":{"$ref":"#/components/responses/Error"},"503":{"$ref":"#/components/responses/Error"}}}},"/api/v1/webhooks/triggers":{"get":{"tags":["Webhooks"],"summary":"List threshold triggers","parameters":[],"responses":{"200":{"$ref":"#/components/responses/Success"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"502":{"$ref":"#/components/responses/Error"},"503":{"$ref":"#/components/responses/Error"}}},"post":{"tags":["Webhooks"],"summary":"Create threshold or event-driven forecast-change trigger","parameters":[],"responses":{"200":{"$ref":"#/components/responses/Success"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"502":{"$ref":"#/components/responses/Error"},"503":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","endpointUrl","latitude","longitude","metric","operator","threshold"],"properties":{"name":{"type":"string","maxLength":80},"endpointUrl":{"type":"string","format":"uri","pattern":"^https://"},"latitude":{"type":"number","minimum":-90,"maximum":90},"longitude":{"type":"number","minimum":-180,"maximum":180},"metric":{"type":"string","enum":["temperature_f","wind_speed_mph","wind_gust_mph","active_alert_count","road_icing_risk","outdoor_work_score","energy_demand_signal","event_comfort_score","precip_start_minutes","forecast_change_score"]},"operator":{"type":"string","enum":["gt","gte","lt","lte"]},"threshold":{"type":"number"},"locationKey":{"type":"string","maxLength":160},"watchValidFrom":{"type":"integer","description":"Optional watched-window start in Unix milliseconds"},"watchValidTo":{"type":"integer","description":"Optional watched-window end in Unix milliseconds"},"routineId":{"type":"string","maxLength":80},"intervalMinutes":{"type":"integer","minimum":5},"cooldownMinutes":{"type":"integer","minimum":15}},"additionalProperties":false}}}}}},"/api/v1/webhooks/triggers/{triggerId}":{"delete":{"tags":["Webhooks"],"summary":"Disable threshold trigger","parameters":[{"name":"triggerId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"$ref":"#/components/responses/Success"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"502":{"$ref":"#/components/responses/Error"},"503":{"$ref":"#/components/responses/Error"}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"Strata API key"},"apiKeyHeader":{"type":"apiKey","in":"header","name":"x-api-key"}},"schemas":{"SuccessEnvelope":{"type":"object","required":["data","meta","usage"],"properties":{"data":true,"meta":{"type":"object","required":["attribution","generatedAt","requestId"],"properties":{"attribution":{"const":"Strata Weather"},"generatedAt":{"type":"string","format":"date-time"},"requestId":{"type":"string"}},"additionalProperties":true},"usage":{"type":"object","required":["dailyQuota","remaining"],"properties":{"dailyQuota":{"type":"integer","minimum":0},"remaining":{"type":"integer","minimum":0}}}}},"ErrorEnvelope":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message","requestId"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"requestId":{"type":"string"}},"additionalProperties":true}}},"RoutePoint":{"type":"object","required":["lat","lon"],"properties":{"lat":{"type":"number","minimum":-90,"maximum":90},"lon":{"type":"number","minimum":-180,"maximum":180}}},"RoutePointsRequest":{"type":"object","required":["points"],"properties":{"points":{"type":"array","minItems":2,"maxItems":25,"items":{"$ref":"#/components/schemas/RoutePoint"}}}},"RouteCoordinatesRequest":{"type":"object","required":["coordinates"],"properties":{"coordinates":{"type":"array","minItems":2,"maxItems":25,"items":{"type":"array","prefixItems":[{"type":"number","minimum":-180,"maximum":180},{"type":"number","minimum":-90,"maximum":90}],"minItems":2,"maxItems":2}}}}},"responses":{"Success":{"description":"Successful response","headers":{"X-Request-ID":{"schema":{"type":"string"}},"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}},"X-RateLimit-Reset":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope"}}}},"Error":{"description":"Standard API error","headers":{"X-Request-ID":{"schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}}