Geocoding SDKs
Four typed client packages wrap the v2 geocoder so you don't hand-roll the autocomplete → retrieve loop, session billing, or error parsing yourself:
| language | package | source |
|---|---|---|
| TypeScript / JavaScript | @mapmetrics/geocoder | NPM/ |
| Dart / Flutter | mapatlas_geocoder | Flutter/ |
| Swift (iOS / macOS) | MapAtlasGeocoder | Swift/ |
| Kotlin (Android / JVM) | mapatlas-geocoder | Android/ |
Not published yet
None of these packages are on npm, pub.dev, Swift Package Index, or Maven Central yet. The install instructions on each language page show the form that will work once they ship (or, for Swift and Kotlin, the git/composite form that works today). Don't expect npm install/dart pub add to resolve against a public registry right now.
Why use an SDK instead of calling the gateway directly
The raw HTTP API (documented under Geocoder v2) has a handful of sharp edges that are easy to get wrong once and then debug for an hour, because most of them fail silently — HTTP 200 with an empty or subtly wrong result, not an error:
- Sessions are billed, not requests. Autocomplete is billed per search session. Forgetting to carry a stable
session_tokenacross keystrokes doesn't error — it just charges roughly 5x more, silently. Every SDK here manages the token for you: one session per search box interaction, automatically. - Debounce is your job otherwise. Without it, a fast typist fires a request per keystroke. All four SDKs debounce
suggest()calls (150ms by default). - Retrieval is keyed on
ord, notid. Retrieving byid404s on every layer. Every SDK takes the suggestion object straight fromsuggest()and readsordoff it for you — there's no id to get wrong. - Some suggestions can't be retrieved at all. The gateway injects locality rows (e.g. two of the fifteen results for
q=Amsterdam) that carry noord. Every SDK exposesisRetrievableon a suggestion so you can filter or disable those rows before the user taps one. - Batch retrieval has one specific encoding.
/v2/retrieve-batch/accepts exactly one URL-encoded JSONitemsparameter — repeatedord=/ords=/ids=params silently returncount: 0. The SDKs build that payload for you from an array of suggestion objects. - Errors come back as HTTP status + a code string, not an exception hierarchy. Each SDK turns them into typed errors/exceptions — a distinct type per failure (
ScopeError,OriginRequiredError,QuotaExceededError, …) — so you cancatch/switchon what actually went wrong instead of parsingerror.statusanderror.codeyourself. - Response shape is easy to get wrong. Forward/reverse geocode return a different, flat shape unless you pass
format=pelias. Every SDK forces the GeoJSON envelope on every search/reverse call — you always get aFeatureCollection.
None of this is exotic — it's mechanical, and it's exactly the kind of thing worth doing once, in a typed client, instead of every app re-deriving it from the endpoint docs.
What's the same across all four
- A
MapAtlasclient constructed with an API key (or agetTokencallback, for rotating credentials). client.geocoding.createSession()→session.suggest(query)→session.retrieve(suggestion)/session.retrieveBatch(suggestions).- A reactive controller for the common "search box" UI shape — see the per-language page for its name and idiom (React hook, Dart
Stream, Swift@Observable, KotlinStateFlow). - One-shot
search()/reverse()calls for when there's no user typing to debounce. - A free
tier: 'osm'(naming varies per language) backed by theosm-geocodescope, and a dedicated self-hosted constructor for MapMetrics/atlas-osm-geocoder — see each page's "OSM tier" section. - Typed errors/exceptions for every documented gateway failure mode — see API Keys & Security for what each one means.
What differs
- Routing, matrix, and isochrones are implemented in the TypeScript and Dart packages only. Swift and Kotlin are geocoding-only for now — see their pages for exactly what's covered.
- Native platforms (Swift, Kotlin, Flutter) need an unrestricted API key. Origin restriction only works for browsers — see Choosing a key for a native app below.
Choosing a key for native apps
Origin restriction is enforced by checking the browser's Origin header — native apps, and any server-side code, send no Origin header at all, so an origin-restricted key can never satisfy that check. This is the single most common integration error a mobile developer hits with these SDKs: reuse a web key in a Flutter/Swift/Kotlin app, and every request throws an origin-required error.
Use an unrestricted key for the Flutter, Swift, and Kotlin SDKs. Origin restriction is still the right call for a browser key used with the TypeScript SDK. See API Keys & Security for the full scope and origin model, and Sessions for the billing model shared by all four SDKs.
Next
- Sessions & billing — the model every SDK is built around.
- JavaScript / TypeScript
- Flutter
- Swift
- Kotlin