MODULE

Geocoding

geocoding AVAILABLE

Geocoding turns a written address into a coordinate, and a coordinate back into an address. It is the single geocoding abstraction for the business: every Mesh service that needs coordinates goes through it, so no caller talks to a geocoding vendor directly. Every answer comes back with a verdict on how much to trust it, because a street-level match on a query that named a house number is not the same thing as finding the door.

What it does

  • Forward geocoding. An address in, a WGS-84 coordinate out.
  • Reverse geocoding. A coordinate in, a structured address out.
  • Bounded batches of either, up to 100 items in one round trip — the common case when a set of stops all need coordinates at once.
  • A quality verdict on every answer, so you can tell a confirmed front door from an approximation that happens to be in the right suburb.
  • A shared cache, so an address your account has already resolved costs nothing to resolve again.
This module costs real money per lookup

Unlike most of the platform, every uncached lookup is a paid call to an external vendor. That is precisely why geocoding is a module you switch on rather than something every account silently consumes. Cache hits are free; it is the misses that bill.

How it works

Branch on quality, never on confidence alone

This is the single most important thing on this page. Every result carries both a confidence number and a quality verdict. Confidence describes how tightly the returned point reflects whatever was matched — it is not a correctness score, and it is not safe to threshold on. A measured street-level result, one that never resolved the house number at all, scored 0.9. No confidence cutoff separates that from a correct answer.

The quality field is the service’s own verdict, combining confidence with what kind of thing was actually matched:

QualityWhat it meansWhat to do
acceptedPremise-level match, high confidence.Use it.
uncertainPremise-level, but middling confidence or a suspiciously wide bounding box.Usable; flag for review.
rejectedStreet- or area-level, or no usable match. The coordinate may be hundreds of metres out.Do not route a driver to it.
ambiguousThe address matched several equally precise places far apart.Do not route to it; re-ask with a locality or postcode.

On an ambiguous result the service deliberately refuses to pick a winner. “100 Queen Street” with no city matches Melbourne, Brisbane and Sydney, all at maximum confidence — choosing one at random would be guessing and calling it an answer. Instead you get up to four alternatives so you can show a chooser or re-query with the locality that was meant.

Structured fields beat a single string

You can pass a freeform address, but supplying addressLine1, locality, region and postcode separately is better: it stops the vendor’s parser guessing where the locality ends and the region begins. If you already hold the fields separately, do not concatenate them just to send one string.

Supplying a two-letter countryCode narrows the search space and materially improves accuracy. Omit it when the country is genuinely unknown — a single-line address from an uploaded file, or a job spanning several countries — and expect more results to come back rejected, because the search then runs globally. Note that it must be exactly two letters: AUS and Australia are both rejected as malformed.

A location bias is a hint, not a filter

When two addresses share a street name and number and you have no postcode to tell them apart, a rough known position — a depot, the last stop, the vehicle — picks the right one. Two cautions. The bias is rounded to roughly a kilometre before it reaches the vendor, so sub-kilometre precision is neither preserved nor useful. More importantly, a bias weakens ambiguity detection: the far-apart rivals that would have produced an ambiguous verdict may never be returned at all. Supplying a bias means trusting your hint over this service’s refusal to guess.

Fuzzy matching is capped on purpose

Opting in to allowFuzzy accepts a match the vendor found only by loosening the query — a relaxed spelling, a dropped token. Such a match is capped at uncertain and can never be accepted, no matter how well it scores. The reason is measured, not theoretical: against the live vendor, a correct relaxed match scored 0.943 and a match 100 km from the address asked for scored 0.824. No threshold separates those. Turn it on when you want volume out of messy data and will review the output; leave it off when a wrong coordinate is worse than no coordinate.

Batches fail per item, and that is normal

A batch request returns 200 even when some items failed. Each item carries its own result or its own error, keyed by its position in the request, because the answers already obtained were paid for and throwing them away to signal one failure would be wasteful. Check every item’s error and quality individually — a 200 does not mean every item resolved.

Batches are bounded, not queued. There is no submit-then-poll contract here: a request over the item limit is rejected rather than accepted and worked through later. For tens of thousands of addresses, page against the endpoint. Within one batch, duplicate addresses collapse to a single vendor call.

One abstraction, so the vendor can change

Callers never talk to a geocoding vendor directly. That indirection buys three things: the vendor can be replaced, or split by country, without any caller changing; a shared read-through cache means a repeat address costs nothing; and the vendor’s account-wide rate limit is absorbed here instead of surfacing to everyone.

That last point has a visible consequence. When the shared provider budget is exhausted, you get a 503, never a 429 — the limit is account-wide and is not the individual caller’s fault. Retry after a short backoff.

A result’s provider field tells you where the answer came from; cache means no vendor call was made and nothing was billed. In steady state most answers are cache hits, so do not read the vendor distribution in your results as traffic share.

One setting

Try another provider for ambiguous addresses (escalateAmbiguous, off by default). When an address matches several places, this asks the next provider rather than stopping and reporting it as ambiguous. Your answer is never worse — if nobody does better you still get the ambiguous result and its alternatives — but it costs an extra lookup each time it fires. Leave it off unless your addresses often match businesses named after the text you searched for.

Attribution

Results derive from OpenStreetMap and are ODbL-licensed. Attribution is obligatory on any surface that displays them.

Permissions

PermissionWhat it allowsNeeded
geocoding.executePerform forward, reverse and batch lookups. This is the only permission the module defines — there is nothing to read back and nothing to write, because a geocode is a question rather than a stored resource.Required
settings.writeChange the module’s escalateAmbiguous setting for the account.Required to configure
stops.writeWrite a resolved coordinate back onto a stop.Recommended
A token without the permission still authenticates

A credential that is valid but lacks geocoding.execute gets a 403, not a 401. If lookups start failing after a credential change, check the permission before suspecting the token itself.

API reference

One contract, covering forward and reverse lookups, individually and in batches.

ServiceWhat it coversReferenceContract
geocoding-apiForward, reverse and bounded batch geocoding.OpenAPI descriptionopenapi.json
These links follow the environment you are reading

Each openapi.json is the generated OpenAPI 3.1 contract, served by the service itself — it is never hand-edited, so it cannot drift from the running API. The OpenAPI description link opens the same contract as a browsable reference. Both resolve to the environment these docs are served from, so a page read on the test site links to the test contract.

Events

This module raises no events.

Geocoding is a request-and-response surface: you ask a question and get an answer in the same call. There is nothing asynchronous to subscribe to, and no webhook to register.

Where geocoding shows up indirectly is on the resources that store a resolved coordinate — a stop whose position is filled in raises the ordinary stop.updated event, not a geocoding-specific one.

The modules that do put events on the stream are listed with their event types in the event catalog; the envelope they arrive in and the delivery guarantees behind them are in Events & webhooks.