API reference
A reference for the gateway data APIs. The pages before this one explain each service; this one is the table you keep open while you write the call.
Maps, the catalog, geocoding, routing and BYOD have a full entry below with every parameter. The services Places, Transit, Elevation, Road events and the routing expansion, are listed with their purpose and their parameters in Other APIs and documented in full on their own pages.
The machine-readable version is /openapi.json
(OpenAPI 3.1), discoverable from
/.well-known/api-catalog. Generate a
client from that rather than transcribing this page.
Conventions
Most routes are a GET with query parameters and no request body. The exceptions are
POST /byod, DELETE /byod/{id}, POST /geocode/batch, POST /matrix, POST /match,
POST /optimized-route, POST /optimize and its GMPRO paths, POST /feedback,
POST /places/{id}/feedback, and the body forms of
POST /route and POST /isochrone, which exist only because avoid_areas is a polygon and a
polygon cannot ride a query string. Responses are JSON except tiles (Mapbox Vector Tile bytes),
terrain (WebP or PNG), glyphs and sprites.
Coordinates are longitude,latitude, in that order, in WGS84 degrees. Bounding boxes are
minlng,minlat,maxlng,maxlat.
One point is near=lng,lat. That spelling works on /places/nearby, /geocode/nearby,
/transit/stops, /incidents, /elevation, /geocode/reverse and /isochrone, and in the
body of POST /isochrone. /route names its two ends from and to, each a lng,lat pair. In JSON request bodies, coordinate pairs are
arrays, so POST /isochrone uses "near": [lng, lat].
Two HTTP exceptions use separate names: /timezone takes lat and lon, while
/identify takes at=lng,lat. The SDK still accepts [lng, lat] pairs for both.
Authentication is one key in any of four places, checked in this order:
| Form | When |
|---|---|
Authorization: Bearer um_live_… | Server-side calls. The normal form. |
X-API-Key: um_live_… | Clients that reserve Authorization for something else. |
X-Goog-Api-Key: um_live_… | Google REST clients, such as a Route Optimization client pointed at the GMPRO paths below. |
?key=um_live_… | Used in generated style URLs for tiles and assets. These endpoints also accept either header form. Excluded from shared tile and asset cache identities. |
On protected data paths, auth runs before routing, so an unauthenticated request returns 401,
including a path that does not exist. Discovery documents and /coverage.json are public exceptions. See Authentication.
Add-ons gate the industry layers and grammars: legal-land, energy, agriculture,
remote, mining. A key without the one a request needs gets 403 with the add-on
named. See Layers for how to buy one.
Maps
GET /styles/{style}.json
A MapLibre style document. The one URL most applications need.
| Parameter | In | Notes |
|---|---|---|
style | path, required | base, muted, outdoor, blueprint, blush, orchid, canopy, lagoon, tropic, sunset, bold, pastel, atlas, swiss, winter. An optional -light or -dark suffix sets the mode inline. |
mode | query | light or dark. An unrecognised value serves light, including when the path named dark. |
lang | query | BCP 47 primary subtag. A full tag uses its primary subtag, so fr-CA is fr. Native labels support ja, ko, zh-Hans, and zh-Hant. Chinese region tags resolve to their script (zh-TW → zh-Hant); explicit script wins. An unsupported code resolves to en and is not a 400. With no lang, the gateway reads Accept-Language, then en. |
theme | query | A ut1. code from unmap.dev/create. A theme replaces the cartography, so it wins over the style in the path. |
overlays | query | Comma-separated catalog layer ids, or byod:<id>. Overrides profile. |
terrain | query | on draws the style on 3D terrain (adds unmap_terrain and a top-level terrain); off or absent leaves it flat. Anything else is a 400; no terrain configured is a 503. |
exaggeration | query | Relief scale for terrain=on, 0.1-5, default 1. A 400 without terrain=on. |
profile | query | energy, agriculture, remote or mining. A composition preset, not a style. |
Returns application/json: a complete style with sources, layers, glyphs,
sprite and metadata. Cache-Control: private, no-store: the document contains the API
key and the tile template for this deploy.
Also 400 invalid_theme for a theme code that does not decode, with a detail array · 400 bad_request for an unknown overlay id or profile · 404 the style name does not resolve · 503
plain text basemap release is misconfigured when the active release is not an eight-digit id
or its object is missing, with Cache-Control: private, no-store. The previous archive is not served.
GET /tiles/{z}/{x}/{y}
The worldwide basemap, as Mapbox Vector Tile bytes. Range-read from object storage, never through compute, which is why it is the fastest thing here.
z, x, y are path integers. Authentication is required; use Authorization: Bearer <key>,
X-API-Key: <key>, or ?key=<key>. Style-generated URLs use the query form so MapLibre can
fetch tiles and assets automatically. Direct callers can use either header.
Returns application/x-protobuf.
Also 204 the request is inside the archive but there is no tile there. That response is not written to the Worker cache · 400
plain text invalid tile coordinates for a non-integer, or for a column outside 0 .. 2^z-1 · 503 plain text
basemap release is misconfigured when the active release is not an eight-digit id or its
object is missing, Cache-Control: private, no-store, and the previous archive is not served.
GET /tiles/{release}/{z}/{x}/{y}
The same tile, pinned to an 8-digit basemap release. The undated path follows whichever
archive is active. The default is the September 22, 2026 planet release. An eight-digit id that was never copied
is plain text 404 basemap release not found with Cache-Control: private, no-store. An
id that is not eight digits is that same body without the cache header. If the active archive
was switched to a release that is not on the server, the style and the undated path answer
503 basemap release is misconfigured, also private, no-store, and do not serve the
Canada extract. Retrying does not restore it.
Returns application/x-protobuf. Also 204 no tile, not written to the Worker cache · 400 plain text invalid tile coordinates for a non-integer, or for a column outside 0 .. 2^z-1.
GET /terrain/{version}/{z}/{x}/{y}
Terrarium/512 relief, z0–12. /terrain/6/{z}/{x}/{y}.webp serves global
Mapterhorn. /terrain/4/{z}/{x}/{y}.png serves Canadian MRDEM.
/coverage.json reports the active release. Versioned URLs
identify their own archive; unknown releases or mismatched suffixes return JSON 404 not_found.
XYZ outside the tile grid returns plain-text 400 invalid tile coordinates.
Returns image/webp or image/png, matching the representation. Also 204 no data,
not cached · 404 terrain archive not configured · 503 unavailable
selected release, without automatic fallback · 502 tile read failure.
GET /contours/{version}/{z}/{x}/{y}
Canadian contour lines from MRDEM-30, z9 to z13, with no 0 m line. The version is
currently 4, cached public, max-age=86400. A version that is not a small integer is plain text 400
invalid tile coordinates.
Returns application/x-protobuf. Also 204 no tile inside a configured archive, not written to the Worker cache · 404 JSON not_found, contour archive not configured.
GET /glyphs/{version}/{fontstack}/{range}.pbf
Font glyphs, for example Noto Sans Regular/0-255.pbf. Includes the faces that draw
syllabics. The version is currently 2. A successful response is cached
public, max-age=31536000, immutable. Not metered.
Returns application/x-protobuf. Also 400 plain text invalid fontstack, invalid range, or invalid asset version · 404 plain text not found when that object is absent, without that cache header.
GET /sprite/{version}/{file}
Sprite sheet, .json or .png, with @2x variants. The sheets are light, dark,
muted-light, and muted-dark. The version is currently 2, cached
public, max-age=31536000, immutable. Not metered.
Returns application/json or image/png. Also 400 plain text invalid sprite, or invalid asset version · 404 plain text not found, without that cache header.
Catalog and data
GET /layers
The whole catalog. Raw storage object keys are never exposed; incomplete coverage always is.
Returns application/json, an array of:
{
"id": "energy.wells",
"display_name": { "en": "Wells", "fr": "Puits" },
"namespace": "energy",
"source": "…",
"source_url": "…",
"licence": "…",
"attribution": "…",
"coverage": "…",
"resolution": "…",
"updated_at": "2026-09-10",
"source_updated_at": "…",
"ingestion_version": "1",
"schema_version": "1",
"freshness_policy": "…",
"known_gaps": "…",
"addon": "energy",
"archives": [{ "id": "default", "minzoom": 4, "maxzoom": 12 }],
"source_layer": "wells"
}An archive holding more than one vector layer also carries source_layers, the full list. The
survey grids use it: survey.dls stacks sixteen levels in one file and survey.nts four,
each with its own zoom range, so a client can add exactly the level it wants as its own map
layer. See Layers.
Read known_gaps before you promise coverage to a user. It is written to be accurate
rather than flattering: several layers cover one province, not the country.
GET /layers/{id}
One catalog row, same shape. Also 404 JSON not_found unknown layer.
GET /layers/{id}/{z}/{x}/{y}
Overlay tiles for one catalog layer. ?key= is required.
Returns application/x-protobuf.
Also 204 outside the layer's zoom band, or no tile there. That response is not written to the Worker cache · 403 add-on required · 404 JSON not_found: unknown layer when the id is not in the catalog, or layer archive not configured when the object is not in the bucket.
GET /identify
Which catalog features contain a point. This is the click handler for a map, and it is
not reverse geocoding: /geocode/reverse finds the nearest named
places, identify returns the polygons the point falls inside.
| Parameter | In | Notes |
|---|---|---|
at | query, required | lng,lat. |
layers | query | Comma-separated identify-capable ids. Default municipalities, which is core, so a key with no add-ons still works. |
geometry | query | true to include each hit's polygon where the row has one. |
Returns application/json:
{
"at": [-114.0719, 51.0447],
"results": [
{ "layer": "municipalities", "id": "ab:calgary", "name": "Calgary", "province": "AB" }
]
}A result carries the fields its layer has: unit and survey_system on survey cells,
uwi, licence, operator and status on energy rows, pid on parcels, geometry
when asked for.
Also 400 bad point or unknown layer · 403 add-on required · 502 / 503 the
backing service is unreachable or still waking.
GET /data/query
Every feature of one layer inside a bounding box. One layer per call, by design.
| Parameter | In | Notes |
|---|---|---|
layer | query, required | One queryable catalog id. |
bbox | query, required | minlng,minlat,maxlng,maxlat. A hard filter: nothing outside it is ever returned. |
limit | query | 1 to 50, default 50. A non-numeric value falls back to the default rather than erroring. |
geometry | query | true to include each feature's geometry. |
Returns application/json: { "layer": …, "bbox": [4], "results": [ … ] }, the
results in the same shape as /identify.
Also 400 unknown layer id or malformed bbox · 403 add-on required · 501 the
layer is real but tile-only, with the queryable ids named in the message.
Geocoding
One URL reads the shape of your query and routes it. You do not pick a backend, and
profile= has no effect here: it composes maps, not searches.
| Looks like | Example | Needs |
|---|---|---|
| Civic address or place | Calgary | core |
| Legal land, DLS or NTS | NW-25-24-1-W5 | legal-land |
| Well identifier | 00/07-10-013-09W4/0 | energy |
| BC parcel id | 010-867-813 | agriculture |
| Facility by name | Kaybob South with layers=facility | energy |
| Rural or general delivery | RR 2 Okotoks | core |
GET /geocode/search
| Parameter | In | Notes |
|---|---|---|
q | query, required | The search text. |
lang | query | Which language renders as name, default en. Every result also carries all its languages under names. |
limit | query | 1 to 50, default 10. |
bbox | query | A hard filter, not a bias. |
layers | query | Civic result types to allow (address, street, locality, region, poi), or well / facility to search energy instead. The two sets cannot be mixed, and an unknown value is a 400. |
focus | query | lng,lat. A soft proximity preference: it reorders, it does not exclude. |
region | query | A province or territory, any spelling. Excludes rows in another province; keeps rows with none. |
geometry | query | true to include the survey polygon on a legal-land hit. |
Returns application/json, an array of places:
[
{
"id": "…",
"name": "Iqaluit",
"layer": "locality",
"lng": -68.5170,
"lat": 63.7467,
"score": 18.4,
"names": { "en": "Iqaluit", "iu": "ᐃᖃᓗᐃᑦ" }
}
]Every result also carries source and source_id (which dataset it came from), match_type
(exact, partial, fallback, unknown), precision (point, street, locality, region,
unknown) and, when the match is not exact, match_reasons. See
result metadata; the rule worth knowing is that a street or
city standing in for an address is always fallback, never exact.
A result may also carry distance (metres, on nearby and reverse), category,
address, legal_land, uwi, licence, operator, status, pid, bbox and
geometry, depending on what matched.
Also 400 q missing, an unknown layers or region value, a malformed focus, or a query
that is Canada Post delivery terms and no community · 403 add-on required for the LSD, UWI or
PID grammars.
GET /geocode/structured
| Parameter | In | Notes |
|---|---|---|
address | query | Street line: civic number and street name. |
city | query | Municipality name. |
region | query | Province or territory, any spelling, normalised to a code. |
postalcode | query | With or without the space. Not a deliverability check. |
country | query | CA only. |
lang, limit, bbox, layers, focus | query | As on search. |
At least one of address, city or postalcode is required. address and city retrieve and
rank; region and postalcode narrow, excluding records that contradict them and keeping records
that are silent about them. Civic only: the legal-land, parcel and energy grammars are shapes of a
free-text string and are not detected here.
Returns the same array of places as search.
Also 400 no anchor field, an unknown province, a malformed postal code, a country other than
CA, or an address that is a civic number with no street name.
A successful parse with no matching row returns []. Never a guessed centroid, and never
a silent fall-through to address ranking.
GET /geocode/autocomplete
Type-ahead, same routing as search. q required; lang default en; limit 1 to 50,
default 8. Returns the same array.
GET /geocode/nearby
Places of a category around a point.
| Parameter | In | Notes |
|---|---|---|
category | query, required | One to eight, comma-separated. A taxonomy id (health.pharmacy) or an everyday word in English or French (pharmacy, pharmacie). Case, accents and hyphens are ignored. |
near | query | lng,lat. Exactly one of near and bbox is required. |
bbox | query | Anchors at the box centre with a radius that covers it. "Around here", not a clipping rectangle. |
radius | query | Metres, 50 to 50000, default 5000. An explicit radius beats one derived from bbox. |
limit | query | 1 to 50, default 10. |
lang | query | Default en. |
Returns the same array, carrying distance in metres.
Also 400 an unknown category token, named in the message, both or neither of
near and bbox, or a longitude or latitude outside WGS84 (bad_request) · 422
outside_coverage when the anchor, or the centre of bbox, is outside Canada.
GET /geocode/reverse
What is near a coordinate, ordered by true geodesic distance. near=lng,lat is required.
lang default en; limit 1 to 50, default 5.
Also 400 a missing near, or a longitude or latitude outside WGS84 (bad_request) · 422
outside_coverage when the coordinate is outside Canada. The corpus is not queried. An
empty array means the point is inside Canada and nothing in the corpus is near it.
POST /geocode/batch
Up to 100 forward searches in one request. Shared controls only.
| Parameter | In | Notes |
|---|---|---|
queries | body, required | Array of 1–100 strings, order preserved. Whitespace-only entries become [] and are not billed. |
lang, limit, layers, focus, region, bbox | body | Same as search. |
Returns an array of place arrays, aligned to queries. Index i is what GET /geocode/search would return for that string. Each non-blank query is one geocode increment.
Also 400 missing or empty queries, or invalid shared controls · 413 more than 100 queries · 429 remaining allowance less than the non-blank count.
See Batch geocoding and the example.
Routing
GET /route
Point to point across the Canada graph.
| Parameter | In | Notes |
|---|---|---|
from | query, required | lng,lat. The origin. Both /route and /isochrone use a single parameter per point. |
to | query, required | lng,lat. |
mode | query | auto, car, bicycle, pedestrian, truck or transit, default auto. transit requires depart_at. car and auto are the same profile. Anything else is a 400; nothing falls back silently. |
depart_at | query | ISO 8601 departure instant, required for mode=transit. See Transit routing for schedule coverage. |
use_highways | query | 0 to 1, default 0.5. 0 avoids motorways and trunks, 1 prefers them. Driving modes only. |
use_hills | query | 0 to 1. 0 avoids climbs even for a longer route, 1 is indifferent. Omitted, Valhalla's own default applies, and it differs by mode: 0.25 on bicycle, 0.5 on pedestrian. Cycling and walking only; driving costing has no grade term. |
Truck parameters apply only with mode=truck. Sending one on another mode is a 400,
not a silent ignore.
| Parameter | Default | Range | Unit |
|---|---|---|---|
height | 4.11 | up to 10 | metres |
width | 2.6 | up to 6 | metres |
length | 21.64 | up to 50 | metres |
weight | 21.77 | up to 100 | tonnes gross |
axle_load | 9.07 | 0 to 40 | tonnes per axle |
axle_count | 5 | 2 to 20 | axles |
hazmat | false | boolean | avoids roads that prohibit |
use_truck_route | 0 | 0 to 1 | prefer designated truck routes |
Returns application/json:
{ "distanceMeters": 42731, "durationSeconds": 2184, "geometry": { … } }.
Also 400 unknown mode, a truck option on another mode, or a coordinate outside WGS84
(invalid_location) · 422 outside_coverage when an end is outside Canada, no_route when
the Canadian graph cannot connect those two points.
GET /isochrone
Travel-time bands from a point, given as near=lng,lat.
minutes is required: comma-separated bands, fractions accepted, at most four bands and
each 120 minutes or less. Same mode, depart_at, use_highways, use_hills and truck
parameters as /route; mode=transit requires depart_at.
Returns application/geo+json, a FeatureCollection with one polygon per band. A transit
band can be a MultiPolygon.
Also 400 more than four bands, a band over 120 minutes, or a coordinate outside WGS84
(invalid_location), with the rule named. 422 outside_coverage when the centre is outside
Canada, or for mode=transit when no scheduled transit serves it. A Canadian centre the engine
refuses is 502.
Your own data
Ten overlays per account, 5 MB each. See Bring your own data.
| Route | Does |
|---|---|
POST /byod | Upload application/geo+json, application/vnd.pmtiles, or multipart/form-data with a file field. ?name= sets the display name when the body is not multipart. Returns 201 with the overlay. |
GET /byod | Your overlays and the current quota. |
GET /byod/{id} | One overlay's metadata. |
GET /byod/{id}/data | The stored bytes. |
GET /byod/{id}/{z}/{x}/{y} | Tiles, for a PMTiles upload. Needs ?key=. |
DELETE /byod/{id} | Remove it. 204, no body. |
An overlay is { id, name, kind, bytes, createdAt, url, overlay }, where overlay is
the byod:<id> token you pass to ?overlays=.
Also 400 missing body, wrong content type, over 5 MB, or an eleventh file · 404
unknown id, or one belonging to another account.
Deleting an overlay a style still names leaves that ?overlays=byod:<id> a 404, so
update the style first.
Other APIs
The rest of the surface, one line each. Each links to the page that documents it properly.
Places · full page
| Route | Parameters | Does |
|---|---|---|
GET /places/search | q (required), limit 1-50 (default 10), lang, bbox | Find places by name. Returns { data, meta }. |
GET /places/nearby | category (required), near=lng,lat or bbox, radius 50-50000 m (default 5000), limit 1-50 (default 10), lang | Places of a category near a point. Carries distance in metres. |
GET /places/{id} | id in path (um:place:…), optional lang | One place. A malformed id is a 404 not_found, not a 400. |
A missing q is 400 { "error": "q is required", "code": "bad_request" }. A bbox corner outside WGS84 is 400 bad_request. On search, a box outside Canada stays a filter. On nearby, an anchor outside Canada, or a bbox whose centre is outside Canada, is 422 outside_coverage.
Transit · full page
| Route | Parameters | Does |
|---|---|---|
GET /transit/agencies | none | Every agency in the deployed feed set. |
GET /transit/stops | near=lng,lat (required), radius 50-10000 m (default 1000), limit 1-100 (default 20) | Stops near a point, nearest first. |
GET /transit/stops/{id} | id in path | One stop. |
GET /transit/stops/{id}/departures | at (ISO 8601 instant with Z or an offset, default now), window 1-240 minutes (default 60), limit 1-200 (default 50) | Scheduled departures. Schedule, not real time. |
GET /transit/routes/{id} | id in path | One route. |
Ski
Behind the Ski add-on: a paid key without it gets 403 addon_required, and a dev-plan key gets dev_only from a production origin or usage_limit_reached once its monthly premium calls are spent. The add-on cannot be bought yet, so until it can only development and internal keys reach these.
| Route | Parameters | Does |
|---|---|---|
GET /ski/areas | province (two-letter code), activity (downhill or nordic), bbox, q (name) | Canadian ski areas from OpenStreetMap, ordered by id. Returns { data, meta }; meta.data_version names the release and meta.attribution must be shown (ODbL). |
GET /ski/areas/{id} | id in path | One area. An unknown id is 404 not_found. |
GET /ski/areas/{id}/lifts-3d | id in path | The area's lifts with baked heights for 3D renderers: data.lifts[] with stations, pylons and a sagging cable, each point [lng, lat, z] in metres above sea level from the terrain release named by data.terrain_release. An area with no lifts is an empty list; an unknown id is 404 not_found. |
Elevation · full page
| Route | Parameters | Does |
|---|---|---|
GET /elevation | near=lng,lat, or points, pipe-separated lng,lat pairs, up to 1000, subject to the 16 KB URL limit | DEM elevation. Returns { elevations, units, datum, resolution, meta }. The active global release mixes terrain and surface models and datums; it is not a uniform bare-earth DTM. null means no data or a coordinate beyond Web Mercator. Zero is a value and can be ocean fill. One call whatever the point count. An unconfigured archive is 404; an unavailable selected release is 503, without fallback. |
Time zone · full page
| Route | Parameters | Does |
|---|---|---|
GET /timezone | lat, lon, optional at (ISO 8601) | IANA timezone and UTC offset. One call. Ocean points are Etc/GMT zones. |
GET /timezone/meta | none | Active IANA and boundary versions. Authenticated, not billed. |
Road events · full page
| Route | Parameters | Does |
|---|---|---|
GET /incidents | jurisdiction, bbox, near=lng,lat, radius up to 500000 m, type, severity, status, updated_since, limit 1-500 (default 100) | Every current road event. British Columbia and Alberta today. |
GET /closures | same | The subset where a road is actually shut. |
GET /road-conditions | same | The subset carrying a surface condition. |
Routing expansion · full page
| Route | Body | Does |
|---|---|---|
POST /matrix | origins: [[lng,lat]], destinations: [[lng,lat]], plus the shared costing options | Durations and distances for every pair. A pair the engine could not connect is a null cell, not a failed request. |
POST /match | coordinates: [[lng,lat]] | Snap a GPS trace to the road network. Returns a route. |
POST /optimized-route | stops: [[lng,lat]] | The order to visit stops in, plus the route. First and last are pinned. |
POST /route | from: [lng,lat], to: [lng,lat], avoid_areas | The GET above with a body, for avoid_areas. Same validation, same responses. |
POST /isochrone | near: [lng,lat], minutes: [5,10,15], mode, depart_at, avoid_areas | The GET above with a body. |
GET /routing/status | none | Graph freshness and restriction-feed ages. Answers 200 even when routing is down. Never metered. |
Optimize · full page
Fleet planning using the Google Route Optimization OptimizeToursRequest format and
OptimizeToursResponse format, for supported fields. Errors on these paths are
Google's shape, { "error": { "code", "message", "status", "details" } }, with the gateway's
code beside it.
Per-plan caps limit shipments, vehicles, locations, the solve's timeout (clamped, with a
Warning header) and solves at once; warnings ride the X-Unmap-Optimize-Warnings header.
| Route | Body | Does |
|---|---|---|
POST /optimize | model: { shipments, vehicles }, timeout, solvingMode | Assigns shipments to vehicles and orders each route. solvingMode: VALIDATE_ONLY only validates. Not /optimized-route, which orders one vehicle's stops. |
POST /v1/projects/{project}:optimizeTours | same | Google-compatible REST path. Replace the host and credentials and check supported fields. {project} is ignored. |
POST /v1/projects/{project}/locations/{location}:optimizeTours | same | The same, with a location, also ignored. |
POST /projects/{project}:optimizeTours | same | The GMPRO path without /v1. |
POST /projects/{project}/locations/{location}:optimizeTours | same | The same, with a location. |
Feedback · full page
| Route | Does |
|---|---|
POST /feedback | Report wrong data. Never metered. |
POST /places/{id}/feedback | The same report, scoped to one place. |
Status codes
| Code | Means |
|---|---|
200 | Success. |
201 | Created, on POST /byod. |
204 | Not an error. A tile inside the archive that is serving, with no data at that square. A missing terrain or contour archive is 404, so that misconfiguration cannot read as empty terrain. A missing basemap release is plain-text 503, not a 204. |
400 | Bad parameter, code bad_request unless a more specific one applies. A longitude or latitude outside WGS84 is bad_request on geocoding and places, and invalid_location on routing. The message names the rule. |
401 | No key, or an unknown or disabled key. A missing key on an unknown path is this status too, because auth runs before routing. With a key, that path is 404 not_found. |
413 | More than 100 queries on POST /geocode/batch, or a body larger than 4 MiB on Optimize. |
403 | The key is valid but lacks the add-on this layer or grammar needs. The body names it. |
404 | JSON not_found: an unknown style, layer, or place; layer archive not configured when a catalog layer's object is not in the bucket; a terrain or contour archive that is not configured; or a path this gateway does not serve. An unmatched path under /tiles, /terrain, /contours, /layers, /glyphs, or /sprite stays plain text. |
422 | outside_coverage when an anchor is outside Canada on /route, /isochrone, /matrix, /match, /optimized-route, reverse or nearby lookup. no_route when a Canadian request has no path. Optimize uses 400 FAILED_PRECONDITION for unreachable mandatory shipments. |
429 | Rate limited. Read Retry-After. |
501 | /data/query only: the layer is real but tile-only. The message lists the queryable ids. |
502 | An upstream failure. The code is upstream_error: a routing endpoint answers { "error": "route failed", "code": "upstream_error" }, and on /elevation a terrain tile that will not decode is { "error": "elevation sample failed", "code": "upstream_error" }. |
503 | A backing service is unreachable or still waking. Retry the JSON 503 that carries Retry-After. Plain-text 503 basemap release is misconfigured has none: the previous archive is not served, and another request does not bring it back. |
504 | Optimize's road travel or solver response exceeded its allotted time. See Optimize errors. |
Most JSON error bodies are { "error": "…", "code": "…" }, with addon and capability where
they apply. Optimize uses the structured error object described above. A malformed tile, terrain, contour, glyph, or sprite request answers plain text.
An unconfigured terrain or contour archive is JSON not_found. /elevation uses terrain archive not configured for that case. See
Errors for the full list of codes.