Places API
Places API
On this page
Quickstart
Search places near a coordinate.
Open Places API has one public search endpoint: GET /v1/places. Send the API key from your
backend, include a location scope, and keep browser frontends away from the secret. Use q for text
search, or use category to list places in a category in an area, up to the first 1,000 places per
query area.
- Create an account with Google or GitHub.
- Create an API key on the dashboard's Overview page. Save it now; it is shown once.
- Set it in your server's environment:
export OPA_KEY="your_api_key".
See the authentication guide for key setup. Building an agent? Connect over MCP instead of writing REST calls.
curl -G "https://api.openplacesapi.com/v1/places" \
--data-urlencode "q=coffee" \
--data-urlencode "lat=40.7128" \
--data-urlencode "lon=-74.0060" \
--data-urlencode "radius_mi=25" \
--data-urlencode "limit=10" \
--data-urlencode "min_confidence=0.85" \
-H "Authorization: Bearer $OPA_KEY" A successful request returns HTTP 200 with a results array (which can be empty) and meta describing the search.
curl -G "https://api.openplacesapi.com/v1/places" \
--data-urlencode "category=cafe" \
--data-urlencode "lat=40.7128" \
--data-urlencode "lon=-74.0060" \
--data-urlencode "radius_mi=25" \
--data-urlencode "limit=50" \
--data-urlencode "offset=0" \
-H "Authorization: Bearer $OPA_KEY" Endpoint
One route, scoped by radius.
/v1/places Returns Overture-backed place results, optionally merged with community and account-owned layers.
| Parameter | Required | Use |
|---|---|---|
q | Usually |
Search text. Required unless category is supplied. A q that names a kind of
place, such as pharmacy, also searches that category; see
category words in q.
|
category | No | Exact Overture category string such as cafe. When supplied, q becomes optional. |
lat, lon | Yes | Latitude and longitude for the search center. |
radius_mi | No | Search radius in miles. Defaults to 25; maximum is 50. |
mode | No |
Search mode: all, name, or address. Defaults to all.
Use name to match place names literally, without reading category words in q.
|
limit | No | Number of results to return. Defaults to 10; text search max 20, category browse max 50. |
offset | No | Category-browse pagination offset. offset + limit can be at most 1000; follow meta.next_offset until it is null. Each page counts as one search. |
min_confidence | No | Minimum Overture confidence score from 0 to 1. No default filter is applied. |
sort | No | relevance (default) or distance, which returns the same matches nearest first. |
layers | No | Explicit ordered layer stack, for example base,open,account:client-a. |
layer_preset | No | Saved account preset. Mutually exclusive with layers. |
Server examples
Keep API keys on your backend.
The Python example needs requests: install it with pip install requests.
const apiKey = process.env.OPA_KEY;
if (!apiKey) throw new Error("OPA_KEY is required");
const url = new URL("https://api.openplacesapi.com/v1/places");
url.search = new URLSearchParams({
q: "ramen",
lat: "35.6762",
lon: "139.6503",
radius_mi: "25",
mode: "all",
min_confidence: "0.85",
}).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(); import os
import requests
response = requests.get(
"https://api.openplacesapi.com/v1/places",
params={
"q": "coffee",
"lat": 40.7128,
"lon": -74.0060,
"radius_mi": 25,
"limit": 10,
"min_confidence": 0.85,
},
headers={"Authorization": f"Bearer {os.environ['OPA_KEY']}"},
timeout=10,
)
response.raise_for_status()
data = response.json() Next steps