TORCAST API Reference

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.

All data is read-only. No write operations are exposed through the developer API. Authentication uses a per-user API key — no OAuth flow required.

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
Keep your key secret. Treat it like a password. Do not commit it to source code or expose it in client-side JavaScript on public pages. Regenerate it from the dashboard if it is compromised.

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).

PlanDaily LimitNotes
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:

HeaderDescription
X-RateLimit-LimitYour plan's daily request ceiling
X-RateLimit-UsedRequests consumed so far today (UTC)
X-RateLimit-RemainingRequests left before the limit is hit
X-RateLimit-PlanYour 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.

0.0–0.5
None
0.5–1.5
Marginal
1.5–2.5
Slight
2.5–3.5
Enhanced
3.5–4.5
Moderate
4.5–5.5
High
5.5–10.0
Extreme

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

FieldTypeDescriptionExample
idstringUnique point identifier derived from lat/lon and mode"live_37.690_-97.330"
latfloatLatitude of the queried point37.69
lonfloatLongitude of the queried point (negative = west)-97.33
namestring | nullHuman-readable location name when available"Wichita, KS"
statestring | nullTwo-letter US state code for the point"KS"

Core TPI Values

FieldTypeDescriptionExample
live_tpifloat | nullCurrent observed TPI. Derived from live NWS alerts, surface observations, storm reports, and boundary detection. Updates as new observations arrive.6.4
predicted_tpi_1hfloat | nullForecast TPI for the next 1 hour using HRRR (3 km convection-allowing model)5.8
predicted_tpi_3hfloat | nullForecast TPI 3 hours out — HRRR. Most commonly used for near-term planning.7.1
predicted_tpi_6hfloat | nullForecast TPI 6 hours out — HRRR4.3
predicted_tpi_12hfloat | nullDay 1 morning outlook — GFS 0.25°. Lower resolution; environment-only (no convective-scale fields).3.0
predicted_tpi_24hfloat | nullDay 1 full outlook — GFS2.5
predicted_tpi_48hfloat | nullDay 2 outlook — GFS. Treat as a broad environmental signal only.1.8
predicted_tpi_72hfloat | nullDay 3 outlook — GFS1.2

Trend & Confidence

FieldTypeDescriptionValues
delta_tpi_3hfloat | nullChange in TPI: predicted_3h minus live_tpi. Positive = conditions are worsening near-term.+0.7
delta_tpi_24hfloat | nullChange from live to 24h forecast — useful for day-scale trend detection-1.2
trendstring | nullHuman-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
confidencestring | nullOverall data quality confidence for this point's score"High" | "Medium" | "Low"

Labels

FieldTypeDescription
live_labelstring | nullText label for live_tpi, e.g. "Moderate Severe", "High Tornado Potential"
predicted_label_1hstring | nullText label for 1h forecast TPI
predicted_label_3hstring | nullText label for 3h forecast TPI
predicted_label_6hstring | nullText label for 6h forecast TPI
predicted_label_24h / 48h / 72hstring | nullText labels for extended GFS forecast windows

ML Correction

FieldTypeDescription
ml_tpifloat | nullML-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_correctionfloatHow much the ML engine shifted the rule-based score (+/−). Zero when model is inactive.

Watch Override

FieldTypeDescription
watch_floor_appliedbooleanTrue 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_typestringType of active watch, e.g. "Tornado Watch", "Severe Thunderstorm Watch". Empty string if no watch is active.

Metadata

FieldTypeDescription
suppressedbooleanTrue when the rule engine suppressed the TPI score based on reality checks (e.g. very high CIN with no forcing)
suppress_reasonstringHuman-readable explanation of why the score was suppressed, if applicable
partial_databooleanTrue when one or more upstream data sources were unavailable. The score is still valid but may be less accurate.
stale_sourcesstring[]List of data source names that were stale or unavailable for this computation
computed_atISO 8601 datetimeUTC timestamp when this specific result was calculated
forecast_model_shortstringModel used for 1h/3h/6h forecasts — always "hrrr"
forecast_model_extendedstringModel used for 12h–72h forecasts — always "gfs"

Endpoints

GET /api/meta Scoring thresholds, labels, weights, data sources

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": [ ... ]
}
GET /api/tpi/snapshot Pre-computed regional grid — fastest endpoint

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.

Returns HTTP 202 Accepted (not 200) if the background worker has not yet produced a snapshot. Check 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

FieldDescription
meta.computed_atUTC timestamp when the worker last regenerated the snapshot
meta.point_countTotal number of grid points in this snapshot
meta.snapshot_age_secondsHow 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.warningPresent only when the snapshot is stale — describes the age and suggests checking worker status
GET /api/tpi/live Real-time TPI for a single point

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

ParameterTypeDefaultDescription
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
}
GET /api/tpi/predicted Forecast TPI for a specific hour

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

ParameterTypeDefaultDescription
latfloat32.84Latitude
lonfloat-83.63Longitude
forecast_hourint (1–72)3Target forecast hour. Snapped to nearest supported: 1, 3, 6 (HRRR) or 12, 24, 48, 72 (GFS). Example: passing 4 uses the 3h HRRR window.
statestringnullTwo-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"])
GET /api/tpi/combined Live + all forecast windows + delta + trend in one call

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

ParameterTypeDefaultDescription
latfloat32.84Latitude
lonfloat-83.63Longitude
statestringnullTwo-letter state code
formatstring"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"
GET /api/tpi/grid Compute TPI over a bounding box

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.

Performance note: Large bounding boxes with fine spacing generate many concurrent upstream requests and may take 10–60+ seconds. Use spacing ≥ 0.25 for broad regional queries. For regional coverage consider /api/tpi/snapshot instead — it is instantaneous.

Query Parameters

ParameterTypeDefaultDescription
bboxstringGeorgia bboxBounding 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.
spacingfloat (0–5)config defaultGrid spacing in degrees. Smaller = more points. Use 0.5 for a fast regional pass, 0.1 for detailed city-scale analysis.
statestringnullState context for boundary detection
formatstring"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']}")
GET /api/tpi/contours SPC-style risk contour polygons

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

ParameterTypeDefaultDescription
fieldstring"live_tpi"Which TPI field to contour. Options: live_tpi, predicted_tpi_1h, predicted_tpi_3h, predicted_tpi_6h, predicted_tpi_24h
min_tpifloat0.5Minimum TPI to include in contours. Increase to filter out low-end areas.

Contour Levels

LevelCategoryColorMeaning
0.5+MRGL#66FF66Marginal risk
1.5+SLGT#FFFF00Slight risk
2.5+ENH#FFA500Enhanced risk
3.5+MDT#FF0000Moderate risk
4.5+HIGH#FF00FFHigh risk
5.5+EXTRM#FFFFFFExtreme risk
GET /api/tpi/categories TPI category definitions for legend rendering

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.

GET /api/v2/ci Convective initiation monitor

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

FieldTypeDescription
windowsarrayList of active CI windows. Empty array when no initiation is detected.
windows[].lat / lonfloatCenter point of the CI window
windows[].severitystringOverall CI severity: "Low", "Moderate", "High", "Extreme"
windows[].glm_jumpbooleanTrue when a GOES-16 GLM lightning jump (2σ threshold) is active at this location
windows[].abi_updraftbooleanTrue when GOES-16 ABI Band 14 cloud-top roughness exceeds the updraft detection threshold
windows[].tpifloatTPI value from the nearest snapshot grid point
overall_severitystringHighest severity across all active windows
GET /api/v2/glm GOES-16 GLM lightning jump status

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

FieldDescription
lightning_jump_activeBoolean — true when a 2σ lightning jump is currently detected
flash_rate_per_minCurrent GLM flash rate (flashes per minute)
rolling_mean_per_min10-minute rolling mean flash rate — the baseline the jump threshold is calculated from
sigma_2_thresholdThe computed 2σ threshold; jump is flagged when flash_rate exceeds this value
retrieved_utcUTC timestamp of the last successful GLM data fetch
GET /api/v2/abi GOES-16 ABI cloud-top roughness (updraft detection)

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

FieldDescription
developing_updraft_detectedBoolean — true when max IR roughness exceeds the updraft detection threshold
max_laplacian_varianceMaximum IR roughness value across the analysis domain — higher = more turbulent cloud tops
high_roughness_zonesArray of lat/lon locations where cloud-top roughness is above threshold
retrieved_utcUTC timestamp of the last ABI data fetch
GET /api/v2/ensemble Weighted ensemble TPI blend across model runs

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

FieldDescription
max_ensemble_tpiHighest TPI value in the current ensemble blend — indicates peak potential anywhere in the domain
points_blendedNumber of grid points included in the ensemble calculation
model_divergence_penaltyBoolean — true when HRRR and GFS disagree enough to apply a 15% confidence reduction
generated_utcUTC timestamp when the ensemble was last computed
GET /api/mping/reports mPing crowd-sourced weather reports

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

ParameterTypeDefaultDescription
hoursint (1–24)2How many hours back to fetch reports. Maximum 24.
categorystringnull (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)

FieldDescription
idmPing report ID
obtimeISO 8601 UTC observation time
categoryReport category (Hail, Tornado, Wind Damage, etc.)
descriptionUser-provided description of the event
lat / lonCoordinates of the report
GET /api/sounding/nearest Atmospheric sounding for the nearest BUFKIT station

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

ParameterTypeRequiredDescription
latfloatREQUIREDLatitude of the query point
lonfloatREQUIREDLongitude
modelstringoptionalData source: hrrr (default), rap, nam, namnest, gfs, sref, hiresw
fhourint (0–72)optionalForecast hour (default 0 = analysis)
include_profilebooleanoptionalSet 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

FieldDescription
nearest_stationBUFKIT station ID of the closest sounding site to your query point
sounding_params.sbcape_jkgSurface-based CAPE (J/kg) — energy available for thunderstorm development. Values >1000 indicate significant instability.
sounding_params.sbcin_jkgSurface-based CIN (J/kg) — the "cap" inhibiting storm initiation. Values <−50 indicate a strong cap; <−200 is effectively a lid.
sounding_params.srh_0_1kmStorm-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_3kmStorm-Relative Helicity 0–3 km (m²/s²) — mid-level rotation potential
sounding_params.shear_0_6km_ms0–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_mLifted Condensation Level height (m AGL) — cloud base. Lower LCL (<1000 m) favors tornado potential.
sounding_params.stpSignificant Tornado Parameter — composite index combining CAPE, SRH, shear, LCL height. >1.0 indicates significant tornado potential.
sounding_params.scpSupercell Composite Parameter — broader supercell potential index. >1.0 supports supercell development.
viewer_urls.iemDirect URL to the Iowa Environmental Mesonet sounding viewer for this station
viewer_urls.rucsoundingsDirect URL to the RUC Soundings viewer for this location
profileFull vertical profile arrays (only present when include_profile=true): p (hPa), z (m), T (°C), Td (°C), u/v (m/s)

Error Codes

HTTP StatusError CodeMeaning
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"]
}