/api-reference/meta-fields
GET /v1/meta/fields
cURL
curl --request GET \ --url https://api.example.com/v1/meta/fields
Self-discovery: field + preset catalog with ETag-based caching.
cURL
curl --request GET \ --url https://api.example.com/v1/meta/fields
When to use this
- Client-side validation — reject unknown field names before sending a /v1/fetch request.
- Tool descriptions — agents that build their own UI from the catalog populate field pickers and preset selectors from this endpoint.
- LLM planners — third-party agents that route to Mireye via the MCP server can render the catalog into their own planner system prompt, same as Mireye’s /v1/ask does internally.
Response shape
JSON
{
"fields": [
{
"derivation": null,
"description": "Ground elevation above the NAVD88 vertical datum at the queried point. Sourced from the USGS 3DEP 1/3 arc-second seamless DEM (~10m), with the USGS EPQS dynamic service as a coverage fallback.",
"interpretation_hints": "Below 10m within 5km of the coast \u2192 storm-surge exposure relevant. Above 3000m \u2192 alpine permitting, snow loads. Combine with coast_distance_m and within_floodplain_polygon for flood-zone reasoning.",
"layer": "terrain",
"lifecycle": "stable",
"name": "elevation",
"null_meaning": null,
"nullable": false,
"presets": [
"terrain",
"flood_risk",
"wildfire_underwrite",
"site_selection",
"wind_siting"
],
"source": "USGS_3DEP",
"source_url": "https://www.usgs.gov/3d-elevation-program",
"ttl_seconds": 31536000,
"type": "float",
"unit": "meters"
}
/* ...295 more fields, ordered by layer */
],
"presets": {
"terrain": ["elevation", "slope_degrees", "aspect_cardinal", "coast_distance_m", "soil_drainage_class", "bedrock_depth_cm"],
"flood_risk": ["elevation", "coast Self-discovery flow
Python
import httpx, time
BASE = "https://api.mireye.com"
class CatalogClient:
def __init__(self):
self._etag: str | None = None
self._catalog: dict | None = None
self._fetched_at: float = 0.0
async def get(self) -> dict:
# Refresh at most once an hour, even if our cache lies.
if self._catalog and time.time() - self._fetched_at < 3600:
return self._catalog
headers = {}
if self._etag:
headers["If-None-Match"] = self._etag
async with httpx.AsyncClient() as c:
r = await c.get(f"{BASE}/v1/meta/fields", headers=headers)
if r.status_code == 304:
self._fetched_at = time.time()
return self._catalog # unchanged
r.raise_for_status()
self._etag = r.headers["ETag"]
self._catalog = r.json()
self._fetched_at = time.time()
return self._catalog How the catalog drives the planner
Text
You are a geospatial data planner. Given a US coordinate and a natural-
language question, pick the catalog fields needed to answer it.
Available fields:
elevation (terrain, float, meters) — Ground elevation above NAVD88...
Hint: Use this when the caller asks about elevation...
Presets: terrain, flood_risk, site_selection, wildfire_underwrite
slope_degrees (terrain, float, degrees) — Slope at the coordinate...
Hint: Spread potential for wildfire; higher = faster spread...
/* ... */
Presets (use one of these instead of listing fields if it fits):
flood_risk: elevation, coast_distance_m, within_floodplain_polygon, ...
/* ... */ Versioning
- Patch (e.g., 0.6.0 → 0.6.1) — wording-only changes: description or interpretation_hints improved, no field added or changed. Safe to ignore for existing clients.
- Minor (0.5.x → 0.6.0) — additive, backwards-compatible changes: new fields or new presets registered. Existing field names, types, and semantics are untouched. (This is the common case — the catalog moved 0.2.0 → 0.6.0 through additive field registrations.)
- Major (0.x.y → 1.0.0) — breaking: field renamed, type changed, or removed. Clients hardcoding field names must be updated.
Successful Response