---
title: "Search places by category or text near a point"
method: GET
path: "/v1/places"
tags: ["Places"]
---

# Search places by category or text near a point

`GET /v1/places`

## Request

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

Category-specific POI search near a point — gas stations, truck stops, restaurants, charging stations, etc. Provide either `query` or center coordinates (or both). For broader discovery use /v1/explore.

## Query parameters

- `location` string: Center point — free-text address or 'lat,lon' string.
- `lat` number: Center latitude (alternative to `location`).
- `lon` number: Center longitude (alternative to `location`).
- `query` string: Free-text place query (alternative to `category`). One of `query` or `category` is required — a bare center (`lat`+`lon`) with neither is rejected with a 400.
- `category` string[]: Structured categories (repeatable / CSV): food, fuel, charging_station, education, health, entertainment, retail, accommodation, nightlife, transport, government, recreation. One of `category` or `query` is required — a bare center (`lat`+`lon`) with neither is rejected with a 400.
- `radius` string: Search radius. Bare numbers are miles unless `units` is set — `radius=30` is 30 miles, `radius=5&units=kilometers` is 5 km; kilometers via `units` or a km suffix ('5km'); aliases mi/km/imperial/metric. A value carrying its own unit suffix ('30mi', '5km') is also accepted and its suffix wins. Default 50 km (about 31 mi); maximum 50 km (up to 31.068 mi). Preferred over `radius_m`.
- `units` 'miles' | 'kilometers': Units for a bare numeric `radius`: miles (default) or kilometers; aliases mi, mile, imperial (miles) and km, kilometer, kilometre, kilometres, metric (kilometers), case-insensitive, echoed as miles|kilometers. An empty `units=` is treated as absent. Ignored when `radius` already carries a unit suffix (a contradicting pair is rejected). Not valid with `radius_m` alone — `radius_m` is always meters, so that pair is rejected rather than silently ignored. On its own (no `radius`) it does not supply a radius — the default 50 km applies — but it selects the display unit of the `units` echo.
- `radius_m` integer: Search radius in meters (0..50000 — i.e. up to 50 km / ~31 mi; 0 means 'not supplied' and applies the default 50 km, as on the MCP tool). Accepted alias; `radius` + `units` is the preferred form. Sending both is only valid when they agree. Do not pair with `units` — `radius_m` is always meters and the pair is rejected.
- `limit` integer: Max results (default 10, clamped 1..50).
- `layers` string: Restrict to: venue, address.

## Response `200`

Places results — items list with optional rich metadata.

- PlacesResponse
  - `warnings` object[]
    - `code` string, required
    - `severity` 'advisory', required
    - `message` string, required
  - `query` string, required
  - `radius` string: Legacy echo — the applied radius as '<n>m'. Present only when the request supplied a radius (any form); absent on the default path. Prefer `radius_km` + `units`.
  - `radius_km` number: Search radius actually applied, in kilometers (the canonical unit) — 50 on the default path. Present on every center-based search, cache hit or miss; absent on the text-only path (no center), where no radius applies.
  - `units` 'miles' | 'kilometers': Display unit for the radius: the request's `units` if sent; else the unit of a suffixed `radius` string; else kilometers for `radius_m`; else miles — the platform default, which also covers a bare numeric `radius` and the no-input path. Same presence rules as `radius_km`.
  - `items` PlacesItem[], required
    - `id` string: Stable public ThinAir id (`ta_place_<key>`). Resolvable via `GET /v1/place`.
    - `name` string
    - `label` string
    - `lat` number
    - `lon` number
    - `layer` string
    - `distance_km` number
    - `website` string
    - `phone` string
    - `hours` string
    - `cuisine` string
    - `brand` string
  - `meta` object, required
    - `upstream_ms` number, required
    - `feature_count` number, required
    - `cacheHit` boolean
  - `upstream_error` string, nullable
  - `raw_upstream_payload` unknown

## Other responses

- `400`: Invalid query parameters.
- `429`: Quota exceeded or rate-limited.

---

[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)
