POST /climate/point/batch
Resolves many GPS point and date pairs in a single call against the ERA5
reanalysis store. Each item uses the same local GRIB-decoded lookup engine as
GET /climate/point: 2 m temperature, total
precipitation and 10 m wind for a dated location, with grid and coverage
metadata that let an agent judge the answer.
Use this endpoint when the agent has a portfolio of sites, parcels or assets to
score at once: parametric insurance checks, agricultural field reviews, energy
asset screening or logistics analysis. The batch is settled as one x402
payment for the whole call and priced per query by the gateway. See the live
/catalog for the authoritative endpoint listing, pricing
model and batch cap.
x402 golden rule: the agent pays for the answer to its question. A
well-formed batch with at least one covered item is a successful answer ->
200, even when other items have a grid gap or ask for a date outside the
covered ERA5 window: those items remain verdicts in results, with null
values and coverage.complete: false (partial success). Requests the service
cannot answer - malformed body, empty batch, batch over the published cap, a
malformed item, or a batch where no item at all is covered - leave the 200
range.
Request
POST with a JSON body. Set Content-Type: application/json.
POST /climate/point/batch
Content-Type: application/json
{
"queries": [
{ "lat": 48.8566, "lon": 2.3522, "date": "2024-07-14" },
{ "city": "Zurich", "date": "2024-07-14" },
{ "lat": 40.7128, "lon": -74.006, "date": "2024-01-20" }
]
}
| Field | Type | Required | Description |
|---|---|---|---|
queries | object[] | yes | Point queries to resolve, from 1 item up to the batch cap advertised in the live catalog |
lat | number | coordinate mode | Latitude in decimal degrees, from -90 to 90 |
lon | number | coordinate mode | Longitude in decimal degrees, from -180 to 180 |
city | string | place-name mode | Place name instead of coordinates, for example "city": "Zurich" |
location | string | no | Strict alias of city; if both are present they must be identical |
country | string | no | ISO-3166 alpha-2 code narrowing an ambiguous place name |
date | string | yes | UTC date to query, format YYYY-MM-DD |
Each item locates its point either with lat/lon coordinates or with
a place name via city (alias location) - the same gazetteer contract as the
single endpoint, and the resolved place is
echoed back in that item’s location field. An item with neither a point
nor a place name, out-of-bounds coordinates or a malformed date rejects the
whole batch with a 400 naming the item’s index - nothing is charged. An
item whose place name is unknown or ambiguous (an unresolvable city, a
city/location mismatch, or a place name given together with coordinates)
does not fail the batch: it stays in results as a degraded verdict -
coverage.complete: false with a guiding reason, only the echoed date,
no coordinates and no values - and is not part of what the agent pays for.
Batch items always request the full climate point payload. For field-level
details, including temperature, precipitation, wind, grid and
coverage, see the single-call reference.
200 response - UnifiedResponse
{
"data": {
"count": 2,
"results": [ { ... }, { ... } ]
},
"provenance": {
"source": "era5-copernicus",
"fetched_at": "2026-06-20T12:00:00Z",
"freshness": { "kind": "snapshot", "as_of": "2026-06-19T00:00:00Z" }
}
}
count: number of point queries resolved, equal toresults.lengthand to the number of submitted items.results: one verdict per query, in the same order as the input. Each element has the same shape as thedataobject returned byGET /climate/point.- A single
provenanceblock covers the whole batch. ERA5 values are derived from Copernicus Climate Change Service information and served from the same snapshot for every item in the call.
Example - mixed coverage batch
A covered item and an uncovered one - a grid gap, a date outside the covered
window, or an unresolvable place name - can coexist in the same paid answer. The
uncovered item remains a verdict in results; it does not make the whole batch
fail.
{
"data": {
"count": 3,
"results": [
{
"lat": 48.8566,
"lon": 2.3522,
"date": "2024-07-14",
"temperature": { "celsius": 24.3 },
"precipitation": { "total_mm": 0.4 },
"wind": { "speed_ms": 3.09, "direction_deg": 139.7 },
"grid": { "lat": 49.0, "lon": 2.0, "distance_km": 30.27 },
"coverage": { "complete": true }
},
{
"lat": 10.0,
"lon": 80.0,
"date": "2024-07-14",
"temperature": { "celsius": null },
"precipitation": { "total_mm": null },
"wind": { "speed_ms": null, "direction_deg": null },
"grid": { "lat": 10.0, "lon": 80.0, "distance_km": 0.0 },
"coverage": {
"complete": false,
"reason": "no data at this grid cell for: temperature, precipitation, wind"
}
},
{
"date": "2024-07-14",
"coverage": {
"complete": false,
"reason": "unknown place 'Xyzzy'; narrow with 'country' (ISO-3166 alpha-2) or provide lat/lon"
}
}
]
},
"provenance": {
"source": "era5-copernicus",
"fetched_at": "2026-06-20T12:00:00Z",
"freshness": { "kind": "snapshot", "as_of": "2026-06-19T00:00:00Z" }
}
}
Coverage honesty
ERA5 is a gridded reanalysis, not a weather station reading. Each result is the
nearest or interpolated grid value served for that item, with the same coverage
semantics as the single endpoint. A spatially uncovered grid cell can return
200 with null values and coverage.complete: false.
The historical window is finite, moves with the ingested store, and differs by
variable exactly as on the single endpoint: 2 m temperature and total
precipitation cover a rolling 30-year window (the WMO-standard climatological
period), 10 m wind a rolling ~5-year window. An item that asks for a date
outside the covered window is a per-item failure, not a batch failure: it
stays in results as a verdict with null values and
coverage: { "complete": false, "reason": "date outside the covered window" },
while the covered items around it are served normally. Only a batch where no
item is covered in date returns 400 OUT_OF_RANGE - zero values delivered,
so the agent pays nothing.
Batch cap and settlement
The gateway prices this endpoint per query and settles the batch as one x402
payment for the call. The current cap and pricing model are published in the
live /catalog, including the unit field used for the batch
size. The request body uses that same field, queries.
An oversized batch is rejected before any lookup work is performed, so it is not a paid answer. Split larger portfolios into multiple calls using the catalog’s published cap.
Errors
Only requests the service cannot answer leave the 200 range.
| Status | code | Case |
|---|---|---|
| 400 | INVALID_BODY | Body missing, not JSON, not an object, or queries missing |
| 400 | EMPTY_BATCH | queries is an empty array ([]) |
| 400 | BATCH_TOO_LARGE | More point queries than the published batch cap |
| 400 | INVALID_QUERY | An item is malformed, has out-of-bounds coordinates, provides neither coordinates nor a place name, or has an invalid YYYY-MM-DD date |
| 400 | UNKNOWN_LOCATION | No item in the batch resolved to a point (every place name unknown, or place-name resolution unavailable on the deployment) |
| 400 | OUT_OF_RANGE | No item in the batch is covered by the store window (a batch with at least one covered item is a 200 with per-item verdicts) |
| 500 | INTERNAL | Internal error (detail logged, not exposed) |
{ "error": "missing 'queries' array in request body", "code": "INVALID_BODY" }
{ "error": "'queries' must contain at least one item", "code": "EMPTY_BATCH" }
{ "error": "batch exceeds the published maximum number of queries", "code": "BATCH_TOO_LARGE" }
{ "error": "query at index 0: invalid date '14-07-2024', expected YYYY-MM-DD", "code": "INVALID_QUERY" }
{ "error": "no query resolved to a point: check the place names, narrow with 'country' (ISO-3166 alpha-2), or provide lat/lon", "code": "UNKNOWN_LOCATION" }
{ "error": "requested date is outside the covered window 1996-06-15..2026-06-14", "code": "OUT_OF_RANGE" }
See also
GET /climate/point- single point/date reference and full field documentation.- For agents - discovery surfaces, the live
/catalogand how settlement works.