Skip to main content
POST
Fetch
Fetch is free on every plan, including batch and asynchronous runs. No wallet balance or licensed-data terms grant is required. Authentication, request rate, concurrency and source capacity limits still apply. Free Fetch excludes parcel identity, ownership, boundaries, zoning and calculations that depend on licensed parcel records. Explicit mixed public/parcel selections are rejected; public presets intentionally include only eligible fields. Use Enrich for public and premium parcel evidence together.

When to use this

Use /v1/fetch when:
  • The caller knows exactly which fields they need.
  • The workflow is deterministic and you don’t want LLM latency or variability on every call.
  • You are powering a downstream model that needs raw structured values rather than synthesized prose.
  • You want a preset bundle (e.g., everything needed for flood underwriting) in one round trip.
Use /v1/ask instead when the question is phrased in natural language and the right answer requires combining values with interpretation.

Request shape

The body needs a location — either lat + lng or an address, never both — plus at least one of fields or preset (both is allowed — preset expands first, then fields unions in). The HTTP limit is 50 distinct explicit fields outside the chosen preset; preset members are exempt. Sending both a coordinate and an address, or neither, is a 422.

Fetching by address

The response is identical to a coordinate request, plus a geocode block:
resolved_location is on every response — coordinate requests too, where source is "coordinate" and no geocode block exists. It states, on one uniform key across all endpoints, which point the response actually answered about: a wrong-place answer is only catchable if the place is stated. Check parcel_grade before trusting parcel-specific fields. false means the coordinate was estimated along a street centerline rather than matched to a building — up to ~2,872 m out in rural areas, which is far enough to describe a neighbouring property. precision_note carries that warning in prose, and normalized_address is what the provider actually matched, so compare it against what your user typed. Budget an extra 5.5 s. An address request resolves the geocode before the fan-out starts, and that resolution is worst-case 3 s (primary) + 2.5 s (fallback) on top of the normal fetch time. A cached address adds effectively nothing. If your client timeout is tight, geocode once via /v1/geocode and reuse the coordinate. Address failures use the same codes as /v1/geocode — address_not_found, address_too_coarse, geocode_timeout, and friends — one table across /v1/geocode, /v1/fetch and /v1/ask.

Presets

Presets are use-case bundles. Pass "preset": "flood_risk" and you get the floodplain-relevant fields without naming each one. The preset expansions:
To add fields beyond a preset’s bundle, send both:

Example 1: flat fields list in Manhattan

Example 2: preset on a coastal coordinate

Houston, downtown — flood-relevant features in the same call:

Per-field response shape

Each value in fields is a self-contained record: A failed entry additionally carries error (string) and retryable (bool); its value is null. Read status to tell a real value from no-data from a failure without parsing notes.

The honesty pattern: status + partial_failures

/v1/fetch always returns 200 unless the request itself is malformed. A field that failed to fetch is surfaced two ways, so it can never be silently dropped or misread as “not requested”:
  1. In fields, with "status": "failed", "value": null, and the error + retryable hints inline — so every requested field is present in fields, distinguished by its status.
  2. In partial_failures, a flat list of just the failures (kept for back-compat).
Two recoverability hints (present on both the fields entry and the partial_failures record):
  • retryable: true — transient and worth a retry with backoff: a timeout / connection reset, or a public-source compute budget that resets later.
  • retryable: false — retrying won’t help: the upstream returned a structured error (a missing plan entitlement, an unsupported request).
We never silently drop a field we couldn’t fetch: every requested field appears in fields with a status (ok / absent / failed). Read status (or cross-check partial_failures) rather than assuming presence in fields means success — a failed field is present too.
Never cache a failed field. The HTTP status is 200, so a cache keyed on “request succeeded” will freeze a transient upstream timeout as a permanent answer. Cache ok and absent entries for up to their ttl_seconds; re-fetch failed entries (with backoff when retryable: true).

Missing and failed fields

Fetch has no usage charge. absent means valid no-data; failed means the source could not complete. Preserve that distinction when interpreting a result. Cacheable point-based fields use the same source cache as Enrich and Search. A successful source result can serve later requests through any of these endpoints, even when they select different fields from that source. Reuse follows the analysis coordinate, or a shared grid cell where supported. Each source keeps its own expiration policy; failed source results are retried. To reuse Enrich’s point values, pass its returned analysis_point.lat and analysis_point.lng to Fetch. This reuse applies only to Fetch’s public fields. Parcel ownership, boundaries and parcel-dependent calculations remain unavailable through Fetch, including wetland and conservation-easement overlaps. Use Enrich or Search’s optional enrichment for licensed parcel output. A cached source result does not expand an endpoint’s field permissions. Fetch remains free; source-cache reuse does not change Enrich or Search prices.

Limits

  • 50 additional explicit fields maximum per HTTP request. Preset members are exempt, and duplicates count once; the expanded result can exceed 50. Exceeding the explicit-field limit returns 400 fields_too_many. The MCP tool’s explicit fields array separately accepts at most 50 entries; use preset to request a published bundle.
  • Batching: one location per request here; up to 25 locations in one call via POST /v1/fetch/batch, which returns index-aligned results in this endpoint’s exact response shape.
  • No caching headers on /v1/fetch. The shared source cache uses local disk and a shared Redis tier in production. The response’s ttl_seconds hint is for the caller’s own cache layer.

Body

application/json
fields
string[] | null
preset
enum<string> | null
Available options:
terrain,
flood_risk,
wildfire_underwrite,
land_cover,
site_selection,
building_lookup,
points_of_interest,
utilities,
boundaries,
solar_siting,
wind_siting,
storage_siting,
data_center_siting,
grid_interconnect,
natural_hazard
lat
number | null
lng
number | null
address
string | null
Required string length: 1 - 256

Response

Successful Response