Atmostorm REST API
A single, consistent API for severe weather data from the NWS, SPC, IEM, NEXRAD, GOES, HRRR, USGS, and more. Everything is GeoJSON-first with spatial filters, real-time-ish update cadence, and free public access.
#Base URL
All endpoints are under /api/v1:
https://atmostorm.com/api/v1/
Responses are JSON by default, GeoJSON for spatial endpoints. Set ?format=geojson or ?format=json to override.
#Quickstart
Get all active NWS alerts in Oklahoma:
curl "https://atmostorm.com/api/v1/alerts?state=OK&active=true"
Observations within 50 km of Norman, OK:
curl "https://atmostorm.com/api/v1/observations?point=35.22,-97.44&radius=50km"
An HRRR point forecast with the next 12 hours:
curl "https://atmostorm.com/api/v1/models/hrrr/point?lat=35.22&lon=-97.44&hours=12"
#Authentication
The API is free and open. You can call every public endpoint anonymously. Passing an API key increases your rate limit and removes per-IP throttling.
Create a key from your account dashboard (requires a free login) and pass it in either a header or a query string:
X-API-Key: wx_abc123…
https://atmostorm.com/api/v1/alerts?api_key=wx_abc123…
#Rate limits
Limits are per-minute, rolling. You'll get a 429 Too Many Requests if you exceed them.
| Tier | Requests / min | How |
|---|---|---|
| Anonymous | 60 | Per IP |
| Authenticated | 600 | Per key |
Need more? Email hello@atmostorm.com and describe your use case — we'll work with public-good projects and operational users.
#Common query parameters
Most spatial endpoints share the same filter vocabulary. Mix and match freely — they compose as an AND.
bboxpointradiusstatewfostartendlatestlimitoffsetformatunits#Errors
Errors return a JSON body with a detail field:
{
"detail": "Invalid bbox: expected 4 numbers separated by commas"
}| Status | Meaning |
|---|---|
| 400 | Bad request — malformed params (e.g. invalid bbox) |
| 401 | Unauthenticated — required for /account and /admin |
| 403 | Forbidden — admin-only endpoint or wrong key scope |
| 404 | Not found — no such alert / sounding / etc. |
| 429 | Rate limit exceeded — back off and retry |
| 5xx | Server error — transient, retry with backoff |
#Response formats
Spatial endpoints return a GeoJSON FeatureCollection by default:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": { "type": "Polygon", "coordinates": [...] },
"properties": {
"id": 42,
"event": "Tornado Warning",
"severity": "Extreme",
"expires": "2026-04-19T22:15:00Z"
}
}
]
}For non-spatial data (e.g. HRRR point forecasts), you get plain JSON:
{
"lat": 35.22,
"lon": -97.44,
"elevation_m": 365.2,
"run": "2026-04-19T12:00:00Z",
"times": ["2026-04-19T13:00:00Z", ...],
"variables": { "t2m_c": [...], "cape_jkg": [...] }
}#Update cadence
Each source runs on its own cadence — we poll, normalize, and deduplicate server-side so you don't have to:
| Source | Refresh |
|---|---|
| NWS alerts | 30 s |
| NWS observations | 5 min |
| MRMS radar composite | 2 min |
| GOES-16 satellite | 5 min |
| SPC outlooks / watches | 15 min |
| HRRR model | hourly |
| Soundings | 12 h |
| USGS river gauges | 15 min |
#Terms & attribution
The data we aggregate is public domain or openly licensed. Please keep attribution on the data sources when you display any derived product.