N-Ways
Developer docsRoutes

Routes

Directions the way people really travel here: by car, okada, keke, danfo, on foot, by train or by boat, with live traffic, tolls, okada and keke bans, borders, and what the ride should cost.

On this page

Base address: https://nways.ng/maps/v1. Routes, fares and traffic here; for many origins and destinations at once see the route matrix, and for a batch of stops route optimisation. Reference

Get a route

POST /maps/v1/routes/compute with a JSON body.

cURL
curl -X POST "https://nways.ng/maps/v1/routes/compute" \
  -H "X-NWays-Api-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"origin": {"lat": 6.6018, "lng": 3.3515}, "destination": {"postcode": "LA08A09DB09"}, "mode": "okada", "fares": true}'
JavaScript
import { createClient } from '@nways/maps'

const nways = createClient({ key: process.env.NWAYS_API_KEY })
const { routes } = await nways.route({
  origin: { lat: 9.0579, lng: 7.4951 },
  intermediates: [{ lat: 9.0765, lng: 7.3986 }],
  destination: { lat: 9.0034, lng: 7.2633 },
  mode: 'drive',
  avoid: ['tolls'],
})
console.log(Math.round(routes[0].durationS / 60), 'min')
Python
import os
import requests

res = requests.post(
    "https://nways.ng/maps/v1/routes/compute",
    headers={"X-NWays-Api-Key": os.environ["NWAYS_API_KEY"]},
    json={"origin": {"lat": 5.6037, "lng": -0.187}, "destination": {"lat": 6.1319, "lng": 1.2228}, "mode": "drive", "lang": "fr"},
    timeout=20,
)
res.raise_for_status()
best = res.json()["routes"][0]
print(round(best["durationS"] / 60), "min")

Request body

FieldDescription
origin, destinationRequired. A { "lat", "lng" } point, a NIPOST { "postcode" } (the route ends at the building’s best entrance), a { "ghanaPost" } address or a { "plusCode" }. The origin may have a heading in degrees, so a moving vehicle doesn’t start with a U-turn.
intermediatesUp to 25 stops on the way, in order, in the same forms.
modedrive (default), van, okada (a motorbike taxi: keeps to okada bans), motorbike (your own motorbike: commercial bans don’t apply), keke and danfo (keep to their bans), walk, bicycle, boat (passenger boats and jetties), train.
alternativestrue for up to 2 more routes (without intermediates).
routingPreferencetraffic_unaware (default) or traffic_aware: live traffic and reported incidents.
departAtWhen the trip starts (RFC 3339): boats run in daylight, and traffic follows the hour.
avoidAny of tolls, highways, bad_roads (roads drivers reported as rough or flooded).
tollVehicleThe toll tariff class: car, suv, bus, truck.
accessTrain and boat trips: how to reach and leave the station or jetty: walk, okada or drive.
lastMileWhere the road stops short of the door: finish on foot (walk) or by okada.
allowBansIDs of reported, unconfirmed bans to ride through anyway.
farestrue adds what the trip should cost to each route.
langen (default) or fr, for instructions.

?fields= keeps only some fields of each route, such as fields=distanceM,durationS,geometry.

Response

200 OK (shortened)
{
  "routes": [
    {
      "distanceM": 1395,
      "durationS": 228,
      "staticDurationS": 228,
      "trafficDelayS": 0,
      "summary": "Admiralty Way and Awudu Ekpekha Boulevard",
      "geometry": { "type": "LineString", "coordinates": [[3.472352, 6.4474], [3.472352, 6.447802], "…"] },
      "legs": [{ "distanceM": 1395, "durationS": 228 }],
      "steps": [
        { "maneuver": "depart_left", "instruction": "Drive north on Victoria Arobieke Street.", "distanceM": 44, "durationS": 6, "streetNames": ["Victoria Arobieke Street"], "startIndex": 0, "endIndex": 1 }
      ],
      "country": "NG"
    }
  ]
}
FieldDescription
routesThe best route first, then any alternatives.
distanceM, durationSLength in metres and time in seconds.
staticDurationS, trafficDelaySThe time without live traffic, and what traffic and incidents add now (with traffic_aware).
geometryA GeoJSON LineString, ready for a map layer.
stepsTurn-by-turn: instruction, distance, time, streetNames, and where each starts and ends in geometry; roundabout exits, traffic lights, and footbridges or zebra crossings on foot.
legsOne per part between stops.
segmentsTrips that change how you travel: a train or boat, or an okada that walks past a ban area.
vehicleRulesOkada, keke and danfo trips: the bans the route kept out of (avoided), rules that are advice only, a start or end inside a ban area (endBan), and where riders say they’re stopped.
lastMileWhere to stop when the road ends before the door, and how to finish.
accessA gated estate or compound at the destination.
tolls, borderCrossingsToll gates and what they cost in their currencies; border posts on trips between countries.
congestion, roadConditionSlow stretches; rough, flooded or damaged stretches drivers reported.
faresWith fares: true: what the trip should cost (see Fares).
warningsAnything else worth telling the rider.

Errors

StatusReasonMeaning
400MODE_INVALID, WAYPOINT_INVALID, TOO_MANY_INTERMEDIATES…A missing or wrong field. The message says which.
404POSTCODE_NOT_FOUND, GHANAPOST_NOT_FOUNDA code N-Ways can’t place.
422NO_ROUTE, NO_ROAD_ROUTENo route: a point is too far from any road, or across water (try boat or walk).
422OKADA_BANNED_ORIGIN, …_DESTINATION, …_STOP, …_ROUTEAn okada can’t do this trip; the same for MOTORBIKE_BANNED_…, KEKE_BANNED_… and DANFO_BANNED_….
422ROUTE_TOO_FARThe places are too far apart for one route of this kind.
503ROUTING_UNAVAILABLEThe routing engine is busy or restarting. Retry after a minute.

Basic routes (car, van, walking and cycling without live traffic, up to 10 stops) and advanced ones (live traffic, okada, keke, danfo, motorbike, boat, train, more than 10 stops, or fares) are priced differently. Pricing

Fares

What a ride should cost, in the country’s money: taxi, shared taxi, okada, keke, danfo or bus, boat and ride-hailing, from what riders paid (basis: crowd) or published sources (basis: guide), with night, rush hour, rain and chartered rides.

GET /maps/v1/fares/estimate

ParameterDescription
from, toRequired. lat,lng each.
modeComma-separated: taxi, shared_taxi, okada, keke, danfo, ridehail, boat. All if not given.
distanceM, durationSThe route’s length and time, if you have them; better estimates.
atWhen the trip is (RFC 3339): night and rush hour cost more.
charter, raintrue for a chartered (“drop”) ride, or in rain.
langen or fr.
cURL
curl "https://nways.ng/maps/v1/fares/estimate?from=6.4474,3.4720&to=6.5244,3.3792&mode=okada,taxi" \
  -H "X-NWays-Api-Key: YOUR_API_KEY"

The answer has the currency and one estimates entry per mode with low, typical and high prices (in the currency’s main unit), a written text such as ₦8,150–15,200, whether it’s perPerson, and its sources. Modes the law keeps off the trip are in notAllowed, with the rule and its source (okadas are banned in much of Lagos).

Live traffic

cURL
curl "https://nways.ng/maps/v1/traffic?bbox=3.30,6.40,3.50,6.60" -H "X-NWays-Api-Key: YOUR_API_KEY"

Roads with live readings in a box (minLng,minLat,maxLng,maxLat, under 3° across), as GeoJSON lines with a congestion level, for drawing on a map. Readings come from N-Ways phones on the road, anonymously. Don’t cache it: it changes by the minute. For speeds per road and direction, for your own ETAs, see the traffic feed.

The earlier address

POST https://nways.ng/v1/routes (with from, to and stops) and /v1/fares/estimate keep working for partners who started with them for at least 12 months, but their answers follow the N-Ways app. Move to /maps/v1, whose answers only ever gain fields.