When to use this
You usually do not need this endpoint.
/v1/fetch and
/v1/ask both accept an address directly and echo the
same quality information back in a geocode block. Reach for /v1/geocode
when you want the coordinate on its own — to inspect it before spending a
fetch, to cache it yourself, or to reuse it across many calls.lat/lng. This one turns a street address into
that coordinate, and tells you how it was derived.
Geocoding is lossy — a coordinate can land on the wrong parcel — so wherever you
use it, the quality signal travels with the answer. As a standalone call you see
accuracy_type before doing anything else; via address on /v1/fetch you get
the same fields in the response’s geocode block.
Request shape
The parser is Geocodio’s, so ordinary formatting variation is fine —
Pkwy/Parkway, N/North, NY/N.Y., extra whitespace, mixed case.
What it cannot do is guess a locality: a bare "706 Ocean Pkwy" with no
city, state, or ZIP is ambiguous nationwide and comes back
404 address_too_coarse.
Example: a rooftop match
Read accuracy_type before you trust the coordinate
This is the field that matters. It says how the coordinate was
derived, and the difference is the difference between the right property
and a neighbour’s.
range_interpolation is the one to watch. It assumes house numbers are
evenly spaced along the block, which holds in a dense grid and breaks in
the countryside. Measured against authoritative county parcel polygons in
North Carolina: every rooftop result fell inside its own parcel with a
median error of 0 m, while interpolated results fell outside, one of them
by 1.1 km. In rural areas the 95th-percentile error is about 2,872 m —
several properties over.
Here is what that looks like. Note that the request said Kyle, TX and the
answer is in San Marcos:
accuracy_type and normalized_address both tell
you what happened — but a caller that reads only lat/lng would
silently underwrite the wrong site. A reasonable rule:
rooftop/nearest_rooftop_match— safe for parcel-level work.- anything else — treat as approximate. Show the user
normalized_addressand let them confirm before you act on it.
Vague addresses are rejected, not guessed
An address the geocoder can only place at a ZIP, city, county, or state centroid returns404 address_too_coarse instead of a coordinate.
This is worth stating plainly because the upstream behaves differently:
given a nonexistent address, Geocodio does not report “no match” — it
answers 200 with the nearest city centroid. Passing that through would
hand you a confident-looking coordinate for an arbitrary property near a
town centre, and every parcel-clipped field downstream would describe the
wrong land, with citations.
Two more ways a request is refused
Beyond the centroid floor above, a result is rejected when it is precise but about the wrong place. These are different failures and need different gates —accuracy_type says how precisely a match was placed, accuracy says
whether the right thing was matched at all.
Low confidence. Below 0.8 similarity (the provider’s own caution
threshold) the match is a guess, so it is refused rather than returned.
"1 Rue de Rivoli, Paris, France" used to come back as a Virginia coordinate at
0.65. Override with MIREYE_GEOCODE_MIN_SIMILARITY if you have a reason to.
Outside the US. We do not ask the provider to force a US match. Doing so
does not filter to US addresses — it asks for the best US thing available,
which is how "10 Downing Street, London, UK" became a rooftop-grade
coordinate in Charleston, West Virginia. Unforced, that query correctly returns
nothing, and a result that does come back non-US is refused.
Both surface as the same 404 codes documented under
Errors.
Known limitation: US territories
Coverage in Puerto Rico, Guam, the US Virgin Islands, American Samoa and the Northern Marianas is thin — and unlike everywhere else, the provider’s confidence score does not reflect that. Measured 2026-07-26:US.
We have not added a heuristic for it, deliberately. Every rule that catches
these also rejects legitimate mainland addresses: a real rural Texas address
that correctly resolves to a neighbouring town shares fewer tokens with its
match than the wrong Puerto Rico one does with its. Trading real addresses for
territory ones is the worse deal.
So this check is yours, and it is the ordinary one: compare
normalized_address against what your user typed. For territory addresses,
treat that as required rather than advisory.
It is not uniform. A San Juan address on a well-covered street resolved
correctly at 0.91, and the US Virgin Islands, American Samoa and the Northern
Marianas refuse cleanly rather than guessing. Puerto Rico and Guam are where a
wrong answer can look right.
Response shape
The fallback, and why provider matters
If the primary provider exceeds its 3 s deadline, we fall back to the free
US Census geocoder rather than failing the request. That fallback fires on
timeout only — never on a missing key, an auth failure, or a no-match,
because those must surface rather than be papered over with a
lower-precision answer.
The fallback is a genuine degradation, not an equivalent. In the same
North Carolina measurement it landed inside the correct parcel zero
times out of nine and missed 6 of 15 addresses entirely. It always reports
accuracy_type: "range_interpolation", and provider: "census" is your
signal that you are on the degraded path.
Errors
Every retryable failure carries a
Retry-After header; non-retryable ones
deliberately do not. A 1–256 character violation is a FastAPI 422, as
elsewhere in the API — see Errors.
Limits
- One address per request. No batching in V1; loop client-side.
- 256 characters maximum, rejected rather than truncated.
- Successful results are cached for 30 days; “no such address” for 24 hours.
A repeat lookup of the same address within the window is free and instant,
and the cache expires on the same 30-day clock as everything else we keep —
this page used to say “a year” here while promising 30 days two sections
down, and both could not be true. The cache key is normalized for
form only — case, spacing, accents and punctuation, except
-,#and/, which carry meaning (12-34Queens house numbers,# 4units,123 1/2half-addresses) — so706 Ocean Pkwyand706 OCEAN PKWYare one entry. It deliberately does not treatParkwayandPkwyas the same word: doing that safely requires knowing which token is the street suffix, and guessing merges real streets whose name is a suffix word (Northern Blvdwould collapse intoN Blvd). Two spellings of one address therefore cost two lookups. That is the intended trade — a duplicate lookup is cheap, a merged cache entry would hand you a different property’s coordinate. A negative is deliberately short-lived: an address the provider has not ingested yet starts working the moment it does, and a month-long 404 would outlast the truth by months. - Worst case 5.5 s (3 s primary + 2.5 s fallback). Set your client timeout above that.
- US only. Feed the coordinate to
/v1/fetchor/v1/ask, both of which enforce the US envelope.
What we keep
The address you send is recorded, alongside the coordinate it resolved to and the accuracy grade that produced it. We keep it so a result can be checked later. If you tell us a lookup returned the wrong data for one of your addresses, the record of what you actually sent is the only thing that can settle it — with just a coordinate and a result, there is no way to tell a bad match from a typo. Concretely, per request we store the address as you typed it, the resolvedlat/lng, and the geocode block including accuracy_type and provider.
Retention is 30 days, everywhere the address lives. Two stores hold it and
both expire on the same clock:
- The audit record (address as typed, coordinate,
geocodeblock) sits in monthly partitions; a scheduled job drops each one once its whole month is past the cutoff, so a record lives 30 to about 60 days depending on when in the month it was created. - The result cache (the matched address and coordinate, keyed by a digest of your input, kept so a repeat lookup does not re-bill) expires at 30 days via the store’s own TTL — no job involved, so it cannot quietly stop.
/v1/fetch or /v1/ask with lat/lng instead — a coordinate request stores
no address, because none was sent.