Files
weatherreporter/docs/integrations/weatherapi.md

6.0 KiB

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 weatherdata.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:

{
  "data": {}
}

For most sources, 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.

/alerts/active is the exception: a successful response with data: null means the endpoint was checked and there are no current active alerts. The adapter records a non-missing alerts source and an empty alert run.

For /outlooks/convective, data: null means no latest run is available and follows missing-source policy. A non-null run with empty outlooks and discussions arrays is checked empty data, not a missing source.

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; configuration validation 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, discussion, and SPC convective outlook requests

Alerts do not receive precision or tz. Weather story requests receive only format=json. SPC convective outlook requests receive only format=json and tz; they do not receive units or precision.

SPC Convective Outlooks

The adapter fetches SPC convective outlook data from:

GET /outlooks/convective?format=json&tz=<weather_api.timezone>

The response uses the standard data envelope. data: null means no latest run is available and follows missing-source policy. A non-null object with empty outlooks and discussions arrays is accepted as checked empty data.

Run fields consumed by weatherreporter:

  • locationId
  • locationName
  • asOf
  • issuedAt
  • updatedAt
  • product
  • outlooks
  • discussions

Outlook fields consumed:

  • id
  • provider
  • product
  • day
  • outlookType
  • label
  • labelText
  • forecaster
  • severityRank
  • validFrom
  • validTo
  • issuedAt
  • expiresAt
  • sourceUrl
  • imageUrl
  • containsLocation
  • geometry

Discussion fields consumed:

  • day
  • headline
  • summary
  • discussion
  • updatedAt

GeoJSON geometry is decoded into collected weather facts and persisted in bundle/debug artifacts, but prompt-facing SPC module output omits geometry.

Endpoints Used

The adapter fetches these endpoints once per bundle:

  • /observations
  • /conditions/current
  • /forecast/hourly
  • /forecast/narrative
  • /alerts/active
  • /discussion
  • /weatherstories/latest
  • /outlooks/convective

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
  • weather_story for /weatherstories/latest
  • spc_convective_outlooks for /outlooks/convective

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

For /alerts/active, an HTTP error or missing data field still fails or follows the relevant error path, but explicit data: null is not a missing-source condition.

For /outlooks/convective, a non-null data object with empty outlook and discussion arrays is accepted as checked empty data.

Source Identity

For source payloads accepted into the bundle, including the explicit null alerts payload, 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 weather data bundle types in internal/weatherdata/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 section text
  • latest weather story title, description, timing, priority, order, alt text, and download URL
  • SPC convective outlook run metadata, outlooks, discussions, and GeoJSON geometry

The adapter intentionally keeps upstream transport and envelope details inside internal/adapters/weatherapi; downstream packages consume the normalized bundle.