TorCAST API
The TorCAST API gives programmatic access to the Tornado Potential Index (TPI) engine — the same data powering the live map. Use it to pull real-time TPI values for any US point, fetch pre-computed regional grids, query atmospheric sounding data, or integrate live severe-weather intelligence into your own application.
Base URL
https://torcast.pro
All endpoints are relative to the base URL above. HTTPS is required — plain HTTP requests will be redirected.
Authentication
Every API request must include your API key. Two methods are supported — use whichever fits your stack.
Method 1 — X-API-Key Header RECOMMENDED
Pass the key in the X-API-Key request header. Works with GET and POST.
curl -H "X-API-Key: YOUR_API_KEY" \
"https://torcast.pro/api/tpi/live?lat=37.69&lon=-97.33"
import requests
API_KEY = "YOUR_API_KEY"
BASE = "https://torcast.pro"
r = requests.get(
f"{BASE}/api/tpi/live",
params={"lat": 37.69, "lon": -97.33},
headers={"X-API-Key": API_KEY},
)
data = r.json()
print(data["results"][0]["live_tpi"])
const API_KEY = "YOUR_API_KEY";
const BASE = "https://torcast.pro";
const res = await fetch(`${BASE}/api/tpi/live?lat=37.69&lon=-97.33`, {
headers: { "X-API-Key": API_KEY },
});
const data = await res.json();
console.log(data.results[0].live_tpi);
Method 2 — Query Parameter
Append ?api_key=YOUR_API_KEY to any endpoint URL. Useful for quick browser tests or GET-only scripts.
https://torcast.pro/api/tpi/snapshot?api_key=YOUR_API_KEY
Finding Your Key
Log into torcast.pro/dashboard and open the Developer API panel in the left sidebar. Your key is shown there along with today's usage. An admin can also provision or revoke keys for your account from the Admin Suite.
Rate Limits
Limits are enforced per API key on a 24-hour rolling calendar day (UTC midnight reset).
| Plan | Daily Limit | Notes |
|---|---|---|
| FREE | 50,000 req / day | Default plan for all new accounts |
| SILVER | 200,000 req / day | Available via subscription upgrade |
| GOLD | 500,000 req / day | High-volume / enterprise use |
Rate Limit Headers
Every API response includes these headers so you can track consumption in real time:
| Header | Description |
|---|---|
| X-RateLimit-Limit | Your plan's daily request ceiling |
| X-RateLimit-Used | Requests consumed so far today (UTC) |
| X-RateLimit-Remaining | Requests left before the limit is hit |
| X-RateLimit-Plan | Your current plan: free, silver, or gold |
When the limit is exceeded, the API returns HTTP 429 with a JSON body explaining the limit and when it resets (midnight UTC).
The TPI Scale
The Tornado Potential Index runs from 0.0 to 10.0. It represents the maximum potential severity of storms that could form in the current environment — not the probability that storms will form.
Labels like live_label and predicted_label_3h in the response contain a human-readable string corresponding to these ranges, e.g. "Moderate Severe".
TPIResult — Field Reference
Most point-based endpoints return one or more TPIResult objects inside a results array. Every field below is optional — it may be null if the data source was unavailable when the request was processed.
Identity
| Field | Type | Description | Example |
|---|---|---|---|
| id | string | Unique point identifier derived from lat/lon and mode | "live_37.690_-97.330" |
| lat | float | Latitude of the queried point | 37.69 |
| lon | float | Longitude of the queried point (negative = west) | -97.33 |
| name | string | null | Human-readable location name when available | "Wichita, KS" |
| state | string | null | Two-letter US state code for the point | "KS" |
Core TPI Values
| Field | Type | Description | Example |
|---|---|---|---|
| live_tpi | float | null | Current observed TPI. Derived from live NWS alerts, surface observations, storm reports, and boundary detection. Updates as new observations arrive. | 6.4 |
| predicted_tpi_1h | float | null | Forecast TPI for the next 1 hour using HRRR (3 km convection-allowing model) | 5.8 |
| predicted_tpi_3h | float | null | Forecast TPI 3 hours out — HRRR. Most commonly used for near-term planning. | 7.1 |
| predicted_tpi_6h | float | null | Forecast TPI 6 hours out — HRRR | 4.3 |
| predicted_tpi_12h | float | null | Day 1 morning outlook — GFS 0.25°. Lower resolution; environment-only (no convective-scale fields). | 3.0 |
| predicted_tpi_24h | float | null | Day 1 full outlook — GFS | 2.5 |
| predicted_tpi_48h | float | null | Day 2 outlook — GFS. Treat as a broad environmental signal only. | 1.8 |
| predicted_tpi_72h | float | null | Day 3 outlook — GFS | 1.2 |
Trend & Confidence
| Field | Type | Description | Values |
|---|---|---|---|
| delta_tpi_3h | float | null | Change in TPI: predicted_3h minus live_tpi. Positive = conditions are worsening near-term. | +0.7 |
| delta_tpi_24h | float | null | Change from live to 24h forecast — useful for day-scale trend detection | -1.2 |
| trend | string | null | Human-readable near-term trajectory based on delta_tpi_3h |
"Rising Fast" ≥ +2.0 "Rising" +0.75 to +2.0 "Steady" ±0.75 "Falling" −0.75 to −2.0 "Falling Fast" ≤ −2.0 |
| confidence | string | null | Overall data quality confidence for this point's score | "High" | "Medium" | "Low" |
Labels
| Field | Type | Description |
|---|---|---|
| live_label | string | null | Text label for live_tpi, e.g. "Moderate Severe", "High Tornado Potential" |
| predicted_label_1h | string | null | Text label for 1h forecast TPI |
| predicted_label_3h | string | null | Text label for 3h forecast TPI |
| predicted_label_6h | string | null | Text label for 6h forecast TPI |
| predicted_label_24h / 48h / 72h | string | null | Text labels for extended GFS forecast windows |
ML Correction
| Field | Type | Description |
|---|---|---|
| ml_tpi | float | null | ML-corrected (HGBT blended) TPI value. Present only when the ML model is trained and active. Typically 25% ML / 75% rule-based blend. Null when model is inactive — use live_tpi. |
| ml_correction | float | How much the ML engine shifted the rule-based score (+/−). Zero when model is inactive. |
Watch Override
| Field | Type | Description |
|---|---|---|
| watch_floor_applied | boolean | True when an active SPC Tornado or Severe Thunderstorm Watch polygon covers this point. When true, a minimum TPI floor is enforced and ML downward corrections are overridden. |
| active_watch_type | string | Type of active watch, e.g. "Tornado Watch", "Severe Thunderstorm Watch". Empty string if no watch is active. |
Metadata
| Field | Type | Description |
|---|---|---|
| suppressed | boolean | True when the rule engine suppressed the TPI score based on reality checks (e.g. very high CIN with no forcing) |
| suppress_reason | string | Human-readable explanation of why the score was suppressed, if applicable |
| partial_data | boolean | True when one or more upstream data sources were unavailable. The score is still valid but may be less accurate. |
| stale_sources | string[] | List of data source names that were stale or unavailable for this computation |
| computed_at | ISO 8601 datetime | UTC timestamp when this specific result was calculated |
| forecast_model_short | string | Model used for 1h/3h/6h forecasts — always "hrrr" |
| forecast_model_extended | string | Model used for 12h–72h forecasts — always "gfs" |
Endpoints
Returns the static configuration that drives the TPI engine: category thresholds, label strings, scoring component weights, all upstream data source descriptions, cache TTLs, and active feature flags. Call this once on startup to build your own legend or validate your TPI range rendering.
This endpoint does not require authentication.
Example Request
curl "https://torcast.pro/api/meta"
import requests
data = requests.get("https://torcast.pro/api/meta").json()
print(data["labels"])
Example Response
{
"service": "TorCAST TPI Engine",
"version": "2.0.0",
"scoring_ranges": { "min": 0.0, "max": 10.0, "decimal_places": 1 },
"labels": {
"0.0-0.5": "No Severe Threat",
"0.5-1.5": "Marginal Severe",
"1.5-2.5": "Slight Severe",
"2.5-3.5": "Enhanced Severe",
"3.5-4.5": "Moderate Severe",
"4.5-5.5": "High Tornado Potential",
"5.5-10.0": "Extreme Tornado Potential"
},
"confidence_levels": ["Low", "Medium", "High"],
"sources": [ ... ]
}
Returns the most recently computed TPI grid as a GeoJSON FeatureCollection. This is the fastest endpoint (~5–50 ms) because it reads a file that the background worker pre-computes every 5 minutes — no upstream GRIB or NWS calls happen on the request path.
Each Feature's properties object contains a full TPIResult including live TPI, all forecast windows, delta, trend, confidence, labels, component scores, and source status for that grid point.
status in the response body and retry after a few seconds.No query parameters — the snapshot covers the full pre-configured region.
Example Request
curl -H "X-API-Key: YOUR_API_KEY" \
"https://torcast.pro/api/tpi/snapshot"
import requests
r = requests.get(
"https://torcast.pro/api/tpi/snapshot",
headers={"X-API-Key": "YOUR_API_KEY"},
)
geojson = r.json()
# Iterate over all grid points
for feature in geojson["features"]:
props = feature["properties"]
lat = feature["geometry"]["coordinates"][1]
lon = feature["geometry"]["coordinates"][0]
print(f"{lat:.2f},{lon:.2f} TPI={props.get('live_tpi')}")
const r = await fetch("https://torcast.pro/api/tpi/snapshot", {
headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await r.json();
for (const feature of data.features) {
const tpi = feature.properties.live_tpi;
const [lon, lat] = feature.geometry.coordinates;
console.log(lat, lon, tpi);
}
Example Response
{
"type": "FeatureCollection",
"meta": {
"status": "ok",
"computed_at": "2025-05-11T18:42:00Z",
"point_count": 1248,
"snapshot_age_seconds": 187.4
},
"features": [
{
"type": "Feature",
"geometry": { "type": "Point", "coordinates": [-97.33, 37.69] },
"properties": {
"id": "snap_37.690_-97.330",
"lat": 37.69,
"lon": -97.33,
"live_tpi": 6.4,
"predicted_tpi_1h": 6.8,
"predicted_tpi_3h": 7.2,
"predicted_tpi_6h": 5.1,
"predicted_tpi_24h": 2.3,
"delta_tpi_3h": 0.8,
"trend": "Rising",
"confidence": "High",
"live_label": "High Tornado Potential",
"predicted_label_3h": "Extreme Tornado Potential",
"partial_data": false
}
}
]
}
Meta Fields
| Field | Description |
|---|---|
| meta.computed_at | UTC timestamp when the worker last regenerated the snapshot |
| meta.point_count | Total number of grid points in this snapshot |
| meta.snapshot_age_seconds | How many seconds old the snapshot is at the time of your request. Values over 900 s (15 min) may indicate the worker is down. |
| meta.warning | Present only when the snapshot is stale — describes the age and suggests checking worker status |
Computes live TPI on-demand for a specific latitude/longitude using current NWS alerts, surface observations, and local storm reports. Also returns HRRR short-range forecast TPI (1h, 3h, 6h). Response time is typically 1–4 seconds due to upstream data fetching.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| lat | float | 32.84 (GA) | Latitude of the query point. US coverage only. |
| lon | float | -83.63 (GA) | Longitude of the query point (negative = west). |
| state | string | null | Two-letter US state code for boundary context, e.g. KS. Used to refine dryline / boundary detection. Optional. |
| format | string | "json" | json (default) returns a TPIResponse object. geojson wraps the result in a GeoJSON Feature. |
Example Request
# Wichita, KS
curl -H "X-API-Key: YOUR_API_KEY" \
"https://torcast.pro/api/tpi/live?lat=37.69&lon=-97.33&state=KS"
import requests
r = requests.get(
"https://torcast.pro/api/tpi/live",
params={"lat": 37.69, "lon": -97.33, "state": "KS"},
headers={"X-API-Key": "YOUR_API_KEY"},
)
result = r.json()["results"][0]
print(f"Live TPI: {result['live_tpi']}")
print(f"3h Forecast: {result['predicted_tpi_3h']}")
print(f"Trend: {result['trend']}")
print(f"Confidence: {result['confidence']}")
const r = await fetch(
"https://torcast.pro/api/tpi/live?lat=37.69&lon=-97.33&state=KS",
{ headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const { results } = await r.json();
const pt = results[0];
console.log("Live TPI:", pt.live_tpi);
console.log("3h Forecast:", pt.predicted_tpi_3h);
console.log("Trend:", pt.trend);
Example Response
{
"results": [
{
"id": "live_37.690_-97.330",
"lat": 37.69,
"lon": -97.33,
"state": "KS",
"live_tpi": 6.4,
"predicted_tpi_1h": 6.8,
"predicted_tpi_3h": 7.2,
"predicted_tpi_6h": 5.1,
"delta_tpi_3h": 0.8,
"trend": "Rising",
"confidence": "High",
"live_label": "High Tornado Potential",
"predicted_label_3h": "Extreme Tornado Potential",
"ml_tpi": 6.6,
"ml_correction": 0.2,
"watch_floor_applied": false,
"active_watch_type": "",
"suppressed": false,
"partial_data": false,
"computed_at": "2025-05-11T18:44:12Z"
}
],
"count": 1,
"computed_at": "2025-05-11T18:44:12Z",
"mode": "point",
"partial_data": false
}
Returns forecast TPI for a single point at a specific forecast hour. Short-range uses HRRR (1h, 3h, 6h). Extended range uses GFS Day 1–3 (12h, 24h, 48h, 72h). The requested hour is snapped to the nearest supported value.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| lat | float | 32.84 | Latitude |
| lon | float | -83.63 | Longitude |
| forecast_hour | int (1–72) | 3 | Target forecast hour. Snapped to nearest supported: 1, 3, 6 (HRRR) or 12, 24, 48, 72 (GFS). Example: passing 4 uses the 3h HRRR window. |
| state | string | null | Two-letter state code (optional) |
Example Request
# 24-hour (Day 1) GFS forecast for Oklahoma City
curl -H "X-API-Key: YOUR_API_KEY" \
"https://torcast.pro/api/tpi/predicted?lat=35.47&lon=-97.52&forecast_hour=24&state=OK"
r = requests.get(
"https://torcast.pro/api/tpi/predicted",
params={"lat": 35.47, "lon": -97.52, "forecast_hour": 24, "state": "OK"},
headers={"X-API-Key": "YOUR_API_KEY"},
)
print(r.json()["results"][0]["predicted_tpi_24h"])
The most complete single-point endpoint. Returns live TPI, all HRRR short-range forecasts (1h/3h/6h), delta, trend, confidence, labels, component scores, and source metadata in one response. Use this when you need the full picture for a location. Accepts format=geojson to return a GeoJSON Feature directly.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| lat | float | 32.84 | Latitude |
| lon | float | -83.63 | Longitude |
| state | string | null | Two-letter state code |
| format | string | "json" | json or geojson |
Example — GeoJSON output
curl -H "X-API-Key: YOUR_API_KEY" \
"https://torcast.pro/api/tpi/combined?lat=36.15&lon=-95.99&state=OK&format=geojson"
Computes live and forecast TPI for every grid point within a bounding box. Returns a GridResponse (JSON array) or GeoJSON FeatureCollection. Each point is lighter than a full TPIResult — it includes TPI values, delta, trend, confidence, and labels but omits detailed component scores.
spacing ≥ 0.25 for broad regional queries. For regional coverage consider /api/tpi/snapshot instead — it is instantaneous.Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| bbox | string | Georgia bbox | Bounding box as min_lat,min_lon,max_lat,max_lon. Example: 33.5,-97.5,37.0,-94.0 covers southern Kansas and northern Oklahoma. |
| spacing | float (0–5) | config default | Grid spacing in degrees. Smaller = more points. Use 0.5 for a fast regional pass, 0.1 for detailed city-scale analysis. |
| state | string | null | State context for boundary detection |
| format | string | "json" | json or geojson |
Example Request
# Southern Kansas / northern Oklahoma at 0.5° spacing, GeoJSON output
curl -H "X-API-Key: YOUR_API_KEY" \
"https://torcast.pro/api/tpi/grid?bbox=33.5,-97.5,37.0,-94.0&spacing=0.5&format=geojson"
r = requests.get(
"https://torcast.pro/api/tpi/grid",
params={
"bbox": "33.5,-97.5,37.0,-94.0",
"spacing": 0.5,
"format": "geojson",
},
headers={"X-API-Key": "YOUR_API_KEY"},
timeout=60,
)
geojson = r.json()
print(f"{geojson['count']} points returned")
# Find highest TPI point
best = max(
geojson["features"],
key=lambda f: f["properties"].get("live_tpi") or 0
)
print(f"Max TPI: {best['properties']['live_tpi']} at {best['geometry']['coordinates']}")
Returns GeoJSON polygon contours for the current snapshot, aligned to SPC convective outlook categories. Each polygon represents an area where TPI is at or above a given threshold. Useful for rendering risk outlines on a map.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| field | string | "live_tpi" | Which TPI field to contour. Options: live_tpi, predicted_tpi_1h, predicted_tpi_3h, predicted_tpi_6h, predicted_tpi_24h |
| min_tpi | float | 0.5 | Minimum TPI to include in contours. Increase to filter out low-end areas. |
Contour Levels
| Level | Category | Color | Meaning |
|---|---|---|---|
| 0.5+ | MRGL | #66FF66 | Marginal risk |
| 1.5+ | SLGT | #FFFF00 | Slight risk |
| 2.5+ | ENH | #FFA500 | Enhanced risk |
| 3.5+ | MDT | #FF0000 | Moderate risk |
| 4.5+ | HIGH | #FF00FF | High risk |
| 5.5+ | EXTRM | #FFFFFF | Extreme risk |
Returns the full category definitions including name, TPI range, hex color, and display label. Use this to build a consistent legend in your application. Does not require authentication.
Example Response
{
"categories": [
{ "name": "NONE", "min": 0.0, "max": 0.5, "color": "#808080", "label": "No Risk" },
{ "name": "MRGL", "min": 0.5, "max": 1.5, "color": "#66FF66", "label": "Marginal" },
{ "name": "SLGT", "min": 1.5, "max": 2.5, "color": "#FFFF00", "label": "Slight" },
{ "name": "ENH", "min": 2.5, "max": 3.5, "color": "#FFA500", "label": "Enhanced" },
{ "name": "MDT", "min": 3.5, "max": 4.5, "color": "#FF0000", "label": "Moderate" },
{ "name": "HIGH", "min": 4.5, "max": 5.5, "color": "#FF00FF", "label": "High" },
{ "name": "EXTRM", "min": 5.5, "max": 10.0, "color": "#FFFFFF", "label": "Extreme" }
],
"description": "TPI categories aligned with SPC convective outlook categories",
"version": "2.0"
}
Monitor Endpoints
Monitor endpoints return pre-computed output from the ensemble worker (worker_ensemble.py). They are near-instantaneous reads from disk — no upstream fetching on the request path. All return status: "pending" if the worker has not yet produced output.
Returns active convective initiation (CI) windows detected by the ensemble worker. Each window represents a geographic area where GLM lightning jump signals and ABI cloud-top roughness are both flagging, indicating storm development in progress or imminent.
Example Request
curl -H "X-API-Key: YOUR_API_KEY" "https://torcast.pro/api/v2/ci"
Key Response Fields
| Field | Type | Description |
|---|---|---|
| windows | array | List of active CI windows. Empty array when no initiation is detected. |
| windows[].lat / lon | float | Center point of the CI window |
| windows[].severity | string | Overall CI severity: "Low", "Moderate", "High", "Extreme" |
| windows[].glm_jump | boolean | True when a GOES-16 GLM lightning jump (2σ threshold) is active at this location |
| windows[].abi_updraft | boolean | True when GOES-16 ABI Band 14 cloud-top roughness exceeds the updraft detection threshold |
| windows[].tpi | float | TPI value from the nearest snapshot grid point |
| overall_severity | string | Highest severity across all active windows |
Returns the current GOES-16 Geostationary Lightning Mapper (GLM) lightning jump status. A lightning jump (2σ above the 10-minute rolling mean) is a strong indicator of rapid storm intensification.
Key Response Fields
| Field | Description |
|---|---|
| lightning_jump_active | Boolean — true when a 2σ lightning jump is currently detected |
| flash_rate_per_min | Current GLM flash rate (flashes per minute) |
| rolling_mean_per_min | 10-minute rolling mean flash rate — the baseline the jump threshold is calculated from |
| sigma_2_threshold | The computed 2σ threshold; jump is flagged when flash_rate exceeds this value |
| retrieved_utc | UTC timestamp of the last successful GLM data fetch |
Returns GOES-16 ABI Band 14 cloud-top roughness analysis. High Laplacian variance in the infrared channel indicates an actively developing updraft — a precursor to severe weather.
Key Response Fields
| Field | Description |
|---|---|
| developing_updraft_detected | Boolean — true when max IR roughness exceeds the updraft detection threshold |
| max_laplacian_variance | Maximum IR roughness value across the analysis domain — higher = more turbulent cloud tops |
| high_roughness_zones | Array of lat/lon locations where cloud-top roughness is above threshold |
| retrieved_utc | UTC timestamp of the last ABI data fetch |
Returns the latest weighted ensemble TPI blend. The ensemble combines multiple model runs (HRRR + GFS cycles) with spatial confidence weighting. The output includes a divergence penalty flag when model runs disagree significantly.
Key Response Fields
| Field | Description |
|---|---|
| max_ensemble_tpi | Highest TPI value in the current ensemble blend — indicates peak potential anywhere in the domain |
| points_blended | Number of grid points included in the ensemble calculation |
| model_divergence_penalty | Boolean — true when HRRR and GFS disagree enough to apply a 15% confidence reduction |
| generated_utc | UTC timestamp when the ensemble was last computed |
Proxies crowd-sourced weather reports from mping.ou.edu. Returns recent storm reports submitted by the public via the mPing mobile app, filtered by category and time window.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| hours | int (1–24) | 2 | How many hours back to fetch reports. Maximum 24. |
| category | string | null (all) | Filter to a specific report type: Hail, Tornado, Wind Damage, Rain, Snow, Ice. Omit for all categories. |
Example Request
# Tornado reports from the last 6 hours
curl -H "X-API-Key: YOUR_API_KEY" \
"https://torcast.pro/api/mping/reports?category=Tornado&hours=6"
Response Fields (per report)
| Field | Description |
|---|---|
| id | mPing report ID |
| obtime | ISO 8601 UTC observation time |
| category | Report category (Hail, Tornado, Wind Damage, etc.) |
| description | User-provided description of the event |
| lat / lon | Coordinates of the report |
Fetches a live atmospheric sounding profile from the nearest BUFKIT station and derives key severe-weather parameters using MetPy. Useful for building skew-T diagrams or assessing storm mode potential.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| lat | float | REQUIRED | Latitude of the query point |
| lon | float | REQUIRED | Longitude |
| model | string | optional | Data source: hrrr (default), rap, nam, namnest, gfs, sref, hiresw |
| fhour | int (0–72) | optional | Forecast hour (default 0 = analysis) |
| include_profile | boolean | optional | Set to true to include full vertical profile arrays (pressure, height, temperature, dewpoint, u/v wind) for skew-T rendering. Increases response size significantly. |
Example Request
curl -H "X-API-Key: YOUR_API_KEY" \
"https://torcast.pro/api/sounding/nearest?lat=35.47&lon=-97.52&model=hrrr&fhour=0"
r = requests.get(
"https://torcast.pro/api/sounding/nearest",
params={"lat": 35.47, "lon": -97.52, "model": "hrrr", "fhour": 0},
headers={"X-API-Key": "YOUR_API_KEY"},
)
snd = r.json()
params = snd["sounding_params"]
print(f"Station: {snd['nearest_station']}")
print(f"CAPE: {params.get('sbcape_jkg')} J/kg")
print(f"CIN: {params.get('sbcin_jkg')} J/kg")
print(f"SRH 0-1: {params.get('srh_0_1km')} m²/s²")
print(f"0-6 Shear:{params.get('shear_0_6km_ms')} m/s")
print(f"STP: {params.get('stp')}")
Sounding Parameters
| Field | Description |
|---|---|
| nearest_station | BUFKIT station ID of the closest sounding site to your query point |
| sounding_params.sbcape_jkg | Surface-based CAPE (J/kg) — energy available for thunderstorm development. Values >1000 indicate significant instability. |
| sounding_params.sbcin_jkg | Surface-based CIN (J/kg) — the "cap" inhibiting storm initiation. Values <−50 indicate a strong cap; <−200 is effectively a lid. |
| sounding_params.srh_0_1km | Storm-Relative Helicity 0–1 km (m²/s²) — low-level wind shear available for tornado production. Values >150 are noteworthy; >300 are significant. |
| sounding_params.srh_0_3km | Storm-Relative Helicity 0–3 km (m²/s²) — mid-level rotation potential |
| sounding_params.shear_0_6km_ms | 0–6 km bulk wind shear (m/s) — supercell organization potential. >15 m/s supports supercells; >20 m/s is strongly supportive. |
| sounding_params.lcl_height_m | Lifted Condensation Level height (m AGL) — cloud base. Lower LCL (<1000 m) favors tornado potential. |
| sounding_params.stp | Significant Tornado Parameter — composite index combining CAPE, SRH, shear, LCL height. >1.0 indicates significant tornado potential. |
| sounding_params.scp | Supercell Composite Parameter — broader supercell potential index. >1.0 supports supercell development. |
| viewer_urls.iem | Direct URL to the Iowa Environmental Mesonet sounding viewer for this station |
| viewer_urls.rucsoundings | Direct URL to the RUC Soundings viewer for this location |
| profile | Full vertical profile arrays (only present when include_profile=true): p (hPa), z (m), T (°C), Td (°C), u/v (m/s) |
Error Codes
| HTTP Status | Error Code | Meaning |
|---|---|---|
| 401 | invalid_api_key |
The provided API key was not found. Check for typos or regenerate your key from the dashboard. |
| 401 | Not authenticated |
No API key was provided and no valid session token was found in the request. |
| 403 | api_key_disabled |
Your API key exists but has been disabled by an administrator. Contact support to re-enable it. |
| 403 | endpoint_not_permitted |
Your API key has endpoint scope restrictions and does not have access to the requested path. The response body includes an allowed_endpoints list. |
| 403 | account_inactive |
Your account has been deactivated. Contact support. |
| 429 | rate_limit_exceeded |
You have hit the daily request limit for your plan. The response body includes limit, used, and resets_at (midnight UTC). Upgrade your plan for a higher limit. |
| 202 | pending |
Not an error — the background worker has not yet produced output. Retry after a few seconds. Applies to /api/tpi/snapshot and monitor endpoints. |
| 400 | (varies) | Bad request — invalid parameter format (e.g. malformed bbox). The detail field describes what was wrong. |
| 502 | (varies) | Upstream data source error — HRRR, GFS, or NWS API was unreachable or returned unexpected data. The detail field describes which source failed. |
Error Response Shape
// HTTP 429 — rate limit exceeded
{
"error": "rate_limit_exceeded",
"message": "Daily API request limit of 50,000 reached for the 'free' plan. Limit resets at midnight UTC.",
"plan": "free",
"limit": 50000,
"used": 50000,
"resets_at": "2025-05-12T00:00:00Z"
}
// HTTP 403 — endpoint not in key scope
{
"error": "endpoint_not_permitted",
"message": "API key 'My App Key' does not have access to '/api/tpi/grid'.",
"allowed_endpoints": ["/api/tpi/snapshot", "/api/tpi/live"]
}