Base URL: https://api.wxalerts.org
The model numbers themselves, for building your own products: one model at a point, only the forecast hours you ask for, only the fields you ask for. SI units, nothing derived, no narrative, no blending between models.
GET /v1/forecast/raw?model=nbm&lat=35.22&lon=-97.44&hours=0
GET /v1/forecast/raw?model=hrrr&lat=35.22&lon=-97.44&forecast_hours=0-6&fields=all
GET /v1/forecast/raw?model=rrfs&lat=35.22&lon=-97.44&forecast_hours=0-6&fields=column,surface_pressure
Available by arrangement. This endpoint answers only API keys that
WxAlerts has enabled for it; any other key gets 403 with the code
admin_key_required. To request access, email
support@wxalerts.org or use the
contact page and say what you are building. We enable it on a key
in your account.
Models
model |
what it is | grid | runs | reach |
|---|---|---|---|---|
nbm |
National Blend of Models: the calibrated blend NWS forecasts start from. Probabilities, amounts and sky | about 13 km, CONUS, Alaska, Hawaii, Puerto Rico, Guam | hourly | about 11 days |
hrrr |
High-Resolution Rapid Refresh: convection-allowing, 3 km. The full pressure-level column plus surface and severe weather fields | 3 km, CONUS | hourly | 18 hours; 48 at 00, 06, 12 and 18Z |
rrfs |
Rapid Refresh Forecast System, NOAA’s successor to the HRRR. The same column and fields as hrrr, on the same grid |
3 km, CONUS | every 3 hours (00, 03, … 21Z) | 18 hours; 84 at 00, 06, 12 and 18Z |
hrrr and rrfs answer in exactly the same shape, so a client written for
one reads the other by changing model=. Two differences to know: the
column’s top two levels are 75 and 50 hPa in HRRR but 70 and 50 hPa in RRFS
(read levels_hpa), and RRFS output arrives about 1 h 50 m after its cycle,
later than HRRR’s.
Asking for hours
Use at most one of these. With none, you get every hour available: NBM from the hour in progress onward, HRRR and RRFS the whole newest run.
| parameter | |
|---|---|
hours |
Offsets from the current hour, 0 being the hour in progress: 0, 0-6, 0,3,6, all |
forecast_hours |
hrrr and rrfs only: forecast hours of the newest run, so 0-6 is f00 to f06 |
valid_from, valid_to |
A window of valid times, ISO 8601, inclusive. A time without an offset is UTC |
Hours that do not exist are left out, never padded, so read what came back
rather than assuming a length. A run is served once its first two hours are
on disk; run.hours_available against run.hours_expected says how much of
it has arrived. NBM has no f000, so the hour in progress is usually its
forecast hour 1 or 2.
Asking for fields
fields is a comma separated list of names or groups. Default: everything
the model offers. An unknown name is a 422 that lists what is on offer.
NBM fields
Group: all.
| field | unit | |
|---|---|---|
temperature |
K | 2 m air temperature |
dewpoint |
K | 2 m dewpoint |
relative_humidity |
% | 2 m |
wind_speed, wind_gust |
m/s | 10 m |
wind_direction |
degrees | 10 m, the direction the wind blows from |
cloud_cover |
% | total sky cover |
high_cloud_cover |
% | |
cloud_layer_1_base to cloud_layer_3_base |
m | cloud layer bases above ground, CONUS, to about 36 hours |
cloud_layer_1_cover to cloud_layer_3_cover |
% | cover of each layer |
ceiling |
m | cloud ceiling above ground; 20,000 m or more means no ceiling |
visibility |
m | tops out near 16,000 m, which means unrestricted |
precip_amount |
kg/m² (= mm) | liquid equivalent over the window ending at the valid time |
precip_probability |
% | chance of more than 0.254 mm (0.01 in) in the window |
thunder_probability |
% | chance of a thunderstorm in the window |
severe_probability |
% | chance the Craven-Wiedenfeld severe parameter exceeds 65 (CONUS) |
rain_probability, snow_probability, freezing_rain_probability, ice_pellet_probability |
% | chance the precipitation is of that type (CONUS and Alaska). Independent, so they need not add up to 100 |
snowfall_amount |
m | snowfall over the window (CONUS and Alaska) |
ice_accumulation |
kg/m² (= mm) | flat ice from freezing rain over the window (CONUS and Alaska) |
snow_liquid_ratio |
ratio | snow to liquid (CONUS and Alaska) |
snow_depth |
m | to about 42 hours (CONUS and Alaska) |
cape |
J/kg | surface based |
Accumulation windows. NBM publishes these accumulated fields over
windows that grow with lead time, and each comes with a companion telling you
which window you got: precip_amount_window_hours,
precip_probability_window_hours, thunder_probability_window_hours,
snowfall_amount_window_hours, ice_accumulation_window_hours. Precipitation
probability, snow and ice are 1-hour in the hourly range and 6-hour past
about 100 hours; thunder goes from 1 to 3 to 6 hours; precipitation amount
stays 1-hour. Read the window before adding hours together or comparing them.
Each NBM hour carries its own cycle, and it can differ between hours: every
valid time comes from the newest NBM run that reached it.
HRRR and RRFS fields
Groups: all, surface (every single-level field), column (every
pressure-level field).
Single-level, in each hour’s values:
| field | unit | |
|---|---|---|
temperature_2m, dewpoint_2m |
K | |
surface_pressure |
hPa | |
mslp |
hPa | mean sea level pressure. HRRR’s MAPS reduction, RRFS’s Eta reduction, so the two are not interchangeable |
u_10m, v_10m, u_80m, v_80m |
m/s | earth relative: u toward east, v toward north |
wind_speed_10m, wind_direction_10m, wind_speed_80m, wind_direction_80m |
m/s, degrees | direction the wind blows from |
wind_gust |
m/s | surface |
pbl_height |
m | boundary layer height above ground |
visibility |
m | surface; up to about 90 km |
reflectivity |
dBZ | composite (the column maximum) |
sbcape, sbcin |
J/kg | surface based |
mlcape, mlcin |
J/kg | 90-0 hPa mixed layer |
mucape, mucin |
J/kg | 255-0 hPa most unstable parcel |
srh_0_1km, srh_0_3km |
m²/s² | storm relative helicity |
updraft_helicity_2_5km |
m²/s² | 2-5 km, maximum over the hour ending at the valid time; null at f00 |
precipitable_water |
kg/m² (= mm) |
On every pressure level, in each hour’s levels:
| field | unit | |
|---|---|---|
height |
m | geopotential height |
temperature, dewpoint |
K | |
u, v |
m/s | earth relative |
wind_speed, wind_direction |
m/s, degrees | direction the wind blows from |
omega |
Pa/s | vertical motion, positive downward |
vertical_velocity |
m/s | vertical motion, positive upward |
The column is 39 levels, bottom up: 1000 to 100 hPa every 25, then 75 and 50
(HRRR) or 70 and 50 (RRFS). Every hour lists every level, so index k is
always the same pressure; a level below the ground at that hour has
below_ground: true and every value null.
HRRR publishes omega and RRFS publishes vertical velocity. Both fields are
offered for both models: the one the model publishes is passed through, and
the other is derived from it (omega = -ρ g w, with ρ from the level’s pressure
and virtual temperature). units says which is which.
What a response holds
An RRFS call for f06 with a few fields, levels trimmed to two:
{
"server_time": "2026-11-12T01:11:35Z",
"model": "rrfs",
"location": { "lat": 35.22, "lon": -97.44 },
"grid_point": { "i": 901, "j": 407, "lat": 35.20763, "lon": -97.43979, "resolution_km": 3.0 },
"run": { "cycle": "2026-11-11T21:00:00Z", "hours_available": 13, "hours_expected": 19, "complete": false },
"fields": ["temperature_2m", "mucape", "mslp", "temperature", "omega", "vertical_velocity"],
"units": {
"temperature_2m": "K",
"mucape": "J/kg, 255-0 hPa most unstable parcel",
"mslp": "hPa, HRRR's MAPS reduction (MSLMA), RRFS's Eta reduction (MSLET)",
"temperature": "K",
"omega": "Pa/s, positive downward, derived hydrostatically from RRFS's w and the level's virtual temperature",
"vertical_velocity": "m/s, positive upward, as RRFS publishes it",
"pressure": "hPa"
},
"levels_hpa": [1000.0, 975.0, 950.0, "...", 100.0, 70.0, 50.0],
"hours": [
{
"valid_time": "2026-11-12T03:00:00Z",
"forecast_hour": 6,
"cycle": "2026-11-11T21:00:00Z",
"values": { "temperature_2m": 287.3, "mucape": 0.0, "mslp": 1018.26 },
"levels": [
{ "pressure": 1000.0, "below_ground": true, "temperature": null, "omega": null, "vertical_velocity": null },
"...",
{ "pressure": 500.0, "below_ground": false, "temperature": 258.8, "omega": 0.198, "vertical_velocity": -0.03 },
"..."
]
}
]
}
An NBM response has the same frame without run, levels_hpa or levels,
and its grid_point names the NBM cell (cell_id, domain). Only the hours
and fields you asked for appear. A field that is present and null means the
model has no value there. unavailable_fields lists any you asked for that
the model does not publish at that point, such as NBM precipitation type in
Hawaii.
Calling it
Send your key in the X-API-Key header (or Authorization: Bearer). A key in
the URL is refused with 400 key_in_query, because URLs end up in logs and
browser history. Browsers block calls from other websites (CORS allows only
wxalerts.org), so call it from a server, script or app.
curl -s -H "X-API-Key: $WXALERTS_KEY" \
'https://api.wxalerts.org/v1/forecast/raw?model=hrrr&lat=35.22&lon=-97.44&forecast_hours=0-6&fields=all'
Limits
5 calls in any 60 seconds per account, shared by every key on the account
and by this endpoint and point soundings together.
Every call that passes the key check counts, including one that answers 404
or 503. Responses carry RateLimit-Limit, RateLimit-Remaining and
RateLimit-Reset; past the limit you get 429 with a Retry-After. One call
can carry a whole run, so ask for the hours and fields you need in one call
rather than one call each.
Errors
| status | means |
|---|---|
400 |
the key was sent in the URL |
401 |
no key, or an unknown, revoked or expired one |
403 |
the key is not enabled for this endpoint (admin_key_required), or lacks weather:read |
404 |
the point is outside the model’s grid |
422 |
a parameter that cannot be satisfied: an unknown field, two ways of choosing hours, forecast_hours with nbm. The message says which |
429 |
over the limit; wait Retry-After seconds |
503 |
the model has no run available yet |

