API preview
Everything on this site — obs, forecasts, soundings, ladders, edges, history — is served as JSON from /v1. No key or account is required for the free scanner today. A supported external API is coming soon; the web app runs on these exact routes now.
No authentication and no published rate limit. CORS is open to every origin, so you can call it straight from a browser while the API product is in preview. Please cache aggressively — the upstream feeds (Open-Meteo, Kalshi, Polymarket) are shared public infrastructure.
Authentication
There is none for the free preview. Send the request. An Authorization header is accepted and ignored, so client libraries written against a keyed build keep working.
curl "https://<your-host>/v1/markets?min_edge_c=10&venue=kalshi"
/v1/markets
All tracked markets with live obs, the selected forecast, market-implied temperature and the best-trade edge. This is the scanner as JSON — the site polls this exact route.
{
"as_of": "2026-07-29T20:12:04Z",
"count": 14,
"venues": [
{ "venue": "kalshi", "ok": true, "count": 9 },
{ "venue": "polymarket", "ok": true, "count": 2 }
],
"markets": [
{
"ticker": "KXHIGHNY-26JUL29",
"venue": "kalshi",
"station": "KNYC",
"type": "daily_high",
"closes_at": "2026-07-30T04:00:00Z",
"obs": { "temp_f": 91.3, "at": "2026-07-29T19:51:00Z", "trend_f_hr": 0.6,
"source": "open-meteo" },
"forecast": {
"high_f": 92.1, "sigma_f": 0.7, "updated_at": "2026-07-29T19:58:00Z",
"peak_local": "4:40 PM",
"components": { "model_consensus_f": 91.0,
"obs_bias_f": 0.62, "balloon_nudge_f": 0.48 }
},
"consensus": { "open_meteo": 90.0, "ecmwf": 91.2, "gfs": 90.5, "icon": 90.1 },
"selected_forecast": { "source": "open_meteo", "label": "Open-Meteo",
"high_f": 90.0, "sigma_f": 1.4 },
"market_implied_f": 90.8,
"gap_f": -0.8,
"edge": { "bucket": "91–92°", "side": "yes", "price_c": 38, "fair_c": 52,
"edge_c": 14, "ev_pct": 37, "kelly_quarter_pct": 4.8 },
"volume_usd": 1240000,
"open_interest_usd": 3100000,
"spread_c": 1,
"liquidity_grade": "A",
"sonde_obs_age_s": 840,
"simulated": { "balloon_network": true, "market_book": false }
}
]
}/v1/markets/{ticker}
Everything in /v1/markets plus the full bucket ladder. Pass forecast_source to switch the selected probability, fair price and edge lens. Sonde probability remains included for comparison.
{
"as_of": "2026-07-29T20:12:04Z",
"market": {
"ticker": "KXHIGHNY-26JUL29",
"selected_forecast": { "source": "open_meteo", "label": "Open-Meteo", "high_f": 91.8 },
"ladder": [
{ "bucket": "≤88°", "low_f": null, "high_f": 88,
"price_c": 6, "selected_prob": 0.0242, "selected_fair_c": 2,
"selected_edge_c": -4, "sonde_prob": 0.0184 },
{ "bucket": "91–92°", "low_f": 91, "high_f": 92,
"price_c": 38, "selected_prob": 0.4475, "selected_fair_c": 45,
"selected_edge_c": 7, "sonde_prob": 0.5216 }
],
"hourly": { "sonde": { "14": 90.6, "15": 91.5, "16": 92.1 },
"observed": { "14": 90.7, "15": 91.3 },
"open_meteo": { "14": 89.2, "15": 90.0 } },
"sounding": { "unit": "SONDE-7", "simulated": true }
}
}/v1/stations/{icao}/obs
Latest Open-Meteo current weather plus one value per elapsed local hour. Real public weather data — not Sonde proprietary telemetry.
{
"station": { "icao": "KNYC", "name": "Central Park",
"lat": 40.779, "lon": -73.969, "timezone": "America/New_York" },
"observation": {
"at": "2026-07-29T19:51:00Z",
"tempF": 91.3, "dewpointF": 68.0, "humidityPct": 47,
"windMph": 9.3, "windDir": "SW", "sky": "Mostly Clear",
"pressureInHg": 29.92, "pressureTrend": "falling",
"trendFPerHour": 0.6,
"todayHighF": 91.3, "todayLowF": 76.2,
"hourlyF": { "8": 81.0, "9": 82.8, "15": 91.3 },
"source": "open-meteo"
},
"simulated": false
}/v1/forecast/{icao}
The Sonde forecast for both market types, with its components broken out — model consensus, observation bias correction, and the simulated balloon contribution — alongside every public model's hourly curve.
{
"station": { "icao": "KNYC", "timezone": "America/New_York" },
"date": "2026-07-29",
"sonde": {
"daily_high": {
"value_f": 92.1, "sigma_f": 0.7,
"peak_local": "4:40 PM", "peak_window_local": "3:47 PM–5:33 PM",
"components": { "model_consensus_f": 91.0,
"obs_bias_f": 0.62, "balloon_nudge_f": 0.48 }
},
"overnight_low": { "value_f": 74.8, "sigma_f": 0.9 }
},
"models": {
"ecmwf": { "high_f": 91.2, "run": "12Z run", "run_age_h": 8 },
"gfs": { "high_f": 90.5, "run": "18Z run", "run_age_h": 4 }
},
"sources": { "models": "open-meteo.com (ECMWF IFS / GFS / ICON)",
"current_weather": "open-meteo.com",
"open_meteo_best": "open-meteo.com best_match",
"balloon_network": "SIMULATED" }
}/v1/soundings/latest
The balloon profile nearest a station, or the whole fleet with no near. Simulated — this deployment operates no fleet. Values are generated deterministically and anchored to the live observation, and every response says so.
{
"notice": "SIMULATED. This deployment operates no balloon fleet…",
"sounding": {
"unit": "SONDE-7",
"station": "KNYC",
"launched_at": "2026-07-29T17:42:00Z",
"next_launch_at": "2026-07-29T21:00:00Z",
"distance_mi": 3.1,
"bearing": "NE",
"profile_age_min": 14,
"surface": { "temp_f": 92.0, "dewpoint_f": 67, "humidity_pct": 44,
"wind_mph": 11, "feed": "2-s telemetry" },
"delta_vs_station_f": 0.7,
"levels_summary": {
"t_925mb_c": 26.1,
"mixed_layer_depth_km": 1.9,
"lapse_0_1km_c_km": 9.6,
"low_level_rh_pct": 38
},
"delta_vs_open_meteo": { "t_925mb_c": 1.9, "mixed_layer_depth_km": 0.6 },
"fresher_than_open_meteo_h": 5.7,
"simulated": true
}
}/v1/performance
MAE by source, calibration, Brier scores and the cumulative backtest. Resolved values are real. Issued forecasts are archived from the moment this deployment starts; archived days are scored for real, and only days predating the archive are reconstructed.
{
"notice": "Resolved values are real … Historical forecasts are SIMULATED …",
"days": 90,
"simulated_forecasts": true,
"forecast_source_coverage": { "archived_days": 14, "simulated_days": 76 },
"mae_by_source": [
{ "name": "Sonde", "maeF": 1.07, "isSonde": true },
{ "name": "ECMWF", "maeF": 1.63 }
],
"calibration": [ { "sayPct": 50, "happensPct": 51.7, "samples": 240 } ],
"brier": { "sonde": 0.118, "market": 0.154 },
"pnl": { "final_usd": 12480, "bankroll_usd": 10000 }
}/v1/resolutions
Settled station-days: what resolved, what each source called, and how the strategy would have settled.
{
"count": 12,
"resolutions": [
{ "date": "2026-07-28", "market": "New York · daily high", "icao": "KNYC",
"sondeF": 91.4, "impliedF": 90.2, "resolvedF": 91,
"errSonde": 0.4, "errMarket": 0.8, "result": "WIN", "pnlUsd": 212 }
]
}/v1/stream
Push channel for obs ticks and edge changes ≥2¢. The original spec called for a WebSocket; this deployment targets serverless hosting where a route handler can’t hold a socket, so it ships as Server-Sent Events — same one-way semantics, works through any proxy, and consumable with a one-line EventSource. Connections are capped at five minutes; reconnect when the stream ends.
const es = new EventSource(
"https://<your-host>/v1/stream?channels=edges,obs:KNYC&min_edge_c=8"
);
es.addEventListener("edges", (e) => {
const { markets } = JSON.parse(e.data); // only markets whose edge moved ≥2¢
console.log(markets[0].edge);
});
es.addEventListener("obs", (e) => console.log(JSON.parse(e.data)));Errors
Failures are explicit. A dead upstream returns 502 naming the feed rather than an empty success — if a panel is missing, the API will say why, and /v1/diagnostics reports every feed at once.
{ "error": "observation feed unavailable for KNYC: api.open-meteo.com returned 503" }