OSM Tier Endpoints
The OSM tier is a free, OpenStreetMap-only geocoder reached through the osm-geocode scope. It is a different engine from the v2 geocoder, with a different response shape and a different cost model, and the differences are easy to trip over when porting code between the two.
| v2 tier | OSM tier | |
|---|---|---|
| Endpoints | /v2/autocomplete/, /v2/retrieve/, … | /osm-autocomplete/, /osm-geocode/, /osm-reverse/ |
| Sessions | yes — billed per session | none |
| Coordinates in suggestions | no — must call /v2/retrieve/ | yes, inline |
| Billing | per session | per request, rate-limited |
Rate limit: 10,000 requests per key per day, plus a global monthly cap. Exhausting it returns a quota error carrying a self-host URL — the engine is open source at MapMetrics/atlas-osm-geocoder.
No retrieve step
The single biggest structural difference: OSM-tier suggestions already carry coordinates. Every row from /osm-autocomplete/ has a center and a geometry, so there is no suggest → retrieve round trip and no session token to thread through.
curl "https://gateway.mapmetrics-atlas.net/osm-autocomplete/?q=amsterdam&token=YOUR_API_KEY"{
"type": "FeatureCollection",
"query": "amsterdam",
"query_ms": 12,
"results": [
{
"id": "poi.0",
"type": "Feature",
"place_type": ["poi"],
"relevance": 1.0,
"text": "Amsterdam Museum",
"place_name": "Amsterdam Museum, NL",
"center": [4.891, 52.3704],
"geometry": { "type": "Point", "coordinates": [4.891, 52.3704] },
"context": [{ "id": "country.nl", "text": "NL", "short_code": "nl" }],
"properties": { "layer": "poi", "popularity": 7043 },
"matching_text": "Amsterdam",
"matching_place_name": "Amsterdam"
}
],
"attribution": "© OpenStreetMap contributors, MapMetrics Atlas"
}Porting v2 code here means deleting the retrieve call, not rewriting it. In the geocoding SDKs this shows up as createSession() throwing on the OSM tier, with autocomplete() available in its place.
results vs features — the key differs by endpoint
The rows are not always under the same key
/osm-autocomplete/ returns its rows under results. /osm-geocode/ returns them under features. Some worker builds emit both keys with the same content. Reading only one of them yields an empty list against the other endpoint — with no error, because HTTP 200 and a well-formed envelope came back either way.
Read defensively:
const rows = body.results ?? body.features ?? [];Both envelopes otherwise agree: type: "FeatureCollection", a query echo, query_ms, and an attribution string.
id is not unique here either
Exactly as on v2, id collides within a single response — and on this tier it collides across genuinely different places. q=amsterdam currently returns "id": "poi.0" for both Amsterdam Museum and Amsterdam Oosterpark Inn.
Do not use id as a list key. It is opaque debug metadata, not a primary key.
Sub-paths are ignored, not routed
/osm-geocode/anything/ returns the same free-text results
The gateway matches on the /osm-geocode/ prefix and ignores whatever follows. /osm-geocode/, /osm-geocode/category/ and /osm-geocode/banana/ all return HTTP 200 with byte-identical free-text results.
There is no sub-path API here. A URL like /osm-geocode/category/ looks like a category endpoint and behaves like an ordinary search, so a typo or an invented path silently returns plausible, wrong data instead of a 404. Only the paths listed on this page mean anything.
For real category filtering, see Category Search on the v2 tier.
Self-hosting
A self-hosted atlas-osm-geocoder instance uses different paths and no token: /search, /reverse, /autocomplete, with no /osm- prefix and no token parameter. Every SDK exposes this as a distinct selfHosted() constructor that never sends a credential.
See Also
- Category Search (v2) — the only endpoint that filters by category.
- Autocomplete (v2) — the session-billed tier.
- Geocoding SDKs — all four wrap both tiers behind one API.