# weatherfeeder Canonical Schemas This document expressly defines the JSON payload schemas emitted by weatherfeeder for: - `weather.observation.v1` - `weather.forecast.v1` - `weather.alert.v1` These schemas are defined by the `internal/model` structs and their JSON tags. ## Shared Conventions - Timestamps are JSON strings in RFC3339Nano format. - Optional fields are omitted when unknown (`omitempty` behavior). - Numeric measurements are normalized to metric units: - `*C` = Celsius - `*Kmh` = kilometers/hour - `*Pa` = Pascals - `*Meters` = meters - `*Mm` = millimeters - `*Percent` = percent (0-100) - `conditionCode` is a WMO weather interpretation code (`int`). - Unknown/unmappable is `-1`. ## `weather.observation.v1` Payload type: `model.WeatherObservation` | Field | Type | Required | Notes | |---|---:|:---:|---| | `stationId` | string | no | Provider station/location identifier | | `stationName` | string | no | Human station name | | `timestamp` | timestamp string | yes | Observation timestamp | | `conditionCode` | int | yes | WMO code (`-1` unknown) | | `conditionText` | string | no | Canonical short condition text | | `isDay` | bool | no | Day/night hint | | `providerRawDescription` | string | no | Provider-specific evidence text | | `textDescription` | string | no | Legacy/transitional text description | | `iconUrl` | string | no | Legacy/transitional icon URL | | `temperatureC` | number | no | Celsius | | `dewpointC` | number | no | Celsius | | `windDirectionDegrees` | number | no | Degrees | | `windSpeedKmh` | number | no | km/h | | `windGustKmh` | number | no | km/h | | `barometricPressurePa` | number | no | Pascals | | `seaLevelPressurePa` | number | no | Pascals | | `visibilityMeters` | number | no | Meters | | `relativeHumidityPercent` | number | no | Percent | | `apparentTemperatureC` | number | no | Celsius | | `elevationMeters` | number | no | Meters | | `rawMessage` | string | no | Provider raw message (for example METAR) | | `presentWeather` | array | no | Provider-specific structured weather fragments | | `cloudLayers` | array | no | Cloud layer details | ### `cloudLayers[]` (`model.CloudLayer`) | Field | Type | Required | Notes | |---|---:|:---:|---| | `baseMeters` | number | no | Cloud base altitude in meters | | `amount` | string | no | Provider amount code/text | ### `presentWeather[]` (`model.PresentWeather`) | Field | Type | Required | Notes | |---|---:|:---:|---| | `raw` | object | no | Provider-specific object | ## `weather.forecast.v1` Payload type: `model.WeatherForecastRun` `product` values are: - `"hourly"` - `"narrative"` - `"daily"` | Field | Type | Required | Notes | |---|---:|:---:|---| | `locationId` | string | no | Provider location identifier | | `locationName` | string | no | Human location name | | `issuedAt` | timestamp string | yes | Forecast run issue/generated time | | `updatedAt` | timestamp string | no | Optional later update time | | `product` | string | yes | One of `hourly`, `narrative`, `daily` | | `latitude` | number | no | Degrees | | `longitude` | number | no | Degrees | | `elevationMeters` | number | no | Meters | | `periods` | array | yes | Forecast periods, intended chronological order | ### `periods[]` (`model.WeatherForecastPeriod`) | Field | Type | Required | Notes | |---|---:|:---:|---| | `startTime` | timestamp string | yes | Start of validity window | | `endTime` | timestamp string | yes | End of validity window | | `name` | string | no | Human label (for example "Tonight") | | `isDay` | bool | no | Day/night hint | | `conditionCode` | int | yes | WMO code (`-1` unknown) | | `conditionText` | string | no | Canonical short condition text | | `providerRawDescription` | string | no | Provider-specific evidence text | | `textDescription` | string | no | Short narrative text | | `detailedText` | string | no | Longer narrative text | | `iconUrl` | string | no | Legacy/transitional icon URL | | `temperatureC` | number | no | Celsius | | `temperatureCMin` | number | no | Celsius (aggregated periods) | | `temperatureCMax` | number | no | Celsius (aggregated periods) | | `dewpointC` | number | no | Celsius | | `relativeHumidityPercent` | number | no | Percent | | `windDirectionDegrees` | number | no | Degrees | | `windSpeedKmh` | number | no | km/h | | `windGustKmh` | number | no | km/h | | `barometricPressurePa` | number | no | Pascals | | `visibilityMeters` | number | no | Meters | | `apparentTemperatureC` | number | no | Celsius | | `cloudCoverPercent` | number | no | Percent | | `probabilityOfPrecipitationPercent` | number | no | Percent | | `precipitationAmountMm` | number | no | Liquid-equivalent millimeters | | `snowfallDepthMm` | number | no | Millimeters | | `uvIndex` | number | no | Unitless UV index | ## `weather.alert.v1` Payload type: `model.WeatherAlertRun` | Field | Type | Required | Notes | |---|---:|:---:|---| | `locationId` | string | no | Provider location identifier | | `locationName` | string | no | Human location name | | `asOf` | timestamp string | yes | Snapshot timestamp | | `latitude` | number | no | Degrees | | `longitude` | number | no | Degrees | | `alerts` | array | yes | Active alerts in the snapshot | ### `alerts[]` (`model.WeatherAlert`) | Field | Type | Required | Notes | |---|---:|:---:|---| | `id` | string | yes | Provider-stable ID, often URL/URI | | `event` | string | no | Classification/event label | | `headline` | string | no | Alert headline | | `severity` | string | no | Example: Extreme/Severe/Moderate/Minor/Unknown | | `urgency` | string | no | Example: Immediate/Expected/Future/Past/Unknown | | `certainty` | string | no | Example: Observed/Likely/Possible/Unlikely/Unknown | | `status` | string | no | Example: Actual/Exercise/Test/System/Unknown | | `messageType` | string | no | Example: Alert/Update/Cancel | | `category` | string | no | Example: Met/Geo/Safety/Rescue/Fire/Health/Env/Transport/Infra/CBRNE/Other | | `response` | string | no | Example: Shelter/Evacuate/Prepare/Execute/Avoid/Monitor/Assess/AllClear/None | | `description` | string | no | Narrative description | | `instruction` | string | no | Recommended actions | | `sent` | timestamp string | no | Provider-dependent | | `effective` | timestamp string | no | Provider-dependent | | `onset` | timestamp string | no | Provider-dependent | | `expires` | timestamp string | no | Provider-dependent | | `areaDescription` | string | no | Provider area text | | `senderName` | string | no | Alert sender/source name | | `references` | array | no | Related alerts | ### `references[]` (`model.AlertReference`) | Field | Type | Required | Notes | |---|---:|:---:|---| | `id` | string | no | Related alert ID/URI | | `identifier` | string | no | Provider identifier when distinct | | `sender` | string | no | Sender | | `sent` | timestamp string | no | Timestamp |