Files
weatherapi/docs/api.md
Eric Rakestraw 5a1134b955
All checks were successful
ci/woodpecker/manual/build-image Pipeline was successful
Suppress superseded alerts in the /alerts/active endpoint
2026-06-17 06:48:14 -05:00

16 KiB

weatherapi HTTP API

This is the canonical public HTTP contract for weatherapi. The service is a read-only API over the latest weather records available in the configured weatherfeeder-populated Postgres database.

Base URL

All paths are relative to the deployment root:

http://localhost:8080

Use your deployment host in production.

Authentication

weatherapi does not implement authentication or authorization. Put access control in front of the service when a deployment requires it.

Response Envelope

Successful JSON and XML responses use a top-level envelope:

{
  "data": {}
}

When no latest/current resource exists, the request still succeeds and returns data: null.

Text responses are rendered from endpoint-specific templates. When the payload is missing, the templates return a short no-data message.

Formats

Every implemented endpoint can produce:

Format Media type
json application/json
xml application/xml
text text/plain

Format selection is:

  1. format query parameter;
  2. Accept header;
  3. configured server.default_format.

format values are case-insensitive. Unsupported formats return 406 Not Acceptable with an error envelope.

Shared Query Rules

Unknown query parameters are rejected with 400 Bad Request.

Parameter Values Default Supported on
format json, xml, text configured default all endpoints
units metric, us metric all endpoints
precision integer 0 through 2 0 observations, current conditions, forecasts
tz or TZ timezone selector UTC/no conversion forecasts, discussions, weather stories, outlooks

units, format, and precision values are normalized case-insensitively where applicable. units=metric returns metric field names; units=us returns US-customary field names for unit-bearing payloads. Alerts, discussions, and weather stories accept units but their current payload fields are not materially changed by it. Outlooks also accept units without changing payload values or field names.

precision controls numeric rounding. The default 0 rounds to whole numbers. precision is rejected on alerts, discussions, weather stories, and outlooks.

Timezone selectors accepted by tz / TZ:

  • IANA timezone names such as America/Chicago;
  • common US abbreviations such as CDT, CST, EDT, EST, MDT, MST, PDT, and PST;
  • UTC offsets in +H, +HH, +HH:MM, -H, -HH, or -HH:MM form, bounded to -14:00 through +14:00;
  • aliases Chicago and Stl, both mapped to America/Chicago.

If both tz and TZ are provided, their values must match case-insensitively. Timezone conversion affects rendered timestamps and forecast /today and /tomorrow day-slice filtering. Without a timezone parameter, day-slice routes use UTC.

Errors

API errors use a stable error envelope:

{
  "error": {
    "code": "invalid_parameter",
    "message": "..."
  }
}

Implemented API error statuses:

Status Code Cause
400 Bad Request invalid_parameter unknown query parameter, invalid parameter value, invalid timezone, conflicting tz / TZ, or unsupported parameter on a route
406 Not Acceptable unsupported_format requested response format is not supported by the endpoint/renderers

Unhandled service or database errors are returned as server errors by the runtime.

Behavior Not Implemented

weatherapi does not implement pagination, cache-control headers, rate-limit headers, idempotency keys, retries, writes, or historical browsing outside the implemented latest-resource and forecast day-slice routes.

Endpoints

Observations

GET /observations

Returns the latest weather observation.

Query parameters: format, units, precision.

Metric data fields:

Field Type Notes
stationId, stationName string optional
timestamp RFC3339 datetime required when data is not null
conditionCode integer WMO weather code
isDay boolean optional
textDescription string optional
temperatureC, dewpointC, apparentTemperatureC number optional
windDirectionDegrees, windSpeedKmh, windGustKmh number optional
barometricPressurePa, visibilityMeters number optional
relativeHumidityPercent number optional
presentWeather array optional

US mode replaces unit-bearing fields with temperatureF, dewpointF, apparentTemperatureF, windSpeedMph, windGustMph, barometricPressureInHg, and visibilityMiles. Direction and percentage fields keep the same names.

Example:

GET /observations?units=us&precision=1

Current Conditions

GET /conditions/current

Returns current conditions aggregated from recent observations rows. The implemented observation window is 30 minutes.

Query parameters: format, units, precision.

Common data fields:

Field Type Notes
conditionText string optional text derived from WMO code and day/night flag
isDay boolean optional
relativeHumidityPercent number optional
windDirectionDegrees number optional

Metric fields: temperatureC, apparentTemperatureC, dewpointC, windSpeedKmh.

US fields: temperatureF, apparentTemperatureF, dewpointF, windSpeedMph.

Example:

GET /conditions/current?format=json&precision=0

Active Alerts

GET /alerts/active

Returns the latest stored alert run filtered to alerts active at request time, omitting older alerts superseded by newer alert references in the same run.

Query parameters: format, units.

When no latest alert run exists, data is null. When a latest run exists but no alerts are currently active, data remains an object and alerts is an empty array.

Run data fields:

Field Type Notes
locationId, locationName string optional
asOf RFC3339 datetime required when data is not null
latitude, longitude number optional
alerts array active alerts, possibly empty

Alerts are active when messageType is not Cancel, effective is absent or at or before request time, and the alert end boundary is absent or after request time. The end boundary prefers ends; if ends is absent, expires is used as a fallback for older rows or providers that do not supply an alert-period end. onset is presented when available but is not used as the active boundary. After active-time filtering, alerts referenced by another alert in the same run are omitted as superseded. References from update and cancel messages are both honored, even when the referencing alert is not itself returned.

Alert fields include id, event, headline, severity, urgency, certainty, status, messageType, category, response, description, instruction, sent, effective, onset, ends, expires, areaDescription, senderName, and references. Most alert fields are optional except id when an alert item is present. ends is the alert-period end; expires is provider expiration metadata.

Reference fields are id, identifier, sender, and sent.

Example:

GET /alerts/active?format=text

Convective Outlooks

GET /outlooks/convective
GET /outlooks/convective/active

Returns the latest SPC convective outlook run reconstructed from weatherfeeder-owned weather.outlook.v2 Postgres tables.

Route behavior:

  • /outlooks/convective returns the latest run with stored location-filtered outlook polygons unless user filters are supplied.
  • /outlooks/convective/active adds an active-time filter using the server's current UTC time. Outlooks are active when validFrom <= now < validTo.

When no latest run exists, data is null. When a run exists but filters match no outlooks, data remains an object and outlooks and discussions are empty arrays. Outlook endpoints use latest-run semantics and do not accumulate historical active outlooks across older runs.

Query parameters:

Parameter Supported on Values
format, units, tz / TZ all outlook routes shared rules above
day all outlook routes 1, 2, or 3
outlookType all outlook routes categorical, tornado, hail, or wind

outlookType values are normalized case-insensitively. Weatherfeeder v2 outlooks are already filtered for the configured location. precision, containsLocation, and unknown parameters are rejected.

Run data fields:

Field Type Notes
locationId, locationName string optional
latitude, longitude number optional
asOf RFC3339 datetime required when data is not null
issuedAt RFC3339 datetime optional
outlooks array ordered outlook polygons, possibly empty
discussions array ordered day-level discussions, possibly empty

Outlook fields:

Field Type Notes
id, provider, product, outlookType, label string required when an outlook is present
day integer SPC outlook day
labelText, forecaster string optional
severityRank integer optional
validFrom, validTo, issuedAt, expiresAt RFC3339 datetime required when an outlook is present
sourceUrl, imageUrl string optional
containsLocation boolean whether the outlook polygon contains the configured location
geometry GeoJSON stored outlook geometry

Discussion fields:

Field Type Notes
day integer SPC outlook day
headline, summary, discussion string optional
updatedAt RFC3339 datetime optional

GeoJSON coordinates use standard GeoJSON coordinate order: longitude, then latitude. Timezone conversion applies to run asOf, run issuedAt, and each outlook's validFrom, validTo, issuedAt, and expiresAt, and discussion updatedAt. Active filtering compares instants and is not changed by the presentation timezone. Endpoint filters also filter discussions to days represented by retained outlooks.

Examples:

GET /outlooks/convective?day=1&outlookType=categorical
GET /outlooks/convective/active?format=text&tz=CDT

Example JSON response:

{
  "data": {
    "locationId": "stl",
    "locationName": "St. Louis",
    "asOf": "2026-06-11T18:00:00Z",
    "issuedAt": "2026-06-11T17:00:00Z",
    "outlooks": [
      {
        "id": "spc-day1-cat-slight",
        "provider": "spc",
        "product": "convective",
        "day": 1,
        "outlookType": "categorical",
        "label": "SLGT",
        "labelText": "Slight Risk",
        "severityRank": 5,
        "validFrom": "2026-06-11T18:00:00Z",
        "validTo": "2026-06-12T12:00:00Z",
        "issuedAt": "2026-06-11T17:00:00Z",
        "expiresAt": "2026-06-12T12:00:00Z",
        "containsLocation": true,
        "geometry": {
          "type": "Polygon",
          "coordinates": [
            [
              [-91.0, 38.0],
              [-90.0, 38.0],
              [-90.0, 39.0],
              [-91.0, 38.0]
            ]
          ]
        }
      }
    ],
    "discussions": [
      {
        "day": 1,
        "headline": "Severe storms possible",
        "summary": "Scattered severe storms are possible.",
        "discussion": "SPC discussion text.",
        "updatedAt": "2026-06-11T17:30:00Z"
      }
    ]
  }
}

Text format uses the shared convective outlook template for both outlook routes and renders a no-data message when data is null.

Forecasts

GET /forecast/hourly
GET /forecast/hourly/today
GET /forecast/hourly/tomorrow
GET /forecast/narrative
GET /forecast/narrative/today
GET /forecast/narrative/tomorrow

Returns the latest hourly or narrative forecast run. /today and /tomorrow return a copy of the latest run with periods filtered by each period's startTime in the resolved timezone. If no periods match, data remains an object and periods is an empty array.

Query parameters: format, units, precision, tz / TZ.

Run data fields:

Field Type Notes
locationId, locationName string optional
issuedAt RFC3339 datetime required when data is not null
updatedAt RFC3339 datetime optional
product string hourly or narrative for implemented routes
latitude, longitude number optional
elevationMeters or elevationFeet number optional, depends on units
periods array ordered forecast periods

Metric period fields:

startTime, endTime, name, isDay, conditionCode, textDescription, temperatureC, temperatureCMin, temperatureCMax, dewpointC, relativeHumidityPercent, windDirectionDegrees, windSpeedKmh, windGustKmh, barometricPressurePa, visibilityMeters, apparentTemperatureC, cloudCoverPercent, probabilityOfPrecipitationPercent, precipitationAmountMm, snowfallDepthMm, and uvIndex.

US mode uses the same non-unit fields and replaces unit-bearing fields with temperatureF, temperatureFMin, temperatureFMax, dewpointF, windSpeedMph, windGustMph, barometricPressureInHg, visibilityMiles, apparentTemperatureF, precipitationAmountIn, snowfallDepthIn, and elevationFeet at run level.

startTime and endTime are required for each period. Other period fields are optional, including conditionCode; narrative forecasts may omit it.

Examples:

GET /forecast/hourly?units=us&precision=1&TZ=-5
GET /forecast/narrative/tomorrow?format=text&tz=Chicago

Forecast Discussions

GET /discussion
GET /discussion/key-messages
GET /discussion/short-term
GET /discussion/long-term

Returns the latest forecast discussion or a focused subresource.

Query parameters: format, units, tz / TZ.

Full discussion data fields:

Field Type Notes
officeId, officeName string optional
product string currently afd from weatherfeeder data
issuedAt RFC3339 datetime required when data is not null
updatedAt RFC3339 datetime optional
keyMessages array of strings optional
shortTerm, longTerm object optional section objects

Discussion section fields are qualifier, issuedAt, and text, all optional.

Subresources return the same metadata plus only their focused field: keyMessages, shortTerm, or longTerm.

Example:

GET /discussion/short-term?format=text&tz=CDT

Weather Stories

GET /weatherstories
GET /weatherstories/latest

/weatherstories returns the latest weather-story run and its ordered stories. /weatherstories/latest returns the latest individual story.

Query parameters: format, units, tz / TZ.

Run data fields:

Field Type Notes
officeId string optional
asOf RFC3339 datetime required when data is not null
stories array ordered story objects

Story fields:

Field Type Notes
officeId string optional
startTime, endTime, updatedAt RFC3339 datetime required when a story is present
title, description, altText, downloadUrl string optional
priority boolean required when a story is present
order integer required when a story is present

Examples:

GET /weatherstories?tz=America/Chicago
GET /weatherstories/latest?format=xml

Copyable Requests

See examples/requests.http for a compact set of requests covering the implemented endpoint families.