# Historical weather for any GPS point and date, from ERA5 > An agent often needs the weather that actually happened at a location on a date. One paid call returns ERA5 reanalysis — temperature, precipitation and wind — decoded from GRIB, no account. Published 2026-06-28 · Updated 2026-08-16 · HTML version: https://invoket.com/blog/historical-weather-for-any-gps-point --- An agent enriching a claim, a backtest or a portfolio of sites often needs one fact it cannot regenerate from text: *what was the weather at this exact place on this exact date?* The honest source is reanalysis — and the honest format is GRIB, a binary the model cannot decode. One paid call — [`GET /climate/point`](/docs/api/climate-point) — answers it: 2 m temperature, total precipitation and 10 m wind for a GPS point and a date, served from ERA5 and returned as plain JSON. No account, no key, pay per call through x402. ## The problem: the real value is locked in GRIB The weather that *actually happened* is not a search result; it lives in gridded reanalysis datasets. ERA5, produced by the Copernicus Climate Change Service (C3S) at ECMWF, is the reference: a globally consistent, hourly record on a mesh of roughly 0.25 degrees, reconstructed by blending observations with a physical model. It is authoritative precisely because it is not a guess — and it ships as GRIB, a packed binary format with its own grids, message headers and unit conventions. A language model cannot decode GRIB, and it should not try to recall a specific day's temperature from memory — that is exactly where it hallucinates. The work that has value is the boring part: pull the right grid, find the cell nearest the point, read the variables, convert units, and hand back a clean answer. That is what this endpoint does. ## The call: one point, one date Supply a latitude, a longitude and a UTC date. Optionally narrow the payload to the families you need: ```http GET /climate/point?lat=48.8566&lon=2.3522&date=2024-07-14 GET /climate/point?lat=48.8566&lon=2.3522&date=2024-07-14&variables=temperature,wind ``` 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` | daily total precipitation 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 | | `coverage` | whether every requested variable had a value | The runtime lookup is local against a GRIB-decoded store, so a covered point resolves in milliseconds. ## Honesty: it is a grid cell, not a station This is the scope point that keeps the answer trustworthy. ERA5 is a gridded reanalysis, **not** a weather station reading. The value you get is the nearest or interpolated grid value for the served cell — on a mesh of about 0.25 degrees — and the response tells you so. The `grid` block returns the cell's own `lat`, `lon` and `distance_km` from the requested point, so an agent can judge how representative the answer is rather than assuming pinpoint precision. Two boundaries follow from the same honesty: - **A covered date can still have a gap.** If a grid cell is missing a value, the response is a **200** with that value `null` and `coverage.complete: false` naming the missing family. The agent paid for the answer to its question, and "there is a gap here" *is* the answer. - **A date outside the window is a 400.** The historical window is finite and moves with the ingested store. A date outside it returns **400** `OUT_OF_RANGE` — the service will not bill for a request it cannot answer. This is the x402 golden rule applied to climate: a well-formed, covered request is a successful answer; only requests the service genuinely cannot process (invalid coordinates, invalid date, an uncovered date, an unknown variable) leave the 200 range. ## A concrete answer ```json { "data": { "lat": 48.8566, "lon": 2.3522, "date": "2024-07-14", "temperature": { "celsius": 22.4 }, "precipitation": { "total_mm": 1.2 }, "wind": { "speed_ms": 4.8, "direction_deg": 216.9 }, "grid": { "lat": 48.75, "lon": 2.25, "distance_km": 13.42 }, "coverage": { "complete": true } }, "provenance": { "source": "era5-copernicus", "freshness": { "kind": "snapshot", "as_of": "2026-06-19T00:00:00Z" } } } ``` `provenance.freshness.as_of` tells the agent which store production date backed the answer, so a reasoning loop can decide whether the snapshot is recent enough. ## 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/climate-point) for the current figure. ## Scoring a portfolio in one settlement Enrichment is rarely one point. When an agent has a list of sites, parcels or assets to score for the same study, [`POST /climate/point/batch`](/docs/api/climate-point-batch) resolves many point-and-date pairs in a single call settled as **one** x402 payment instead of one settlement per point: ```json { "queries": [ { "lat": 48.8566, "lon": 2.3522, "date": "2024-07-14" }, { "lat": 40.7128, "lon": -74.006, "date": "2024-01-20" } ] } ``` Results come back in input order, each item carrying its own `grid` and `coverage`, so a partially uncovered point is a verdict in the list — not a failure of the whole batch. The cap and the per-query pricing model live in the live `/catalog`. ## Historical, not forecast `GET /climate/point` is the *past*: what the reanalysis says happened. Its twin, [`GET /weather/forecast`](/docs/api/weather-forecast), answers the *future* — a point forecast from GFS for upcoming dates and lead times. Reach for the historical endpoint to enrich a claim, backtest an agricultural model or build a parametric-insurance baseline; reach for the forecast when the decision is forward-looking. When the question is a season rather than a day, [`GET /climate/aggregate`](/docs/api/climate-aggregate) summarises a window instead of returning a single date. Used for what it is — a reproducible grid-cell value from ERA5, with the served cell and its coverage exposed honestly — `GET /climate/point` gives an agent the weather that actually happened, without an account and without parsing GRIB. For the full field reference, boundary semantics and error codes, see the [`GET /climate/point` documentation](/docs/api/climate-point). ERA5 values are derived from Copernicus Climate Change Service (C3S) information.