Places API

# API Reference

Reference for the Open Places API search and category endpoints, query parameters, responses, warnings, headers, and OpenAPI contract.

Operation

## `GET /v1/places`

Searches place names and scoped addresses near a latitude/longitude point, or lists a category in an area when `category` is supplied. The source contract has a readable preview at [OpenAPI YAML](/docs/openapi). 

GET `https://api.openplacesapi.com/v1/places` 

Authenticated public search endpoint for server-side integrations.

Query parameters

## Inputs accepted by the search endpoint.

| Name            | Type    | Required | Details                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| --------------- | ------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| q               | string  | Usually  | Search text, up to 128 characters after normalization, with at least 3 searchable letters or numbers (2 for a contiguous CJK query such as 咖啡). Required unless category is supplied. In the default mode=all, a q that names a kind of place also searches that category; see [category words in q](https://openplacesapi.com/docs/reference#category-words).                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| category        | string  | No       | Exact Overture category slug; look slugs up with [GET /v1/categories](https://openplacesapi.com/docs/reference#categories). Matches primary and alternate categories plus hierarchy ancestors of the primary category, so a parent such as food\_and\_drink also matches its subcategories. Enables category browse and makes qoptional. Reviewed legacy aliases resolve to the current slug in meta.category, with a category\_alias warning and resolved\_category. Legacy parent aliases such as travel → travel\_service, automotive → automotive\_service, and attractions\_and\_activities → arts\_and\_entertainment can match fewer categories than the old filter; check category\_alias and choose a current slug for the scope you need. An unknown slug returns an unknown\_category warning with suggestions. |
| lat             | number  | Yes      | Latitude from \-90 to 90.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| lon             | number  | Yes      | Longitude from \-180 to 180.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| radius\_mi      | number  | No       | Must be greater than 0. Defaults to 25; maximum is 50.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| mode            | enum    | No       | all, name, or address. Defaults to all, which matches names and addresses and reads category words in q. name matches place names literally, without category interpretation. address requires at least 4 searchable letters or numbers.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| limit           | integer | No       | Minimum 1. Defaults to 10; text search maximum is 20, category browse maximum is 50.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| offset          | integer | No       | Category-browse pagination offset. offset + limit can be at most 1000, so category browse reaches the first 1,000 places in sort order. Use meta.next\_offset for the next page; it is null on the last page. Each page is one billed search.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| min\_confidence | number  | No       | Minimum confidence from 0 to 1. Omit for no confidence filter.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| sort            | enum    | No       | relevance (default) or distance. distance returns the same matches nearest first, and category pages from offset walk outward from lat/lon. Add min\_confidence so low-confidence records don't fill the nearest results.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| layer\_preset   | string  | No       | Account-owned preset slug. Mutually exclusive with layers.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| layers          | string  | No       | Explicit ordered selection such as base,open,account:client-a. At most 10 account layers.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |

Category words in q

## A plain `q=pharmacy` searches the pharmacy category too.

In the default `mode=all`, when `category` is not supplied and `q` names a kind of place, the search also covers the matching categories. Top-level groups such as `shopping` or `food_and_drink` are never read from `q`. 

A whole-`q` category phrase such as `pharmacy`, `chemist`, `fire station`, or `pizza near me` lists places in the category first (primary-category and subcategory matches before alternate-category matches; within each, confidence bands of at least `0.9`, at least `0.6` but below `0.9`, then below `0.6` (including missing confidence), nearest first within each band), then other places whose name matches `q`. Address-only matches are dropped. A category phrase plus other words, such as `boots pharmacy`, keeps full-text matches first, then adds places in the category whose names match the other words. 

`meta.interpreted_as` reports the reading (`type`, `categories`, `text`, and a `message`), or is `null` when `q` was searched as plain text. Each result can carry `match`: `name`, `address`, `category`, or `name_and_category`. Use `mode=name` to match a literal name, and an explicit `category` with `offset` to page through a category, up to the first 1,000 places per query area. 

If a search with `q` finds nothing, it is retried once with a relaxed `q`: trailing legal suffixes such as `LLC` or `GmbH`, parenthesized asides, and the words `and`, `the`, and `of` are dropped. Relaxed results must contain the remaining words as whole words of the place name and carry a `query_relaxed` warning. If that still finds nothing, `q` may be read as the closest category by meaning (for example `tienda de computadoras` as `computer_store`): the results are nearby places in that category, with `match: category`and a `category_inferred` warning. 

Responses

## Success, quota, and error responses are explicit.

| Status        | Response                                                                      |
| ------------- | ----------------------------------------------------------------------------- |
| 200           | Search completed, including zero-result searches.                             |
| 400           | Validation error; error.details lists each rejected field.                    |
| 401, 403      | Authentication or layer authorization failure.                                |
| 402, 429, 503 | Quota exhausted, per-account rate limit exceeded, or temporarily unavailable. |

Only requests with an explicit `category` can page. Follow `meta.next_offset`; each page is one billed search. It can be `null` because the next page would cross the 1,000-place window even when more places match; check `pagination_limit_reached` in `meta.warnings`. 

Node.jscategory paging

```
const apiKey = process.env.OPA_KEY;
if (!apiKey) throw new Error("OPA_KEY is required");
let offset = 0;
do {
  const url = new URL("https://api.openplacesapi.com/v1/places");
  url.search = new URLSearchParams({
    category: "cafe", lat: "40.7128", lon: "-74.0060",
    limit: "50", offset: String(offset),
  }).toString();
  const response = await fetch(url, {
    headers: { Authorization: `Bearer ${apiKey}` },
  });
  if (!response.ok) throw new Error(`Search failed: ${response.status}`);
  const body = await response.json();
  console.log(body.results);
  offset = body.meta.next_offset;
} while (offset !== null);
```

The rate limit is 120 requests per minute per account for everyone, with at most 8 searches in flight per account at once. Purchases add searches and extend the whole balance for 12 months. `X-Quota-Limit` describes the current balance allocation; `X-Quota-Remaining` is the number left. There is no reset header. Every error body includes a `docs_url` linking to its entry on the [errors page](/docs/errors#error-codes). 

JSON SearchResponse 

```
{
  "results": [
    {
      "place_id": "overture:08f2c...",
      "name": "Devocion",
      "lat": 40.688838,
      "lon": -73.979914,
      "distance_mi": 2.15,
      "category": "cafe",
      "categories": ["cafe", "coffee_shop"],
      "category_hierarchy": ["food_and_drink", "casual_eatery", "cafe"],
      "address": {
        "locality": "Brooklyn",
        "country_code": "US"
      },
      "phone": "+17185551212",
      "website": "https://www.devocion.com",
      "confidence": 0.92,
      "operating_status": "operational",
      "match": "category"
    }
  ],
  "meta": {
    "request_id": "00000000-0000-4000-8000-000000000000",
    "data_source": "overture",
    "data_release": "2026-10-21.0",
    "data_releases": ["2026-10-21.0"],
    "q": "coffee",
    "category": null,
    "min_confidence": 0.85,
    "sort": "relevance",
    "mode": "all",
    "lat": 40.7128,
    "lon": -74.006,
    "radius_mi": 25,
    "limit": 10,
    "offset": 0,
    "next_offset": null,
    "interpreted_as": {
      "type": "category",
      "categories": ["coffee_shop", "cafe"],
      "text": null,
      "message": "Read \"coffee\" as the category coffee_shop (also cafe): places in that category come first, then other name matches. Use mode=name to match names only, or category=coffee_shop with offset to page through every match."
    },
    "warnings": [],
    "layer_selection": {
      "source": "default",
      "preset": null,
      "layers": [{ "type": "overture_base" }, { "type": "open" }]
    }
  }
}
```

Warnings

## Read `meta.warnings` before giving up.

Successful responses can carry warnings. On an empty first page, `unknown_category` lists the closest known categories in `suggestions`, and `no_results_within_radius` reports `nearest_match_distance_mi` and a `nearest_match` object (public `id`, `name`, `distance_mi`, and `locality` and `country` when available) when a match is found within 100 miles. That place stays outside `results`, with a message naming the `radius_mi` to retry with. `query_relaxed` means `q` had no exact matches and the results are for the relaxed text named in the message. `category_inferred` means nothing matched by name, so the results are nearby places in the closest category by meaning. `pagination_limit_reached` means more places match than a category browse can page through, so `next_offset` is `null` before the end of the results. See [search warnings](/docs/errors#search-warnings) for every code. 

| Warning         | Meaning and client action                                                                                                                                                                                                                           |
| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| category\_alias | A reviewed legacy category was resolved to resolved\_category, also returned in meta.category. This warning can appear on any successful page. Legacy parent aliases can narrow the old filter; check the resolved slug against the scope you need. |

Categories

## `GET /v1/categories`

Lists valid `category` values from the Overture category taxonomy, including parent groups. It is public, needs no API key, does not count against quota, and is cacheable for an hour. Without `q` it returns every category alphabetically; with `q` (1 to 64 characters) it returns the best matches, 20 by default. `limit` accepts `1` to `100`. Unknown parameters return `validation_error`. 

GET `https://api.openplacesapi.com/v1/categories` 

Category lookup for building `category` requests.

JSON CategoryListResponse 

```
curl "https://api.openplacesapi.com/v1/categories?q=coffee&limit=3"
```

```
{
  "categories": [
    {
      "category": "coffee_shop",
      "label": "Coffee shop",
      "parent": "non_alcoholic_beverage_venue",
      "hierarchy": [
        "food_and_drink",
        "non_alcoholic_beverage_venue",
        "coffee_shop"
      ]
    },
    {
      "category": "coffee_roastery",
      "label": "Coffee roastery",
      "parent": "coffee_shop",
      "hierarchy": [
        "food_and_drink",
        "non_alcoholic_beverage_venue",
        "coffee_shop",
        "coffee_roastery"
      ]
    },
    {
      "category": "coffee_and_tea_supplies",
      "label": "Coffee and tea supplies",
      "parent": "food_and_beverage_store",
      "hierarchy": [
        "shopping",
        "food_and_beverage_store",
        "coffee_and_tea_supplies"
      ]
    }
  ],
  "meta": {
    "request_id": "00000000-0000-4000-8000-000000000000",
    "q": "coffee",
    "count": 3,
    "total": 2201
  }
}
```

[ **Preview OpenAPI YAML** Review the source contract visually before downloading the YAML file. ](/docs/openapi) [ **Error details** Review machine-readable codes, quota headers, and retry metadata. ](/docs/errors)
