Document convective outlook endpoints

This commit is contained in:
2026-06-11 15:46:00 +00:00
parent e897ae52df
commit 993621e3b3
7 changed files with 228 additions and 20 deletions

View File

@@ -63,16 +63,17 @@ Unknown query parameters are rejected with `400 Bad Request`.
| `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 |
| `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.
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, and weather stories.
`precision` is rejected on alerts, discussions, weather stories, and outlooks.
Timezone selectors accepted by `tz` / `TZ`:
@@ -220,6 +221,151 @@ Example:
GET /alerts/active?format=text
```
### Convective Outlooks
```http
GET /outlooks/convective
GET /outlooks/convective/active
GET /outlooks/convective/location
```
Returns the latest SPC convective outlook run reconstructed from
weatherfeeder-owned Postgres tables.
Route behavior:
- `/outlooks/convective` returns the latest run with all stored 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`.
- `/outlooks/convective/location` adds the same active-time filter and
`containsLocation=true`.
When no latest run exists, `data` is null. When a run exists but filters match
no outlooks, `data` remains an object and `outlooks` is an empty array.
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` |
| `containsLocation` | `/outlooks/convective`, `/outlooks/convective/active` | boolean |
`outlookType` values are normalized case-insensitively. `containsLocation` is
rejected on `/outlooks/convective/location` because that route always applies
`containsLocation=true`. `precision` 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 |
Outlook fields:
| Field | Type | Notes |
| --- | --- | --- |
| `id`, `provider`, `product`, `outlookType`, `label` | string | required when an outlook is present |
| `day` | integer | SPC outlook day |
| `labelText`, `forecaster`, `headline`, `summary`, `discussion` | 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 |
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`. Active filtering
compares instants and is not changed by the presentation timezone.
Examples:
```http
GET /outlooks/convective?day=1&outlookType=categorical
GET /outlooks/convective/location?format=text&tz=CDT
```
Example JSON response:
```json
{
"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]
]
]
}
}
]
}
}
```
Example location-filtered JSON response:
```json
{
"data": {
"locationId": "stl",
"asOf": "2026-06-11T18:00:00Z",
"outlooks": [
{
"id": "spc-day1-tor-2pct",
"provider": "spc",
"product": "convective",
"day": 1,
"outlookType": "tornado",
"label": "2%",
"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": "Point",
"coordinates": [-90.2, 38.6]
}
}
]
}
}
```
Text format uses the shared convective outlook template for all three outlook
routes and renders a no-data message when `data` is null.
### Forecasts
```http