The endpoint mismatch problem nobody talks about
Reach for /current.json by instinct — it says “current” in the name — and you’ll be right often enough that the problem stays hidden for a while. Then you’ll start seeing support tickets about temperatures that look off, or you’ll audit your quota usage and realize you’ve been burning calls on data that hasn’t changed. The gap between what the endpoint label implies and what the pipeline actually does is real, and it varies a lot depending on where the requested location is and what time of day the request lands.
This isn’t a WeatherAPI-specific quirk. It’s a structural mismatch, and it affects anyone building on any weather API that blends observations with model output under a single “current” label.
What /current.json actually returns
The current endpoint blends two data sources: the most recent METAR observation from the nearest (or best-scored) weather station, and model output to fill fields the station doesn’t report — things like feelslike_c, vis_km, and UV index. The observation half is only as fresh as the station’s last report. For an ICAO-coded airport station, that’s typically a METAR every 30 minutes. For a SYNOP station in a rural area, it might be hourly at best, and data age drifts.
The model-filled fields come from whichever NWP run is current. HRRR covers the contiguous US on an hourly run cycle at 3km grid resolution, so the model-derived fields are usually fresher than the observation half for US locations. Outside the HRRR domain you’re on GFS at 0.25-degree resolution, with a run cycle that drops to every 6 hours. “Current” in Chicago and “current” in rural Kazakhstan are not the same freshness guarantee — and the response gives you no immediate signal about which situation you’re in unless you parse last_updated yourself.
When the forecast endpoint is actually better for present conditions
Counterintuitive, but worth walking through. The /forecast.json endpoint with days=1 returns hourly data for today. For the current hour, that hourly slot draws from the same model output as the current endpoint, but it’s structured around a fixed time window rather than a live observation. For a dashboard refreshing every 15 minutes, the forecast endpoint’s hourly bucket for hour=N tends to be more stable and internally consistent than the current endpoint, which can show a small discontinuity when a new METAR arrives mid-interval and shifts the observation-blended values.
The real tradeoff: forecast data for the current hour is a model estimate, not an observation. If the distinction between “measured” and “modelled” matters for your use case — energy metering, agricultural sensor cross-validation, anything with a compliance requirement — stay on /current.json. If you’re building a UI and need a plausible present-conditions display, the hourly forecast slot is more predictable to work with.
Quota waste patterns from support tickets
Three patterns come up repeatedly.
1. Polling current.json faster than stations report
A developer polls /current.json every 5 minutes for a single location. METAR stations report every 30 minutes. The observation half of the response doesn’t change for 25 of those 30 minutes — so that’s 6 API calls returning effectively the same data that 1 cached call would have covered. The model-derived fields shift slightly between calls, but not in ways that matter for most UIs.
Fix: cache the response for 15–20 minutes with a short jitter (±2 minutes) to avoid thundering-herd re-requests at the cache expiry boundary. You miss nothing meaningful.
2. Using history.json for “yesterday” when forecast covers it
/history.json is metered differently on most plans. If you need yesterday’s hourly data and that date falls within the forecast endpoint’s lookback window, /forecast.json with a past date returns the same data at a lower quota cost. Check your plan’s specifics — but the general pattern holds: forecast endpoints are more quota-efficient for near-recent dates than the history endpoint.
3. Fetching full 14-day forecasts when you need 3 days
The response payload for days=14 runs roughly 4–5x the size of days=3 in JSON, and parsing it in a browser or mobile client carries a real cost. Beyond about day 7, GFS-based forecasts carry enough uncertainty that displaying hourly precision is actively misleading to users. Fetch what you’ll actually show.
Location type changes which endpoint strategy makes sense
Urban areas with dense METAR and SYNOP coverage — London, Chicago, Singapore — are where /current.json earns its name. Station density is high, the selected station is probably genuinely representative of the coordinate, and observations are fresh. The composite station-scoring logic (distance, elevation difference, recent reading consistency relative to neighbors) tends to find a good match quickly in these grids.
Remote or elevated locations are a different situation. If the nearest station is 60km away in a valley and the requested coordinate is on a mountainside, the current endpoint is doing more model-filling than the response makes obvious, and the observation component is less representative regardless of its timestamp. For these locations, leaning on the forecast endpoint — purely model-derived and at least internally consistent — is arguably more honest about what the data actually is. A reading that openly comes from GFS is less misleading than one that implies observation precision it doesn’t have.
A concrete decision tree
- Present conditions, urban or airport location, observation freshness matters:
/current.json, cache for 15 min. - Present-hour conditions for a UI, no compliance requirement:
/forecast.json?days=1, pullforecast.forecastday[0].hour[N]for the current hour index. More stable across refresh cycles. - Today’s full hourly timeline (past and future hours):
/forecast.json?days=1. Single call, covers the full day. - Last 2–5 days of hourly data: Check whether your plan allows past dates on
/forecast.jsonbefore reaching for/history.json. - More than 7 days back:
/history.json. No substitute. - Remote or elevated location where station representativeness is uncertain: Consider flagging the data source to your users rather than presenting model output as if it were an observation.
One thing worth checking in the response itself
The current object in a /current.json response includes last_updated and last_updated_epoch. Parse that field and compare it to your request time. A delta over 45 minutes means the observation input is stale — you’re mostly looking at model output regardless of which endpoint you called. Worth logging, especially for locations where observation freshness is part of your product’s accuracy story.
For well-covered locations this rarely triggers. But station outages and regional METAR feed gaps do happen, and last_updated is the earliest signal you’ll get that something is off — well before a user files a ticket saying the temperature looks wrong. A 90-minute-old “current” reading should probably hit a different code path than a 10-minute-old one. If you’re not already using that field for cache-invalidation logic, that’s the one concrete change worth making before you ship.
