Skip to content

50,000 free calls a month, card-free. Get an API key →

Documentation menu
docs / migrate-from-nextbillion · raw .md

Migrating from NextBillion.ai

A port from NextBillion is a rewrite of the call layer, not a URL swap. Their Directions, Distance Matrix, Navigation and Isochrone APIs are a proprietary family with their own request and response shapes, so every endpoint below needs client changes. What you gain in exchange is an ADR dangerous-goods model, EV journey planning, a self-host licence with a published price, and an agent surface you can call without a key.

Be straight about the shape. MapMap's routing is OSRM-compatible on the URL endpoint and Valhalla-shaped on POST /route. NextBillion's is neither. Their Fast and Flexible variants share one envelope (status, routes[], legs[], steps[], with latitude/longitude objects and distance/duration as {value} wrappers) and take named origin/destination query parameters. A handful of their parameter names are borrowed from OSRM spelling (overview, approaches, bearings, alternatives, geometry=polyline6), but the envelope is not OSRM's and there is no costing or costing_options anywhere in it. Anyone who tells you the Flexible API is Valhalla-shaped has not read the specification. Checked against their own OpenAPI document on 3 September 2026.

Key swap

NextBillion keys are issued after a business account is set up with them. MapMap keys are issued by one unauthenticated call, card-free:

sh
curl -fsS -X POST "https://api.mapmap.ai/v1/keys" \
  -H "Content-Type: application/json" \
  -d '{"email": "you@example.com", "accept_tos": true}'

Their key travels as a key= query parameter on every request. Ours goes in Authorization: Bearer snk_… (preferred), or ?api_key=snk_… for URL-only contexts such as style and tile URLs. Verify the email and the free tier is 50,000 calls a month, commercial use allowed.

Note the host difference while you are porting: their documentation is on docs.nextbillion.ai and their API is on api.nextbillion.io.

Endpoint mapping

NextBillionMapMapNotes
GET /directions/json (Fast)GET /route/v1/{profile}/{coords} or POST /routeCoordinates move from origin=/destination= query parameters to a path of lon,lat;lon,lat (OSRM endpoint) or a locations[] array of {lat, lon} (native). Watch the order: theirs is lat,lng.
GET /directions/json?option=flexiblePOST /routeThe native endpoint is where truck, ADR and route options live. See the parameter table below.
GET /distancematrix/jsonPOST /matrixTheir origins/destinations become sources/targets arrays of {lat, lon}. Response is durations (seconds) and distances (metres), row-major, with null for unreachable pairs. Up to 10,000 elements per request.
POST /mdm/create and GET /mdm/status (async matrix)POST /matrix, or POST /v1/jobs/matrix + GET /v1/jobs/{id}Two ways across. Up to 10,000 elements the matrix answers synchronously and the polling pair disappears; above that the asynchronous lane is the same submit-and-poll shape you already have, at 40,000 elements, with an optional signed webhook so you can stop polling altogether.
POST /optimization/v2 and GET /optimization/v2/resultPOST /optimise, or POST /v1/jobs/optimise + GET /v1/jobs/{id}Same choice. Up to 200 unique locations it is one synchronous call and the result-polling disappears; up to 2,000 the asynchronous lane keeps the job-id shape and adds a signed webhook. Truck and ADR constraints shape the plan either way, polling costs no quota, and a failed job refunds what its submission was charged. Limits are published: 200 or 2,000 unique locations, 1,500 km matrix span. See optimisation.
GET /snapToRoads/jsonPOST /trace_route, POST /trace_attributesTheir path becomes shape (an array of {lat, lon}) or encoded_polyline. timestamps and radiuses have no direct equivalent; shape_match (edge_walk, map_snap, walk_or_snap) selects the snapping behaviour instead.
POST /route-reconstruction, POST /postTripRoutePOST /route/reportDistance and duration broken down by road class, admin area, toll, bridge, tunnel and surface, over an existing route or trace.
GET /isochrone/jsonPOST /isochronecontours_minutes and contours_meters become one contours array whose entries carry a time in minutes or a distance in kilometres. polygons, denoise and generalize port by name. Ten contours per request against their four.
GET /geocodeGET /geocodeTheir q becomes query, and at becomes focus. The response shape differs: ours returns candidates with name, label, lat/lon, type and address parts, not their HERE-style items[] with position{lat,lng}. This one always needs client changes.
GET /revgeocodeGET /geocode/reverseTheir at=lat,lng becomes lat and lon parameters.
GET /navigation/jsonGET /route/v1/{profile}/{coords}?steps=trueAdd voice_instructions=true and banner_instructions=true for Mapbox-shaped spoken prompts and banners, including lane diagrams where OSM carries turn:lanes.
GET /incidentsPOST /v1/incidents/alongIncidents and closures along a route shape, with per-source coverage metadata. Coverage differs by deployment; 501 where none is configured.
POST /hos/trip-planPOST /optimiseDriver hours are expressed as vehicle time windows, breaks and shift limits inside the optimisation problem rather than as a separate endpoint. See driver hours.
/places/autosuggest, /places/autocompleteGET /geocode/suggest, GET /geocode/retrieveSearch-as-you-type: a compact suggestion list per keystroke, then the full feature for the row the user picked.
/optimization/driver-assignment/v1, /clusteringNo direct equivalentModel the assignment as a VRP over POST /optimise, or run your own clustering over POST /matrix output.

Parameter compatibility

Every mapped parameter below was checked as existing on both sides. Anything that exists on only one side is in the section after it.

ConceptNextBillionMapMapWatch out
Vehicle profilemode = car, truck, motorcycle, bike, walkcosting = auto, truck, motorcycle, bicycle, pedestrian (plus bus, motor_scooter)bike becomes bicycle, walk becomes pedestrian. Fast-variant callers only ever had car and truck.
Truck height, width, lengthtruck_size = height,width,length in centimetresheight, width, length in metresDivide by 100. Theirs is one packed string, ours is three fields.
Truck weighttruck_weight in kilogramsweight in tonnesDivide by 1,000. Their own docs are inconsistent here: weight is kg while truck_axle_load is tonnes.
Axle loadtruck_axle_load in tonnescosting_options.truck.axle_load in tonnesSame unit, so this one ports directly.
Avoidancesavoid = toll, ferry, highway, …avoid_tolls, avoid_ferries, avoid_motorways booleansTheir pipe-separated list becomes separate booleans. avoid_tolls and avoid_motorways are motorised profiles only.
Shortest versus fastestroute_type = fastest, shortestshortest booleanDefault on both is fastest.
Alternativesalternatives, altcountalternatives = true/false or a number, max 3One field instead of two.
Geometry encodinggeometry = polyline, polyline6, geojsongeometries = polyline, polyline6, geojson on the OSRM endpointSame three values under a pluralised name. Their Flexible variant drops geojson, so a Flexible caller gets it back here.
Time-dependent routingdeparture_time, a UNIX timestamp in secondsdate_time, an object of {type, value} such as {"type": 0, "value": "2026-08-13T09:20"}Both cost against typical conditions at the given time, but the encoding differs: a local ISO-8601 string with a type discriminator, not an epoch.
Step-by-step legssteps (Fast only)steps=trueTheir Flexible variant has no steps at all, so a Flexible caller gains this in the move.

Two of their parameters have no documented MapMap equivalent and are not in the table above because the table is a parity list: approaches (unrestricted or curb) and bearings. Both are OSRM-named on their side, but neither appears in the MapMap API reference, so treat curbside approach and start-bearing constraints as capability you are giving up rather than remapping.

What ports with client changes

Everything. There is no drop-in path here, and it would be dishonest to suggest one. Budget for:

  • Coordinate order and encoding. Theirs is lat,lng in a query string; ours is {lat, lon} objects in JSON, or bare lon,lat pairs on the OSRM-compatible URL endpoint. That last one has caught everybody at least once.
  • Unit conversions. Centimetres to metres, kilograms to tonnes, and their isochrone contours_meters to our distance in kilometres.
  • Response parsing. Their routes[].legs[].distance{value} becomes a plain distance_m; their status/msg envelope becomes HTTP status plus a problem+json body.
  • Deciding what to do with the polling pairs. Below the synchronous caps (10,000 matrix elements, 200 optimisation locations) both collapse to one call and the job-id plumbing comes out. Above them, keep it: /v1/jobs/… is the same submit-and-poll shape, and the polling half is quota-free.

What MapMap adds

  • ADR dangerous goods, modelled properly. Their hazmat_type is a flat nine-value filter (explosives, gas, flammable_liquid, flammable_gas, organic, toxic, radioactive, corrosive, other) that avoids unsuitable roads, and their specification contains no ADR tunnel category, no tunnel-restriction code and no placard concept. Tunnels are all or nothing through avoid=tunnel. MapMap takes a tunnel_code of B to E with hazmat on the truck profile and enforces ADR 8.6.4 in costing, returns applied_adr saying what was enforced, and answers the pure tunnel-entry question through POST /adr/check with no routing at all. Read the limits on that page honestly before you rely on it: it reflects what the map and the ADR matrix record, and it certifies nothing.
  • EV journey planning. POST /v1/ev/plan works out the charge stops: physics consumption over the route's own legs, charge times integrated over the vehicle's charging curve rather than energy divided by peak power, and a reserve floor the state of charge never breaches. When no plan exists it says feasible: false with the cause and the furthest reachable point. POST /v1/charging/along ranks charge points along a route by power with their real engine-computed detour. NextBillion's published API carries no EV endpoint or parameter.
  • Self-hosting with a published price. The whole stack, gateway, routing engine, geocoder and MCP server, from one Docker Compose file, with licence anchors on the pricing page and in /pricing.json. Their on-premises deployment is offered "exclusively under our Enterprise pricing plan" and quoted on request.
  • Offline territories. ed25519-signed territory packages that verify with no network, do not expire, and update differentially. On-device routing, search and turn-by-turn against the local package.
  • An agent surface. A hosted MCP server with 39 tools at https://mcp.mapmap.ai/mcp, connectable with no key at all under fair use, plus /llms.txt, /llms-full.txt, /openapi.json, /pricing.json, one-call keys and x402 machine payments.
  • Measured clearance. POST /v1/clearance/along judges a vehicle against surveyed point-cloud geometry rather than map tags, where a survey exists.

What has no replacement

Say this out loud before you plan the migration, because it is the part that decides whether you can move at all.

  • Asset tracking, live tracking and geofencing. NextBillion ships a tracking platform (their Skynet asset APIs, device battery and location telemetry, geofence entry and exit events). MapMap has no equivalent and is not trying to build one. If that platform is load-bearing for you, keep it or replace it with a telematics vendor: Samsara, Motive, Webfleet, Verizon Connect, Geotab or Teltonika-based integrators all sell this as their core product, and most take routing from an API like ours. MapMap routes and complies; it does not track your fleet.
  • Their per-customer map editing. Private-road and custom-restriction overlays are not a hosted self-service product here today. Custom territory builds are a self-host and Sovereign tier conversation.
  • Static map images from the routing platform. There is a static map endpoint on the website, not on the gateway, and it is not a like-for-like replacement for their static_map_image tooling.
  • Hosted worldwide coverage on day one. Hosted coverage is territory-based; check GET /territories. Self-host covers anywhere you build.
  • Hours-of-service as a standalone endpoint. The capability exists inside POST /optimise as shifts, breaks and time windows, but a client calling POST /hos/trip-plan directly is rewriting, not remapping.

Billing differences to encode

Their pricing is quoted per order, per asset or per API call under an annual commitment. Ours is published and prepaid: two price classes detected per request, Standard (car, bicycle and pedestrian routing, matrix, isochrone, matching, geocoding) and Premium (anything truck or ADR, drawing 20 included calls from the free tier). No credit means a 402 or 429, never surprise billing, and a request answered 4xx is never charged. Machine-readable at https://mapmap.ai/pricing.json.

Attribution

MapMap requires "© OpenStreetMap contributors"; compiled styles carry it structurally. See licensing.

Full API reference: /docs/api-reference (append .md for raw markdown). Units, errors and quotas: conventions. A side-by-side on commercial terms: NextBillion.ai alternative.