Files
weatherreporter/docs/integrations/weatherapi.md

123 lines
3.8 KiB
Markdown

# Weather API Integration
This document describes the external Weather API contract used by
`weatherreporter`.
## Purpose
`weatherreporter` uses a configured Weather API base URL to fetch normalized
weather source data and assemble a `forecast.Bundle`. This is an integration
contract for the project adapter, not a complete public API reference for the
upstream service.
## Base URL
`weather_api.base_url` must be an absolute URL. Adapter requests join this base
URL with the endpoint paths listed below. Generation and explicit bundle fetches
fail before any HTTP request when the base URL is empty or not absolute.
The HTTP client uses `weather_api.timeout`.
## Response Envelope
Every response used by the adapter must be JSON with a top-level `data` field:
```json
{
"data": {}
}
```
`data: null` is treated as a missing source. Missing optional sources follow the
configured missing-source policy. Missing hourly forecast data fails bundle
fetching because hourly periods are required for report generation.
Malformed JSON envelopes, non-2xx statuses, and response read failures include
endpoint context in returned errors. Decode errors include source context when
they fail the fetch; optional malformed sources follow the missing-source policy.
## Query Parameters
The adapter sends these query parameters:
- `format`: from `weather_api.format`; the implemented configuration requires
`json`
- `units`: from `weather_api.units`
- `precision`: from `weather_api.precision` on observations, current
conditions, hourly forecast, and narrative forecast requests
- `tz`: from `weather_api.timezone` on hourly forecast, narrative forecast, and
discussion requests
Alerts do not receive `precision` or `tz`.
## Endpoints Used
The adapter fetches these endpoints once per bundle:
- `/observations`
- `/conditions/current`
- `/forecast/hourly`
- `/forecast/narrative`
- `/alerts/active`
- `/discussion`
`weatherreporter` does not call day-slice forecast endpoints or discussion
subsection endpoints. Report-period selection and daypart summarization happen
inside Go after the full hourly and narrative products are fetched.
## Required And Optional Sources
Hourly forecast is required:
- `data: null` for `/forecast/hourly` fails the fetch.
- an hourly forecast with no `periods` fails the fetch.
- malformed hourly data fails the fetch.
Other fetched sources are optional and follow `missing_source.default` or a
source-specific `missing_source.sources` policy:
- `observations` for `/observations`
- `current` for `/conditions/current`
- `narrative` for `/forecast/narrative`
- `alerts` for `/alerts/active`
- `discussion` for `/discussion`
The adapter also creates missing stub source records for `daily` and
`weather_story` because those source slots exist in the internal bundle but are
not fetched from the Weather API.
Policy behavior:
- `error`: fail the fetch for that source
- `warn`: omit the source data, add a warning, and continue
- `none`: omit the source data and continue without a warning
## Source Identity
For non-null source payloads, the adapter records:
- source name
- endpoint path
- query parameters sent
- fetch time
- source issue and update timestamps when present in the payload
- SHA-256 hash of the compact raw `data` JSON
Warnings are recorded both on the affected source and on the bundle-level
warnings list.
## Compatibility Assumptions
The adapter expects payload fields compatible with the internal forecast bundle
types in `internal/forecast/bundle.go`, including:
- observation timestamps and observation values
- current condition values
- forecast run metadata and `periods`
- active alert run data
- discussion metadata, key messages, and short/long-term sections
The adapter intentionally keeps upstream transport and envelope details inside
`internal/adapters/weatherapi`; downstream packages consume the normalized
bundle.