API v1

Read-only access to the same model cache the dashboard runs on. You can pull a single point or a batch of them, and everything comes back as JSON with CORS enabled.

During the beta these endpoints are open — no key required. API keys, per-tier rate limits, and paid access are planned for after the beta; heavy automated use may be throttled in the meantime, so be polite.

Quick start

curl "https://mesoviewer.com/api/forecast?lat=29.0&lon=-101.0"

Endpoints

GET /api/runs

List cached models, runs, params, and forecast hours.

Example

curl https://mesoviewer.com/api/runs

Response shape

{
  "data": [
    {
      "id": "hrrr",
      "latest_run": "20260418_09z",
      "runs": ["20260418_09z", ...],
      "params": ["sbcape", "shr06", "srh01", ...],
      "fhrs": ["f000", "f001", ..., "f018"]
    },
    { "id": "rap", ... },
    { "id": "gfs", ... },
    { "id": "rrfs", ... }
  ]
}
POST /api/forecast/bulk

Hourly forecast at many lat/lon points in one call (up to 1,000 points per request). The server builds its interpolant once per field and hour, so cost scales with the number of fields and hours; adding more points is nearly free.

Example

curl -X POST https://mesoviewer.com/api/forecast/bulk \
  -H "Content-Type: application/json" \
  -d '{
    "model": "hrrr",
    "params": ["mucape", "shr06"],
    "hours":  ["f003", "f007"],
    "points": [
      { "id": "amarillo", "lat": 35.2, "lon": -101.8 },
      { "id": "okc",      "lat": 35.5, "lon":  -97.5 },
      { "id": "dallas",   "lat": 32.8, "lon":  -96.8 }
    ]
  }'

Response shape

{
  "request": { "model": "hrrr", "run": "20260418_09z",
               "params": ["mucape","shr06"], "point_count": 3 },
  "run_time": "2026-04-18T09:00:00+00:00",
  "data": [
    {
      "point": { "id": "amarillo", "lat": 35.2, "lon": -101.8 },
      "hours": [
        { "fhr": "f003", "lead_hours": 3,
          "valid_time": "2026-04-18T12:00:00+00:00",
          "mucape": {"value": 0,    "unit": "J/kg"},
          "shr06":  {"value": 53.1, "unit": "kt"} },
        { "fhr": "f007", "lead_hours": 7,
          "valid_time": "2026-04-18T16:00:00+00:00",
          "mucape": {"value": 0,    "unit": "J/kg"},
          "shr06":  {"value": 54.4, "unit": "kt"} }
      ]
    },
    { "point": {"id":"okc","lat":35.5,"lon":-97.5}, "hours": [...] },
    { "point": {"id":"dallas","lat":32.8,"lon":-96.8}, "hours": [...] }
  ]
}
GET /api/forecast

Hourly forecast at a single lat/lon for one or more parameters.

Query parameters

NameRequiredDescription
latyesLatitude in degrees (-90..90).
lonyesLongitude in degrees (-180..180).
modelnoModel id (default: hrrr). See /api/runs.
runnoRun id (default: the latest cached run for the model).
paramsnoComma-separated param ids. Default: sbcape,shr06,srh01.
hoursnoComma-separated forecast hours (f003,f006) or all. Default: all.

Example

curl "https://mesoviewer.com/api/forecast?lat=29.0&lon=-101.0&model=hrrr&params=mucape,shr06,srh03&hours=f003,f007"

Response shape

{
  "request": { "model": "hrrr", "run": "20260418_09z", "lat": 29, "lon": -101,
               "params": ["mucape", "shr06", "srh03"] },
  "run_time": "2026-04-18T09:00:00+00:00",
  "data": [
    {
      "fhr": "f003",
      "lead_hours": 3,
      "valid_time": "2026-04-18T12:00:00+00:00",
      "mucape": { "value": 1558.74, "unit": "J/kg" },
      "shr06":  { "value": 49.37,   "unit": "kt" },
      "srh03":  { "value": 138.17,  "unit": "m²/s²" }
    },
    {
      "fhr": "f007",
      ...
    }
  ]
}

Error envelope

All non-2xx responses are JSON:

{ "error": { "code": "INVALID_PARAMS", "message": "lat and lon must be numeric" } }
CodeHTTPMessage (example)
INVALID_PARAMS400"lat and lon must be numeric"
INVALID_JSON400"could not parse body: …"
EMPTY_BODY400"POST body is required"
TOO_MANY_POINTS400"received 1500 points; max is 1000"
PAYLOAD_TOO_LARGE413"body must be < 5 MB"
MODEL_NOT_FOUND404"no cached data for model 'zzz'"
RUN_NOT_FOUND404"run '20260419_99z' not cached; latest is '20260418_09z'"
PARAM_NOT_FOUND404"params not cached for hrrr/20260418_09z: ['wibble']"

More endpoints

  • GET /api/sounding/{model}/{run}: the full vertical profile at a point (temperature, dewpoint, winds, heights).
  • GET /api/plume/gefs/{run}/t2m: all 31 GEFS members at a point for every cached hour.

Embeds

Drop a live map into your own page with an iframe — no key, no script tag. All parameters are optional:

<iframe
  src="https://mesoviewer.com/embed?lat=35.5&lon=-97.5&zoom=6&model=hrrr&param=sbcape&fhr=f003&theme=dark&basemap=vector"
  width="720" height="480" style="border:0"></iframe>

model / param / fhr pick what's shown (defaults: hrrr · shr06 · f003); run pins a cycle (default: latest); lat/lon/zoom or region (conus | ak | hi) frame the view; theme is light | dark; basemap is minimal | streets | satellite | terrain | vector. A small "open in MesoViewer" link carries viewers to the full dashboard.

Planned

  • POST /api/v1/alerts/webhook: register a geometry and threshold; the server posts to your URL when triggered.
  • GET /api/replay: historical model output beyond the rolling 24-hour cache.