A day-by-day forecast series for one location, in one call

An agent planning energy, logistics or field work over a week needs the whole daily series, not one call per day: min/max temperature, total precipitation and peak wind for every day to the horizon.

By Matthias Begot · · Updated

An agent planning a week — scheduling energy dispatch, sequencing deliveries, picking a spray window on a farm — does not need one forecast instant. It needs the whole window: minimum and maximum temperature, total precipitation and peak wind for every day from today to the planning horizon. One paid call — GET /weather/forecast/daily — returns that series for a GPS point or a city name, one row per UTC calendar day, settled as one x402 payment for the entire series instead of a settlement per lead time.

The problem: weekly planning is many targets, and polling multiplies calls

The single-instant endpoint, GET /weather/forecast, answers one point and one target per call — the right shape when the question is “what happens here at hour 24?” (see A weather forecast by GPS coordinates or city, pay per call). But a planning agent’s question is a series: seven days, fourteen days, the whole covered window. Polling that lead time by lead time means one HTTP round-trip, one 402 challenge and one settlement per target — and then the agent still has to aggregate 3-hourly steps into daily minima, maxima and precipitation totals itself.

The daily endpoint collapses that loop. The agent states the point and the number of days; the service does the per-day aggregation from the same NOAA GRIB data and returns the finished series in a single response — a single settlement, whatever the length of the window.

The call: a point (or a city) and a number of days

Locate the point either with coordinates or with a place name — never both — and optionally bound the series with days (an integer from 1 to 35, defaulting to 16):

GET /weather/forecast/daily?lat=48.8566&lon=2.3522&days=7
GET /weather/forecast/daily?city=Zurich&days=7
GET /weather/forecast/daily?lat=48.8566&lon=2.3522&days=10&variables=temperature,precipitation

Place names resolve against an embedded GeoNames gazetteer — exact match, case- and accent-insensitive, ambiguity resolved by population and narrowed with country= — and the resolved place is echoed back in data.location, so the agent can verify which Zurich answered before acting on the numbers.

The series always starts at the current UTC day and runs forward: there is no from/to, because this endpoint is a forward window, not a historical range. For the past, the twin surface is GET /climate/point over ERA5 reanalysis.

What the agent gets back: one summary row per covered UTC day

The response is the same UnifiedResponse shape as every Invoket endpoint — a data block plus provenance. Inside data, days[] carries one element per covered UTC calendar day, in date order:

FieldWhat the agent learns
temperature_min_c / temperature_max_cdaily 2 m temperature extremes, Celsius
precipitation_sum_mmtotal precipitation over the day, millimetres
wind_speed_max_msmaximum 10 m wind speed of the day, m/s
sourcethe model that served this day — never mixed within a day
steps_usedhow many forecast steps actually backed the summary
coverageper-day completeness, with a reason when partial

Alongside the rows, grid names the cell that actually answered (with its distance from the requested point), lead.cycle names the analysis cycle, and a top-level coverage block states whether the whole requested range was served in full.

Two registers: deterministic days first, ensemble-mean days after

The series is backed by two public NOAA models. The Global Forecast System (GFS) is the deterministic register, on roughly a 0.25° mesh with forecasts out to 16 days. Beyond it, the Global Ensemble Forecast System (GEFS) — a 31-member ensemble whose 00 UTC cycle extends to 35 days — supplies the extended window as an ensemble mean on a coarser 0.5° mesh. Both are public-domain U.S. government data.

The endpoint chooses the source per day and says so: a day fully covered by the deterministic GFS is served from it; a later day is served from the GEFS ensemble mean, and its source field names it explicitly. An ensemble mean is a smoothed central estimate, not a deterministic run — an agent weighing a day-25 number should treat it accordingly, and the response gives it exactly the metadata to do that.

Coverage honesty: partial days are marked, never hidden

The daily rows are derived summaries, and the endpoint is explicit about how:

  • Grid cell, not station. Values come from the nearest model grid cell — about 0.25° in the GFS register, 0.5° in the ensemble register — not a weather-station reading. grid.distance_km quantifies the gap.
  • Sub-sampled extremes. Min/max temperature are the extremes of the ingested 3-hourly steps, not the model’s own daily TMAX/TMIN fields; the true extreme can be missed by a few tenths of a degree.
  • Partial days are flagged. Day zero starts at the analysis cycle rather than at midnight, so it is usually complete: false with a stated reason; the same applies to a day cut at the window end or missing a family value.
  • Uncovered days are omitted, not invented. Asking for more days than the window covers is never an error: absent days simply do not appear in days[], and the top-level coverage says how many fell outside. The agent never has to shrink days to dodge a 400.

The x402 golden rule, applied to a series

The agent pays for the answer to its question. A well-formed request that returns at least one usable day is a 200 — including a series with a partial first day or a grid gap, both reported through coverage. Only requests the service cannot answer leave the 200 range: invalid coordinates or an unresolvable place name, an out-of-bounds days, or a range with no covered day at all (OUT_OF_RANGE). And if no forecast cycle has been ingested yet, the service returns 503 NO_FORECAST_AVAILABLE — a transient, no-charge state, never a paid partial answer.

Pricing is flat per call for the whole series; the authoritative figure — like every price and accepted rail — is served live by the catalog, never hardcoded here.

A network of sites: the batch companion

For a portfolio of locations, POST /weather/forecast/batch resolves many point-and-target forecasts in one call and one settlement, priced per query. Its items are single instants — each carries lat/lon and exactly one target (horizon_h, valid_time or date) — so a multi-site weekly plan is expressed as a fan-out of site × date items within the published batch cap, with per-item coverage verdicts and partial success (one uncovered site never fails the batch). Note the scope differences from the daily endpoint: batch items take explicit coordinates only (no city names), and the batch returns instant values, not pre-aggregated daily summaries.

The practical split: one site, whole window → the daily series; many sites, specific targets → the batch.

Where it fits in the x402 loop

The call follows the same cycle as every Invoket endpoint — discover the endpoint, receive a 402 challenge, pay, replay. The Quickstart walks that loop with runnable snippets, and For agents covers the discovery surfaces and the live /catalog.

Used for what it is — a reproducible day-by-day summary of public NOAA forecast data, with the serving model, grid cell and completeness of every single day exposed honestly — GET /weather/forecast/daily turns “poll the forecast all week” into one paid call. For the full field reference, place-name contract and error codes, see the GET /weather/forecast/daily documentation.