polyweather.today · API

polyweather OpenAPI

Programmatic access to live, minute-by-minute observed airport temperatures — the same sub-hourly runway-sensor data that leads the official METAR — plus today's-high tracking, METAR history and our next-METAR nowcast, across 30+ airports. JSON over HTTPS, rolling window only.

Copies the whole spec (endpoints + fields) as text — paste it into ChatGPT/Claude to generate a client.

Base URL

https://www.polyweather.today/api/open/v1

Authentication

Send your key in the Authorization header. Requests must come from an IP bound to the key, or you get 403 ip_not_allowed (the response's detail shows the detected IP — bind that one). Manage keys in the developer console.

Authorization: Bearer pmw_live_xxxxxxxx

Plans & limits

PlanPriceRateMonthlyIPs / keyAccess
Basic$49/mo60/min100,0001cities, latest, window, daily-high, metar
Pro$99/mo300/min1,000,0003+ nowcast, multi-city latest

Every response carries X-RateLimit-Remaining / X-RateLimit-Remaining-Month; a 429 includes Retry-After. {city} = ICAO (ZBAA) or slug (beijing); °C, UTC ISO-8601.

Quick start

curl -s "https://www.polyweather.today/api/open/v1/weather/ZBAA/latest" \
  -H "Authorization: Bearer pmw_live_your_key"

Code examples

Python (requests)
import requests

BASE = "https://www.polyweather.today/api/open/v1"
KEY = "pmw_live_your_key"   # create at https://www.polyweather.today/developers
headers = {"Authorization": f"Bearer {KEY}"}

# Latest observation for Beijing (runway temp leads the METAR)
r = requests.get(f"{BASE}/weather/ZBAA/latest", headers=headers, timeout=10)
r.raise_for_status()
d = r.json()
print(d["runway_temp_c"], "->", d["metar_temp_c"], "high", d["daily_high_c"])

# Next-METAR nowcast (Pro)
nc = requests.get(f"{BASE}/weather/ZBAA/nowcast", headers=headers).json()["nowcast"]
print(nc["pred_int"], "p", nc["p_hit"], nc["light"])
Node.js (fetch, Node 18+)
const BASE = "https://www.polyweather.today/api/open/v1";
const KEY = "pmw_live_your_key"; // create at https://www.polyweather.today/developers
const headers = { Authorization: `Bearer ${KEY}` };

// Latest observation for Beijing (runway temp leads the METAR)
const res = await fetch(`${BASE}/weather/ZBAA/latest`, { headers });
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const d = await res.json();
console.log(d.runway_temp_c, "->", d.metar_temp_c, "high", d.daily_high_c);

// Next-METAR nowcast (Pro)
const { nowcast } = await (await fetch(`${BASE}/weather/ZBAA/nowcast`, { headers })).json();
console.log(nowcast.pred_int, "p", nowcast.p_hit, nowcast.light);

Endpoints

GET/cities
API Basic

List supported cities and their codes.

{
  "count": 16,
  "cities": [
    {
      "code": "ZBAA",
      "slug": "beijing",
      "name": "Beijing",
      "airport": "Beijing Capital International Airport",
      "beta": false
    }
  ]
}
code ICAO code — use as {city} in other calls
slug also accepted as {city}
name city name
airport airport full name
beta true = newer station, less-calibrated nowcast
GET/weather/{city}/latest
API Basic

Newest observation for one city.

{
  "city": "ZBAA",
  "name": "Beijing",
  "runway_temp_c": 30.6,
  "runway_at": "2026-06-22T06:08:00Z",
  "metar_temp_c": 31,
  "metar_at": "2026-06-22T06:00:00Z",
  "daily_high_c": 31,
  "daily_high_at": "2026-06-22T06:00:00Z",
  "yesterday_high_c": 31,
  "conditions": {
    "wind_dir": 140,
    "wind_kt": 8,
    "gust_kt": 22,
    "sky": "FEW",
    "sky_cover": 1,
    "visibility_km": 10,
    "pressure_hpa": 1005,
    "dewpoint_c": 16
  },
  "source": "noaa",
  "generated_at": "2026-06-22T06:10:26Z"
}
runway_temp_c latest minute-level runway-sensor mean (°C) — leads the METAR
runway_at time of that runway reading (UTC)
metar_temp_c latest official METAR temperature (whole °C)
metar_at METAR observation time (UTC)
daily_high_c today's running daily high — the number markets settle on
daily_high_at when today's high was reached (UTC)
yesterday_high_c yesterday's daily high (context)
conditions observed wind/sky/visibility/pressure/dewpoint — each field present only when reported
source METAR source: noaa | amsc
generated_at snapshot build time (UTC)
GET/weather/{city}/window
API Basic

Rolling minute-by-minute series. Window only — no history beyond it.

Query:
limitpoints to return, default 90, max 120
{
  "city": "ZBAA",
  "name": "Beijing",
  "window_minutes": 90,
  "runway_ends": ["01", "18L", "18R", "19", "36L", "36R"],
  "count": 3,
  "points": [
    {
      "at": "2026-06-22T06:08:00Z",
      "ends": { "19": 30.6, "18R": 30.2, "36L": 30.8 },
      "mean": 30.6
    }
  ]
}
window_minutes rolling window length — only the last ~90 min is exposed
runway_ends this airport's runway-end labels
count number of points returned
points[].at minute timestamp (UTC), newest first
points[].ends per-runway-end temperature (°C)
points[].mean average across ends
GET/weather/{city}/daily-high
API Basic

Today's running high so far.

{
  "city": "ZBAA",
  "name": "Beijing",
  "daily_high_c": 31,
  "peaked_at": "2026-06-22T06:00:00Z",
  "hourly_settlement": false,
  "generated_at": "2026-06-22T06:10:26Z"
}
daily_high_c today's running max (°C) — the settlement number
peaked_at time of that high (UTC)
hourly_settlement true = only on-the-hour readings count (e.g. Chengdu)
GET/weather/{city}/metar
API Basic

Recent METARs (parsed temp + raw text).

Query:
limitcount, default 8, max 24
{
  "city": "ZBAA",
  "name": "Beijing",
  "metars": [
    {
      "at": "2026-06-22T06:00:00Z",
      "temp_c": 31,
      "raw": "METAR ZBAA 220600Z 14008KT 9999 FEW040 31/16 Q1005",
      "source": "noaa"
    }
  ]
}
metars[].at observation time (UTC)
metars[].temp_c METAR temperature (°C)
metars[].raw raw METAR text
metars[].source data source
GET/weather/{city}/nowcast
API Pro

Next-METAR forecast: prediction, probability distribution, decision light.

{
  "city": "ZBAA",
  "name": "Beijing",
  "nowcast": {
    "model": "anchor-v2",
    "pred_int": 31,
    "pred_float": 30.85,
    "h_min": 22,
    "next_metar_at": "2026-06-22T06:30:00Z",
    "p_hit": 0.551,
    "ladder": [
      { "t": 30, "p": 0.256 },
      { "t": 31, "p": 0.551 },
      { "t": 32, "p": 0.168 }
    ],
    "light": "yellow"
  },
  "slope_30": 0.17,
  "regime": "flat",
  "forecast": {
    "high_c": 32.4,
    "peak_hour_local": "15:00",
    "cloud_pct_peak": 45,
    "models": [ { "name": "ECMWF", "high": 31.5 } ],
    "tomorrow_high_c": 33
  }
}
nowcast.pred_int predicted NEXT METAR, rounded (°C)
nowcast.pred_float predicted, unrounded
nowcast.h_min horizon: minutes until the next METAR
nowcast.next_metar_at expected next METAR time (UTC)
nowcast.p_hit calibrated probability pred_int is exactly right
nowcast.ladder full probability distribution: { t: temp, p: probability }
nowcast.light decision light green / yellow / red (signal reliability)
slope_30 runway-temp slope, °C per 30 min (signed)
regime flat | mid | fast
forecast Open-Meteo model guidance: high_c, peak_hour_local, cloud_pct_peak, models[], tomorrow_high_c
GET/weather/latest
API Pro

Every city's latest in one call.

{
  "count": 16,
  "generated_at": "2026-06-22T06:10:26Z",
  "cities": [
    {
      "city": "ZBAA",
      "name": "Beijing",
      "runway_temp_c": 30.6,
      "metar_temp_c": 31,
      "daily_high_c": 31,
      "daily_high_at": "2026-06-22T06:00:00Z"
    }
  ]
}
cities[] per city: runway_temp_c, metar_temp_c, daily_high_c, daily_high_at

Errors

HTTPerrorMeaning
401missing_api_key / invalid_api_key / key_revokedBad or missing Authorization header.
402no_active_api_planPlan lapsed — renew at /developers.
403ip_not_allowedRequest IP isn't allowlisted. The detected IP is in `detail` — bind that IP.
403plan_upgrade_requiredEndpoint needs API Pro (nowcast, multi-city).
404unknown_city / unknown_resourceCheck the path.
429rate_limitedPer-minute or monthly cap hit — see Retry-After.

Getting started

API access is a paid add-on. Open the developer console to buy a plan (crypto, instant) and create an IP-locked key — your plan also unlocks the full web dashboard.

View-only data — not betting or financial advice. Rolling-window access; historical bulk export is not offered.