---
title: "Reverse geocode — convert coordinates into the nearest address"
method: GET
path: "/v1/reverse"
tags: ["Geocoding"]
---

# Reverse geocode — convert coordinates into the nearest address

`GET /v1/reverse`

## Request

- Base URL: `https://geo.thinair.co`
- URL: `https://geo.thinair.co/v1/reverse`
- Auth: HTTP bearer

Look up the nearest address, street, or place around a `(lat, lon)` pair. Results ordered by proximity. Results may be served from cache for up to 7 days, so repeated nearby lookups can return `X-Cache: HIT`.

## Query parameters

- `lat` number, required: Latitude in decimal degrees, WGS84.
- `lon` number, required: Longitude in decimal degrees, WGS84.
- `size` integer: Maximum candidates to return (1–40). Defaults to 5 in the service layer (capped to 40).
- `layers` string: Restrict to a comma list of layers: address, street, venue, neighbourhood, borough, locality, localadmin, county, macrocounty, region, macroregion, dependency, country, continent, postalcode, or coarse (all admin layers). Admin layers resolve from the nearest indexed feature's parent hierarchy.
- `boundary_country` string: ISO 3166-1 alpha-2 or alpha-3 country code to scope results.

## Response `200`

Reverse geocoder result envelope.

- ReverseResponse
  - `features` ReversedFeature[], required
    - `id` string: Stable public ThinAir id (`ta_place_<key>` / `ta_intersection_<key>`). Resolvable via `GET /v1/place`.
    - `name` string
    - `label` string
    - `confidence` number
    - `layer` string
    - `intersection_type` 'corner' | 'interchange'
    - `intersection_precision` 'geometric_crossing' | 'tangent_intersection' | 'centroid_cluster' | 'approximate'
    - `street_kind` 'street' | 'route'
    - `cross_street_kind` 'street' | 'route'
    - `street_route` string
    - `cross_street_route` string
    - `place_type` string, required
    - `confidence_scope` 'query_to_candidate', required: What `confidence` is scoped to. `query_to_candidate` means it scores how well this candidate matches the submitted query — it is NOT a probability that the place is real, that the address is correct, or that mail would arrive. Fixed value today; treat it as a closed set that may gain members.
    - `address_evidence` object, required: What THIS CANDIDATE carries, component by component — `matched` (a real value is present), `partial` (only a coarser or derived stand-in, e.g. an interpolated house number or a locality falling back to its administrative parent), `absent` (nothing). This describes the result, NOT a comparison against your query: the engine returns no per-component match data, and re-parsing your text here would mean two parsers disagreeing about the same string. Derived from the feature, never from `confidence`.
      - `house_number` 'matched' | 'partial' | 'absent', required
      - `street` 'matched' | 'partial' | 'absent', required
      - `locality` 'matched' | 'partial' | 'absent', required
      - `region` 'matched' | 'partial' | 'absent', required
      - `postal_code` 'matched' | 'partial' | 'absent', required: Whether the candidate carries a postal code. Presence only — this states what the result has, and makes no claim about its correctness.
    - `postal_code` string: An eligible US ZIP5 read from the selected result's own postal-code field. While origin enforcement is active this field is emitted ONLY when the engine stamped the value as coming from the address record itself (`source_record` provenance); a value inherited from a parent area, or a result cached before that evidence existed, is omitted rather than emitted without provenance — so an absent ZIP under enforcement means "not proven for this record", not "no such ZIP". Provenance describes only WHERE the value came from. It is not a postal operator check of any kind — no certification, no address-quality rating, and no statement about whether mail would arrive — so a syntactically correct, correctly-sourced value can still be wrong for the address. Also omitted when unavailable or unsuitable for five-digit form. US address results only. Distinct from `address_evidence.postal_code`, which is a presence STATUS rather than a value. On reverse geocoding this describes the RETURNED ADDRESS — it is not a postal assignment to the coordinate you supplied.
    - `address_line1` string: House number and street for an eligible US address result, composed from the result's own components — never parsed from the display label. Absent when the result is not a US street address.
    - `address_line2` string: Unit or suite, only when the source record carries one. A unit supplied in your request is never echoed back here.
    - `formatted_address` string: Single-line US display form, e.g. `1600 Pennsylvania Avenue NW, Washington, DC 20500, USA`. The postal segment is present only when an eligible ZIP is; its absence never suppresses the street address.
    - `address_components` object: The same US components the formatted string is built from. Every field is source-established or absent; nothing is inferred or back-filled.
      - `house_number` string
      - `street` string
      - `unit` string
      - `locality` string
      - `region_code` string
      - `region_name` string
      - `postal_code` string
      - `country_code` string
    - `method` string, required
    - `lat` number, required
    - `lon` number, required
  - `meta` ReverseMeta, required
    - `upstream_ms` number, required
    - `feature_count` number, required
    - `cacheHit` boolean
    - `bbox` unknown[]
      - unknown
    - `query` string, required
    - `mode` 'geocode' | 'reverse', required
  - `geojson` ReverseFeatureCollection, required
    - `type` 'FeatureCollection', required
    - `features` object[], required
      - `type` 'Feature', required
      - `geometry` object, required
        - `type` 'Point', required
        - `coordinates` unknown[], required
          - unknown
      - `properties` object, required
  - `warnings` string[]: Geocoder warnings (`geocoding.warnings`) — present only when the suppress middleware emitted signals on this response.
  - `upstream_error` string, nullable

## Other responses

- `400`: Invalid coordinates or query parameters.
- `429`: Quota exceeded.
- `502`: Upstream geocoder unavailable.

---

[API](https://skmtc.dev/thinair/apis/thinair-geo-api.md) · [All operations](https://skmtc.dev/thinair/apis/thinair-geo-api/llms.txt) · [OpenAPI document](https://skmtc.dev/thinair/apis/thinair-geo-api/revisions/8fac2d5e4b34?raw)
