Hyperlocal weather for the Monte Sano plateau. The same JSON that powers this site — current conditions, multi-source forecasts, the pool, live radar & lightning. Public, read-only, no key.
*)
JSON only
UTC ISO-8601 timestamps
°F · inches · mm/hr (radar)
https://mswx.netCache-Control:
max-age (60–600s). Honor it; don't poll /now faster than
once a minute. There's no rate limit today, but tight polling loops are the
fastest way to earn one./api/v1/now. It's a single
round-trip with everything a home screen needs. Reach for the others only
when you need history, the multi-day strip, or the radar map./api/v1/now
Everything for a home screen in one call — plateau temp, valley, pool, sun, sky, rain chance + plateau rainfall today, thunder, live lightning, live rain-nowcast.
{
"as_of": "2026-05-25T19:00:00.000Z",
"mswx": { "temp_f": 74.2, "rh_pct": 61, "today_high_f": 76.6, "today_low_f": 66.2, "n_stations": 5 },
"valley": { "temp_f": 79.9, "station_id": "HSVWX", "label": "Downtown" },
"pool": { "temp_f": 75.9, "obs_time": "2026-05-25T18:58:00.000Z", "age_seconds": 120 },
"sun": { "sunrise_utc": "...", "sunset_utc": "...", "is_day": true },
"sky": { "cloud_pct": 81, "label": "mostly cloudy" },
"rain": { "today_pct": 88, "today_in": 0.42, "tomorrow_pct": 40 },
"thunder":{ "peak_pct": 35, "peak_at": "..." },
"lightning": { "strikes_nearby": false, "prob_30min": 5, "prob_60min": 7 },
"rain_now": { "currently_raining": true, "outcome": "keeps_raining",
"peak_rate_mm_hr": 10.0, "certainty_pct": 90,
"starts_iso": null, "ends_iso": null, "nowcast_age_seconds": 344 }
}
/api/v1/forecast/daily
?days=7 (1–10)
Per-day air high/low, pool high/low, cloud %, rain chance.
{ "days": [
{ "date": "2026-05-25", "air_high_f": 76.6, "air_low_f": 66.2,
"pool_high_f": 77.3, "pool_low_f": 73.9,
"cloud_pct": 81.4, "cloud_label": "mostly cloudy", "pop_pct": 88 }
] }
/api/v1/forecast/hourly
?hours=24 (1–168)
Hourly air temp, pool temp, cloud %, rain chance, UV index.
{ "hours": [
{ "t": "2026-05-25T19:00:00.000Z", "air_temp_f": 76.6,
"pool_temp_f": 75.9, "cloud_pct": 83, "pop_pct": 79, "uv_index": 4 }
] }
/api/v1/forecast/valley
?hours=48 (1–168)
Valley (Downtown) air-temp forecast — the 1000-ft-lower microclimate.
{ "hours": [ { "t": "2026-05-25T19:00:00.000Z", "air_temp_f": 79.9 } ] }
/api/v1/observed/hourly
?hours=24 (1–168)
Observed history: plateau, valley, pool, rainfall. Hour buckets centered HH:30; a 10-min live tail covers the past ~2h. rain_in is plateau-composite inches in the bucket; pool_temp_f null when no reading that hour.
{ "hours": [
{ "t": "2026-05-24T19:30:00.000Z", "air_temp_f": 70.1,
"valley_temp_f": 74.8, "pool_temp_f": null, "rain_in": 0.08 }
] }
/api/v1/alerts
Active NWS watches/warnings over us + nearby cells within ~50 mi. Each carries contains_us/distance_mi/bearing/local_area + priority; sorted by priority then closeness. banner=true marks the severe few the site shows as a top banner.
{ "as_of": "...", "count": 2, "banner_count": 1, "top_priority": 43, "alerts": [
{ "event": "Severe Thunderstorm Warning", "severity": "Severe", "headline": "...",
"area": "Limestone, AL; Madison, AL; Lincoln, TN", "onset": "...", "ends": "...",
"banner": true, "geometry": { "type": "Polygon", "coordinates": ["…"] },
"contains_us": false, "distance_mi": 5.3, "bearing": "NW",
"local_area": "~5 mi NW", "priority": 43 }
] }
/api/v1/radar/nowcast
Live rain nowcast: is it raining now, when does it start/stop, how sure are we, the 0–60 min advected rate, and hourly POP. rain_now matches /now.
{
"as_of": "...", "location": { "lat": 34.7335, "lon": -86.5236 },
"rain_now": { "currently_raining": true, "outcome": "keeps_raining",
"peak_rate_mm_hr": 10.0, "certainty_pct": 90 },
"motion": { "u_km_min": 0.31, "v_km_min": 0.12, "method": "pysteps" },
"freshness":{ "latest_obs_age_seconds": 120, "latest_nowcast_age_seconds": 344 },
"observed": [ { "t": "...", "rate_mm_hr": 6.4 } ],
"forecast": [ { "t": "...", "rate_mm_hr": 10.0 } ],
"pop_hourly":[ { "t": "...", "blend_pct": 70, "radar_blend_pct": 88, "nws_pct": 60 } ]
}
/api/v1/radar/map
Manifest to draw the animated radar map: bbox, absolute frame PNG URLs (kind=obs|fcst), lightning strikes, PMTiles basemap, neighborhood overlay.
{
"as_of": "...", "site": "KHTX", "bbox": [-87.55, 33.9, -85.5, 35.55],
"frames": [ { "url": "https://mswx.net/radar-frames/o_12.png",
"valid_time": "...", "kind": "obs" } ],
"frame_cadence_seconds": 300,
"lightning": null,
"basemap": { "pmtiles_url": "https://mswx.net/tiles/mswx-20260601.pmtiles",
"flavor": "dark", "glyphs": "...", "sprite": "...",
"center": [-86.5236, 34.7335], "min_zoom": 5, "max_zoom": 14 },
"overlays": { "neighborhood_geojson_url": "https://mswx.net/static/neighborhood.geojson" }
}
/api/v1/widget
Compact pre-shaped payload for a small home-screen widget (current + a few slots + daily strip + one insight line).
{ "as_of": "...", "sky": { "cloud_pct": 81, "label": "mostly cloudy" },
"slots": [...], "daily": [ { "date": "2026-05-25", "hi_f": 76.6, "lo_f": 66.2,
"icon": "☁", "pop_pct": 90 } ], "insight": { "emoji": "🌧", "text": "Rain 9p · 79%" } }
/plateau-api/openapi.jsoncurl -s https://mswx.net/api/v1/now | jq .
struct Now: Decodable {
struct MSWX: Decodable { let temp_f: Double?; let today_high_f: Double? }
struct RainNow: Decodable { let currently_raining: Bool; let outcome: String
let peak_rate_mm_hr: Double; let certainty_pct: Int? }
let as_of: String
let mswx: MSWX
let rain_now: RainNow?
}
let url = URL(string: "https://mswx.net/api/v1/now")!
let (data, _) = try await URLSession.shared.data(from: url)
let now = try JSONDecoder().decode(Now.self, from: data)
print(now.mswx.temp_f ?? 0, now.rain_now?.outcome ?? "—")