Migrating from Mapbox

By the end of this guide, you'll have replaced your Mapbox data API calls with Plaza. The big thing to know upfront: Plaza is data-only. You'll still want MapLibre GL JS (or another tile renderer) for your map.

Why people switch

Open data, open terms. Mapbox uses OSM data but wraps it in proprietary APIs and restrictive terms. Plaza serves OSM data directly under ODbL. Cache it, transform it, redistribute it.

Query languages. Mapbox gives you fixed endpoints. Plaza adds Overpass QL and SPARQL. Want every bench in Paris that faces a river? Write a query. Mapbox can't do that.

Cross-feature queries. Chain geocoding, isochrones, and search in a single request. See the cross-feature guide.

Simpler pricing. Mapbox prices each API separately (geocoding, directions, isochrones, each with different rates). Plaza bills on total API calls at a single rate.

API mapping

Mapbox API Plaza equivalent Method
Geocoding v6 (forward) /api/v1/geocode?q=... GET
Geocoding v6 (reverse) /api/v1/geocode/reverse?lat=...&lng=... GET
Directions v5 /api/v1/route POST
Isochrone v1 /api/v1/isochrone?lat=...&lng=...&time=... GET
Matrix v1 /api/v1/matrix POST
Search (via Geocoding) /api/v1/search?q=... GET
(no equivalent) /api/v1/overpass (Overpass QL) POST
(no equivalent) /api/v1/sparql (SPARQL) POST
(no equivalent) /api/v1/nearby?lat=...&lng=... GET

Auth change

Mapbox puts access tokens in the query string. Plaza uses a header.

# Mapbox
curl "https://api.mapbox.com/geocoding/v5/mapbox.places/Berlin.json?access_token=MAPBOX_TOKEN"
# Plaza
curl "https://plaza.fyi/api/v1/geocode?q=Berlin" \
-H "x-api-key: pk_live_YOUR_KEY"

Code changes

Forward geocoding

Python -- Mapbox:

from mapbox import Geocoder
geocoder = Geocoder(access_token="MAPBOX_TOKEN")
resp = geocoder.forward("Brandenburg Gate, Berlin")
features = resp.geojson()["features"]
coords = features[0]["geometry"]["coordinates"] # [lng, lat]

Python -- Plaza:

import requests
resp = requests.get(
"https://plaza.fyi/api/v1/geocode",
params={"q": "Brandenburg Gate, Berlin"},
headers={"x-api-key": "pk_live_YOUR_KEY"}
)
result = resp.json()["results"][0]
lat, lng = result["lat"], result["lng"]

Directions

JavaScript -- Mapbox:

const mbxDirections = require("@mapbox/mapbox-sdk/services/directions");
const client = mbxDirections({ accessToken: "MAPBOX_TOKEN" });
const resp = await client.getDirections({
profile: "driving",
waypoints: [
{ coordinates: [2.3522, 48.8566] },
{ coordinates: [2.3350, 48.8849] }
]
}).send();
const route = resp.body.routes[0];

JavaScript -- Plaza:

const resp = await fetch("https://plaza.fyi/api/v1/route", {
method: "POST",
headers: {
"x-api-key": "pk_live_YOUR_KEY",
"Content-Type": "application/json"
},
body: JSON.stringify({
origin: { lat: 48.8566, lng: 2.3522 },
destination: { lat: 48.8849, lng: 2.3350 },
mode: "auto"
})
});
const route = await resp.json();

Isochrones

curl -- Mapbox:

curl "https://api.mapbox.com/isochrone/v1/mapbox/driving/13.4132,52.5219?\
contours_minutes=15&polygons=true&access_token=MAPBOX_TOKEN"

curl -- Plaza:

curl "https://plaza.fyi/api/v1/isochrone?lat=52.5219&lng=13.4132&time=900&mode=auto" \
-H "x-api-key: pk_live_YOUR_KEY"

Mapbox takes contours_minutes. Plaza takes time in seconds. Multiply by 60.

Reverse geocoding

Python -- Mapbox:

resp = geocoder.reverse(lon=2.2945, lat=48.8584)
place_name = resp.geojson()["features"][0]["place_name"]

Python -- Plaza:

resp = requests.get(
"https://plaza.fyi/api/v1/geocode/reverse",
params={"lat": 48.8584, "lng": 2.2945},
headers={"x-api-key": "pk_live_YOUR_KEY"}
)
address = resp.json()["display_name"]

Distance matrix

curl -- Mapbox:

curl "https://api.mapbox.com/directions-matrix/v1/mapbox/driving/\
2.3522,48.8566;2.3350,48.8849;2.2945,48.8584?access_token=MAPBOX_TOKEN"

curl -- Plaza:

curl -X POST "https://plaza.fyi/api/v1/matrix" \
-H "x-api-key: pk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"origins": [{"lat": 48.8566, "lng": 2.3522}],
"destinations": [
{"lat": 48.8849, "lng": 2.3350},
{"lat": 48.8584, "lng": 2.2945}
],
"mode": "auto"
}'

Mapbox puts all coordinates in the URL as semicolons. Plaza takes separate origins and destinations arrays in the body, which is easier to read and doesn't hit URL length limits for large matrices.

Things that work differently

No map tiles. This is the biggest change. Mapbox is map-first. Plaza is data-only. Keep using MapLibre GL JS with any tile source (MapTiler, Stadia, self-hosted) and use Plaza for the data queries behind the map.

GeoJSON everywhere. Mapbox has its own response structure with routes, waypoints, and custom objects. Plaza returns standard GeoJSON where possible. Less response transformation needed.

Travel mode names. Mapbox uses driving, walking, cycling. Plaza uses auto, foot, bicycle. Find-and-replace.

Coordinate parameters. Mapbox URLs use lng,lat order. Plaza uses separate lat and lng query parameters or {"lat": ..., "lng": ...} objects in POST bodies. GeoJSON geometry in responses is always [lng, lat] per the spec.

Overpass QL and SPARQL. No Mapbox equivalent. If you've been fetching everything in a bounding box and filtering client-side, you can push that logic into an Overpass query instead.

Streaming. Large result sets stream as newline-delimited JSON. Mapbox caps most endpoints at a few hundred results. Plaza streams millions. See the streaming guide.

Gotchas

Time in seconds, not minutes. Mapbox isochrone uses contours_minutes. Plaza uses time in seconds. A 15-minute isochrone is time=900.

Separate origin/destination. Mapbox Directions takes a waypoint list in the URL. Plaza takes origin and destination as separate objects in the POST body.

No place categories. Mapbox geocoding returns place_type (poi, address, neighborhood). Plaza returns OSM tags directly. Map your Mapbox type filters to OSM tag queries.

Per-plan rate limits. Mapbox has fixed limits per endpoint. Plaza has per-plan limits across all endpoints. Check the auth docs for your tier.

Autocomplete is a separate endpoint. Mapbox geocoding does autocomplete by default. Plaza has a dedicated /geocode/autocomplete endpoint optimized for keystroke-by-keystroke suggestions.