# 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 requests `/conditions/current` with the same `format`, `units`, and `precision` query parameters used for current conditions. After a readable 2xx response, it retains that response for the normal current-conditions source step rather than making a second identical request. Failure after the readiness request's internal retry budget stops the fetch before source requests begin. ## Endpoints And Query Parameters The adapter makes one source request for each endpoint, subject to retry on transient failures. A successful readiness request supplies the current conditions source response. The remaining independent source requests run concurrently, then their results are processed in the source order shown below. This keeps source provenance, missing-source policy, and surfaced errors deterministic regardless of response order. | 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`. Every hourly period needs nonzero `startTime` and `endTime` values, with `endTime` after `startTime`; a missing, malformed, empty, or invalidly bounded 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.