# A weather forecast by GPS coordinates or city, pay per call > An agent planning logistics or energy dispatch needs a forecast for a point and a lead time, not a dashboard. One paid call returns GFS — temperature, precipitation and wind — decoded from GRIB, no account. Published 2026-06-28 · Updated 2026-08-16 · HTML version: https://invoket.com/blog/a-forecast-for-any-location-pay-per-call --- An agent planning the next few days — routing a delivery, dispatching energy, deciding whether to spray a field — needs one forward-looking fact: *what will the weather be at this point at this lead time?* It does not need a dashboard, an account or an API key. One paid call — [`GET /weather/forecast`](/docs/api/weather-forecast) — returns it: 2 m temperature, precipitation and 10 m wind for a GPS point and a forecast target, served from GFS and returned as plain JSON, billed per call through x402. ## The problem: a forecast is a packed binary, not a fact a model knows Numerical weather prediction is the honest source for "what will happen next." The Global Forecast System (GFS), run by NOAA's NCEP, is the public reference: a global model on a mesh of roughly 0.25 degrees, re-run on a fixed cycle, with forecast steps reaching out about 16 days. It is authoritative because it is a physical model — and, like reanalysis, it ships as GRIB, a packed binary with its own grids, cycles and lead-time bookkeeping. A language model cannot decode GRIB, and it must not invent tomorrow's temperature for a specific coordinate. The valuable work is mechanical: pick the right cycle, resolve the requested lead, find the grid cell nearest the point, read the variables, convert units, and return a clean answer with enough metadata that the agent can judge it. That is what this endpoint does. ## The call: a point and a target Give a latitude, a longitude, and **exactly one** way to name the forecast target — a lead time in hours (`horizon_h`) or an explicit instant (`valid_time`): ```http GET /weather/forecast?lat=48.8566&lon=2.3522&horizon_h=24 GET /weather/forecast?lat=48.8566&lon=2.3522&valid_time=2026-06-21T00:00:00Z ``` The response is a `UnifiedResponse` — a `data` block plus a `provenance` block — the same shape every Invoket endpoint returns: | Field | What the agent learns | |-----------------|----------------------------------------------------------------| | `temperature` | 2 m temperature in Celsius | | `precipitation` | forecast precipitation total in millimetres | | `wind` | 10 m wind speed (m/s) and meteorological direction (degrees) | | `grid` | the cell that actually answered, and its distance from the point | | `lead` | resolved cycle, target instant and served model step | | `coverage` | whether every requested variable had a value | The `lead` block is the forecast-specific honesty: whichever way you named the target, it echoes back the GFS `cycle` used, the resolved `valid_time`, the computed `horizon_h`, and the actual `step_time` served — so the agent knows *which run and which step* produced the number. ## Honesty: a grid cell, a bounded horizon, and a freshness flag This endpoint is deliberately scoped, and the response says so on every axis. - **It is a grid value, not a station.** GFS is a gridded model on about a 0.25° mesh; the answer is the nearest or interpolated cell, and `grid` returns that cell's `lat`, `lon` and `distance_km` from the requested point. - **The horizon is bounded.** Forecast steps are discrete (commonly around three hours) and the public horizon reaches up to about 16 days (`horizon_h` `0` to `384`). A target outside the available window is a **400** `OUT_OF_RANGE`, not a fabricated extrapolation. - **Freshness is explicit.** `provenance.freshness.kind` is `live` for a fresh cycle, or `cached` with an `age_secs` when a stale-but-covered cycle answers — so an agent can decide whether to trust the number or retry after the next run. This endpoint answers **one point and one target per call**. For many point-and-target items in one settlement, use [`POST /weather/forecast/batch`](/docs/api/weather-forecast-batch); for a whole day-by-day series at one point, use [`GET /weather/forecast/daily`](/docs/api/weather-forecast-daily). ## A concrete answer ```json { "data": { "lat": 48.8566, "lon": 2.3522, "horizon_h": 24, "temperature": { "celsius": 18.6 }, "precipitation": { "total_mm": 0.4 }, "wind": { "speed_ms": 6.1, "direction_deg": 242.3 }, "grid": { "lat": 48.75, "lon": 2.25, "distance_km": 13.42 }, "lead": { "cycle": "2026-06-20T00:00:00Z", "valid_time": "2026-06-21T00:00:00Z", "horizon_h": 24, "step_time": "2026-06-21T00:00:00Z" }, "coverage": { "complete": true } }, "provenance": { "source": "gfs-noaa", "freshness": { "kind": "live" } } } ``` GFS data comes from NOAA and is public-domain U.S. government data. ## The x402 golden rule, applied to a forecast The agent pays for the *answer to its question*. A well-formed, covered request is a successful **200** — even when a variable is `null` because the grid cell has a gap, in which case `coverage.complete: false` names the missing family. Only requests the service genuinely cannot answer leave the 200 range: invalid coordinates or target (`INVALID_COORDS`, `INVALID_TIME`), a target past the horizon (`OUT_OF_RANGE`), or an unknown variable (`INVALID_VARIABLE`). One state is deliberately *not* a paid answer: if no GFS cycle has been ingested yet, the service returns **503** `NO_FORECAST_AVAILABLE` — a transient, no-charge condition, not a partial answer the agent is billed for. ## Where it fits in the x402 loop Each paid call follows the same pattern as every Invoket endpoint. The [Quickstart](/docs/quickstart) walks the whole discover → `402` → pay → replay cycle with runnable snippets, and [For agents](/docs/for-agents) covers the discovery surfaces and the live `/catalog`. Price and accepted rails are not pinned in this article — they are served live by the [catalog](https://api.invoket.com/catalog); see the [endpoint reference](/docs/api/weather-forecast) for the current figure. ## Forecast, not history `GET /weather/forecast` is the *future*: what GFS expects to happen. Its twin, [`GET /climate/point`](/docs/api/climate-point), is the *past* — historical ERA5 reanalysis for a dated location (see [Historical weather for any GPS point and date, from ERA5](/blog/historical-weather-for-any-gps-point)). Reach for the forecast when the decision is forward-looking — energy dispatch, logistics routing, short-term agricultural or risk planning; reach for the historical endpoint to enrich a claim or backtest a model. Used for what it is — a reproducible grid-cell forecast from GFS, with the served cell, the resolved lead and the cycle freshness exposed honestly — `GET /weather/forecast` gives an agent a future weather signal without an account and without parsing GRIB. For the full field reference, lead semantics and error codes, see the [`GET /weather/forecast` documentation](/docs/api/weather-forecast).