Geocoding
The Geocoding API converts between addresses and coordinates. It runs on the global OpenStreetMap dataset - continuously updated by millions of contributors - so coverage is worldwide and improves over time without any action on your part.
By default responses are plain JSON with named "lat" and "lon" string fields - no coordinate-order ambiguity. If you prefer GeoJSON (FeatureCollection with geometry.coordinates), add format=geojson to any request. In that case coordinates follow the GeoJSON standard: [longitude, latitude].
X-Api-Key header. Get your key from the dashboard - it's the same key used for all PickPoint APIs.Forward geocoding
Address or name → coordinates. Returns a JSON array of candidates ranked by importance - a score that combines how well-known the place is (derived from Wikipedia article link counts across languages) and how closely it matches the query text. The Eiffel Tower scores ~0.81; a village named Paris in rural Texas scores ~0.25.
In most cases the first result is what you want. For ambiguous queries - "Moscow" matches Russia, Idaho, and several other places - either show the top few candidates or constrain the search with countrycodes.
curl "https://api.pickpoint.io/v2/geocode/forward?q=Eiffel+Tower,+Paris&limit=1" \
-H "X-Api-Key: YOUR_KEY"[
{
"place_id": 5013364969,
"osm_type": "node",
"osm_id": 5013364969,
"lat": "48.8583701",
"lon": "2.2944813",
"class": "tourism",
"type": "attraction",
"place_rank": 30,
"importance": 0.8142,
"addresstype":"attraction",
"name": "Eiffel Tower",
"display_name": "Eiffel Tower, Champ de Mars, Paris, Île-de-France, France",
"address": {
"attraction": "Eiffel Tower",
"road": "Champ de Mars",
"suburb": "7th arrondissement",
"city": "Paris",
"postcode": "75007",
"country": "France",
"country_code":"fr"
},
"boundingbox": ["48.8572","48.8596","2.2933","2.2956"]
}
]Key fields in the response:
lat/lon- coordinates as strings. Parse to float when you need arithmetic.display_name- full human-readable label, ready to show to users.importance- relevance score 0–1. The array is already sorted by this; higher = more likely to be the intended result.place_rank- administrative level: 4 = country, 8 = state, 14 = city, 26 = street, 30 = POI.osm_type+osm_id- stable OSM identifiers. Combine asN123(node),W123(way), orR123(relation) for the Lookup endpoint.address- structured components: road, suburb, city, postcode, country. The POI name appears under its own category key (e.g."attraction": "Eiffel Tower").boundingbox-[min_lat, max_lat, min_lon, max_lon]for the matched feature.
Handling ambiguity
Without constraints, "Paris" returns the French capital first - but it also matches Paris, Texas. "High Street" matches over 5,000 streets in the UK alone. Two parameters fix this:
countrycodes=fr- restrict to specific countries (ISO 3166-1 alpha-2, comma-separated).viewbox+bounded=1- restrict to a geographic bounding box. Pass the user's visible map area.
# Only results strictly inside Paris bounding box
curl "https://api.pickpoint.io/v2/geocode/forward?q=Musée&countrycodes=fr&viewbox=2.25,48.81,2.42,48.91&bounded=1&limit=5" \
-H "X-Api-Key: YOUR_KEY"Reverse geocoding
Coordinates → address. Returns a single JSON object (not an array). The zoom parameter controls how specific the result is: 18 (default) returns a full postal address, 10 returns the city, 3 returns only the country.
curl "https://api.pickpoint.io/v2/geocode/reverse?lat=48.8584&lon=2.2945&zoom=18" \
-H "X-Api-Key: YOUR_KEY"{
"place_id": 5013364969,
"osm_type": "node",
"osm_id": 5013364969,
"lat": "48.8583701",
"lon": "2.2944813",
"display_name": "Eiffel Tower, Champ de Mars, 7th arrondissement, Paris, 75007, France",
"address": {
"attraction": "Eiffel Tower",
"road": "Champ de Mars",
"suburb": "7th arrondissement",
"city": "Paris",
"state": "Île-de-France",
"postcode": "75007",
"country": "France",
"country_code":"fr"
},
"boundingbox": ["48.8572","48.8596","2.2933","2.2956"]
}Lower zoom levels are useful when you want a city or region label regardless of coordinate precision - e.g. labelling GPS tracks on a zoomed-out map. Zoom scale: 3 = country · 8 = county · 10 = city · 14 = suburb · 16 = street · 18 = building.
Address search (autocomplete)
Accepts partial queries and is optimised for low latency - fast enough to call on each keystroke. Returns an array in the same format as forward geocoding. Debounce to ~250 ms on the client and cancel in-flight requests when the query changes to avoid stale responses overwriting fresh ones.
# As the user types "Baker St" in a UK app
curl "https://api.pickpoint.io/v2/address/search?q=Baker+St&countrycodes=gb&limit=5&viewbox=-0.18,51.49,-0.12,51.53" \
-H "X-Api-Key: YOUR_KEY"Place lookup
Fetch full details for a known OSM object by its osm_type and osm_id. The prefix encodes the type: N = node, W = way, R = relation. Pass up to 50 IDs in a single request.
# Fetch details for a known osm_type + osm_id
curl "https://api.pickpoint.io/v2/geocode/lookup?osm_ids=N5013364969" \
-H "X-Api-Key: YOUR_KEY"This avoids repeating a text search when you've already stored the identifiers. Useful for displaying up-to-date place details from a previously saved result.
Language and script support
Add a language BCP 47 tag to get display_name and address fields in a specific language. OSM contains place name translations in 100+ languages, so coverage is generally good worldwide. Non-Latin scripts work in both queries and responses - Arabic, Chinese, Cyrillic, Japanese, Korean. Transliteration also works: "Moskva" finds Moscow, "Köln" and "Cologne" both find the same city.
Response formats
By default the API returns plain JSON. Pass format= to get any Nominatim-compatible output format:
format= | Shape | Coordinates | Notes |
|---|---|---|---|
json (default) | Array of objects | lat, lon strings | Flat structure, easy to use. Named fields, no coordinate-order ambiguity. |
geojson | GeoJSON FeatureCollection | [lon, lat] in geometry.coordinates | Same shape as Address Search output. Use for GeoJSON-native pipelines. |
jsonv2 | Array of objects | lat, lon strings | Extended JSON with category, type, place_rank and additional metadata. |
geocodejson | GeocodeJSON FeatureCollection | [lon, lat] | Open geocoding standard with a structured geocoding object per feature. |
xml | XML document | lat/lon attributes | Nominatim-compatible XML for legacy system integrations. |
Things worth knowing before you ship
- An empty array is not an error.
[]is a valid 200 response - the query simply didn't match. Prompt the user to refine their input rather than silently failing. - Specific queries win. "221B Baker Street, London, UK" is vastly more reliable than "baker street". Include city and country whenever you know them.
latandlonare strings. Parse them withparseFloat()or equivalent before doing any arithmetic or passing them to a map library.- Cache aggressively. Geocoding output for a given address is stable. Store coordinates in your database and treat geocoding as a one-time normalisation step.
- Never expose your key in the browser. Proxy all calls through your backend.
- Postcodes geocode too. Pass a postcode alone - "SW1A 2AA", "10001" - to get a centroid for that postal district.