# Weather API Integration Weatherreporter fetches normalized weather inputs from a configured Weather API base URL. This guide defines the HTTP contract the service must satisfy; it is not a general Weather API reference. Configuration values are defined in the [configuration reference](../config.md). Normalization and collection behavior are documented in [Weather data internals](../internal/weather-data.md) and [Collection internals](../internal/collect.md). ## Base URL And Requests `weather_api.base_url` must be an absolute HTTP(S) URL. Weatherreporter joins each endpoint path to the configured base URL path, so a service hosted under a path prefix must keep that prefix available. Requests use `GET` and carry the configured timeout on every HTTP attempt. Every request sends `format` and, except where noted below, `units`. The configured format must be `json`. Before retrieving sources, Weatherreporter warms up `/conditions/current` with the same `format`, `units`, and `precision` query parameters used for current conditions. The warmup only requires a readable 2xx response; its body is not decoded. Failure after its internal retry budget stops the fetch before source requests begin. ## Endpoints And Query Parameters The adapter makes one source request for each endpoint after a successful warmup, subject to retry on transient failures. | Source | Endpoint | Query parameters | Availability | | --- | --- | --- | --- | | Observations | `/observations` | `format`, `units`, `precision` | Optional | | Current conditions | `/conditions/current` | `format`, `units`, `precision` | Optional | | Hourly forecast | `/forecast/hourly` | `format`, `units`, `precision`, `tz` | Required | | Narrative forecast | `/forecast/narrative` | `format`, `units`, `precision`, `tz` | Optional | | Active alerts | `/alerts/active` | `format`, `units` | Optional; `data: null` means checked with no active alerts | | Forecast discussion | `/discussion` | `format`, `units`, `tz` | Optional | | Weather story | `/weatherstories/latest` | `format` | Optional | | SPC convective outlooks | `/outlooks/convective` | `format`, `tz` | Optional; non-null empty lists are checked empty data | `precision` comes from `weather_api.precision`; `tz` comes from `weather_api.timezone`. Weatherreporter does not call day-slice forecast or discussion-subsection endpoints. ## Response Envelope Each endpoint response must be JSON with a top-level `data` member: ```json { "data": {} } ``` An absent `data` member is treated as a missing source. For ordinary sources, `data: null` is also missing. The active-alert exception is listed above: its explicit `null` payload represents an empty alert result. Hourly forecast data must be present and contain at least one `period`; a missing, malformed, or empty hourly product fails collection. The remaining sources follow the configured missing-source policy. Under `error`, collection fails; under `warn`, the source is omitted and an inspectable warning is recorded; under `none`, the source is omitted without a warning. A per-source policy overrides the default. See [Configuration](../config.md) for policy settings and [Weather data internals](../internal/weather-data.md) for recorded source metadata. Malformed top-level JSON envelopes and HTTP failures are direct request errors. Malformed `data` for an optional source follows its missing-source policy. ## Payload Fields Used Weatherreporter decodes only the fields below; additional upstream fields are ignored. Timestamps must be JSON values accepted by Go's `time.Time` decoder. ### Observations And Current Conditions `/observations` uses `stationId`, `stationName`, `timestamp`, `conditionCode`, `isDay`, `textDescription`, `temperatureC`, `temperatureF`, `dewpointC`, `dewpointF`, `windSpeedKmh`, `windSpeedMph`, `windGustKmh`, `windGustMph`, `windDirectionDegrees`, `barometricPressurePa`, `barometricPressureInHg`, `visibilityMeters`, `visibilityMiles`, `relativeHumidityPercent`, `apparentTemperatureC`, `apparentTemperatureF`, and `presentWeather`. `/conditions/current` uses `conditionText`, `isDay`, `relativeHumidityPercent`, `windDirectionDegrees`, `temperatureC`, `temperatureF`, `apparentTemperatureC`, `apparentTemperatureF`, `dewpointC`, `dewpointF`, `windSpeedKmh`, and `windSpeedMph`. ### Hourly And Narrative Forecasts Both forecast endpoints use run-level `locationId`, `locationName`, `issuedAt`, `updatedAt`, `product`, `latitude`, `longitude`, `elevationMeters`, `elevationFeet`, and `periods`. Each `periods` item uses `startTime`, `endTime`, `name`, `isDay`, `conditionCode`, `textDescription`, `temperatureC`, `temperatureF`, `temperatureCMin`, `temperatureFMin`, `temperatureCMax`, `temperatureFMax`, `dewpointC`, `dewpointF`, `windSpeedKmh`, `windSpeedMph`, `windGustKmh`, `windGustMph`, `windDirectionDegrees`, `barometricPressurePa`, `barometricPressureInHg`, `visibilityMeters`, `visibilityMiles`, `apparentTemperatureC`, `apparentTemperatureF`, `cloudCoverPercent`, `probabilityOfPrecipitationPercent`, `precipitationAmountMm`, `precipitationAmountIn`, `snowfallDepthMM`, `snowfallDepthIn`, `uvIndex`, and `relativeHumidityPercent`. ### Alerts, Discussion, And Weather Story `/alerts/active` uses the `asOf` timestamp and keeps each item in `alerts` as an alert payload. Weatherreporter does not require a separate alert-item schema at this integration boundary. `/discussion` uses `officeId`, `officeName`, `product`, `issuedAt`, `updatedAt`, `keyMessages`, and the `shortTerm` and `longTerm` sections. Each section uses `qualifier`, `text`, and `issuedAt`. `/weatherstories/latest` uses `officeId`, `startTime`, `endTime`, `updatedAt`, `title`, `description`, `altText`, `priority`, `order`, and `downloadUrl`. ### SPC Convective Outlooks `/outlooks/convective` uses run-level `locationId`, `locationName`, `asOf`, `issuedAt`, `updatedAt`, `product`, `outlooks`, and `discussions`. Each outlook uses `id`, `provider`, `product`, `day`, `outlookType`, `label`, `labelText`, `forecaster`, `severityRank`, `validFrom`, `validTo`, `issuedAt`, `expiresAt`, `sourceUrl`, `imageUrl`, `containsLocation`, and GeoJSON `geometry`. Each discussion uses `day`, `headline`, `summary`, `discussion`, and `updatedAt`. ## Timeouts, Retries, And Failures The configured Weather API timeout applies to each warmup and source HTTP attempt. Weatherreporter retries transient transport and response-read failures and these response statuses: `408`, `429`, `500`, `502`, `503`, and `504`. It does not retry other HTTP statuses, malformed envelopes, missing data, or payload decoding failures. A canceled context also stops an in-progress retry delay. The adapter accepts response bodies up to 10 MiB and rejects larger bodies before decoding. A non-2xx response reports its relative endpoint and status, without including upstream response text. Request construction, response-limit, read, and decode failures include endpoint context in their errors. Retry counts and delays are adapter behavior rather than Weather API request parameters. Do not depend on a particular attempt count when implementing the service.