Skip to content
Navo24 Navo24
GETAPI key

Sea route

GETapi.navo24.com/v1/distance/route

Sea distance, transit time and the ECA and non-ECA miles between two ports or two points, with optional alternative corridors and route geometry. One call is one request, whatever options you set. The example is Shanghai to Rotterdam with alternatives, trimmed to the Panama corridor.

Query parameters

fromstringrequired

Origin. A UN/LOCODE such as CNSHA, coordinates as lat,lng, or any form from the Locations table under Road, rail and air. Points snap to the nearest point of the sea network.

modestring

SEA (default), ROAD, RAIL, AIR or RIVER. SEA keeps the response shape on this page. The other modes answer with sections, see Road, rail and air and Inland waterways.

tostringrequired

Destination, in the same forms as from.

speed_knotsnumber

Service speed for the transit time, 3 to 40. Default 14.

routing_modestring

short (default) takes the shortest open route. safe also closes Bab-el-Mandeb, so Asia to Europe goes through Panama or round the Cape.

avoidstring

Comma-separated passages to close, from the Passages table below. Example: suez,panama.

alternativesboolean

Also return the other sensible corridors. Closing Suez gives Panama and the Cape, closing Panama gives Suez and the Cape, closing Malacca gives Sunda. Default false.

pathboolean

Include the route polyline as [lat, lng] pairs, for drawing on a map. Default false.

Response schema

15 fields

Nested exactly as the JSON is. Open a branch to read its fields; hover a name for the full dot-path.

dataobject
fromobject

The resolved points: locode, name, country, country_code, lat, lng. source is network (a port on the routing graph), unlocode (UN/LOCODE coordinates) or coordinates (you sent lat,lng).

toobject

The resolved destination, same shape as data.from.

routing_modestring

short or safe, as applied.

avoided[]array

Every passage closed for this calculation: yours plus the one safe adds.

routeobject
labelstring

Name of the corridor: via Suez Canal, via Panama Canal, via Cape of Good Hope or direct.

distanceobject
nmnumber

Total sea distance in nautical miles. distance.km carries the same in kilometres.

ecaobject
nmnumber

Miles sailed inside an Emission Control Area.

non_eca_nmnumber

Miles sailed outside every ECA. eca.nm + eca.non_eca_nm = distance.nm.

sharenumber

ECA miles as a fraction of the total, 0 to 1.

zones[]array

Miles per zone: id, name, nm. Zones the route does not enter are left out.

transitobject
daysnumber

Time under way at transit.speed_knots, also given as transit.hours. Port stays, canal waiting and bunker calls are not included.

passages[]array

Canals and straits on the route, as id and name.

path[]array

Only with path=true: the polyline as [lat, lng].

alternatives[]array

Only with alternatives=true. Same shape as route, plus avoids[] (the passages closed to get it) and extra.nm, extra.days against the main route. Sorted by distance, empty when no other corridor makes sense.

metaobject
took_msnumber

Server time for the calculation.

Errors

A failure answers with an HTTP error status and { "error": { "code", "message" } }. Branch on the code, and log the message.

invalid_request400

A parameter is missing or malformed: an unknown mode, speed_knots outside 3 to 40, an unknown passage in avoid, a pol/pod that is not a sea port, or a date that is not YYYY-MM-DD.

location_not_found404

The location is well formed but we cannot place it: an unknown code, or an address the geocoder does not find.

no_route422

No route joins the two points with the modes and passages you allowed, for example SEA only between two inland cities. When a seasonal river closure is the cause, the message names each closure, its typical window and the date it usually reopens.

geocoder_unavailable503

Free-text address lookup is briefly down. Codes and coordinates keep working.

How the ECA split is measured

The route is walked in steps of at most 20 nautical miles, and each step is counted in the ECA it lies in or as open sea. Boundaries model MARPOL Annex VI to within a few miles at the zone edge. Good for spot-rate models and fuel estimates, not a legal compliance record.

What transit time covers

Distance divided by speed, so time under way. Port stays, canal transits and waiting depend on the service, not the geometry: add them yourself.

Alternatives

Each alternative is a real route with one or more passages closed. A route that already avoids Suez gets no Suez-closed alternative. Anything longer than 2.2 times the main route is dropped as not commercially sensible.

Coverage

14,196 ports: 3,962 on the routing network and the remaining UN/LOCODE seaports with coordinates. Any point at sea or on the coast also works as lat,lng.

Passages

Ids accepted by <code>avoid</code> and returned in <code>passages[]</code> and <code>avoids[]</code>. GET /passages returns the same list.

idPassage
suezSuez Canal
panamaPanama Canal
babalmandabBab-el-Mandeb
malaccaStrait of Malacca
gibraltarStrait of Gibraltar
ormuzStrait of Hormuz
bosporusBosporus
sundaSunda Strait
south_africaCape of Good Hope
chiliStrait of Magellan
beringBering Strait (always avoided)
northwestNorthwest Passage (always avoided)

ECA zones

Emission Control Areas under MARPOL Annex VI that the split is measured against.

idZoneRegulatesIn force since
north-americanNorth American ECASOx, NOx, PM2012-08-01
us-caribbeanUS Caribbean Sea ECASOx, NOx, PM2014-01-01
north-seaNorth Sea ECASOx, NOx (Tier III from 2021)2007-11-22
balticBaltic Sea ECASOx, NOx (Tier III from 2021)2006-05-19
mediterraneanMediterranean Sea ECASOx, PM2025-05-01
curl 'https://api.navo24.com/v1/distance/route?from=CNSHA&mode=SEA&to=NLRTM&speed_knots=14&routing_mode=short&alternatives=true' \
  -H "Authorization: Bearer tmcp_YOUR_API_KEY"
Response
{
  "data": {
    "from": {
      "locode": "CNSHA",
      "name": "Shanghai",
      "country": "China",
      "country_code": "CN",
      "lat": 31.40009,
      "lng": 121.49711,
      "source": "network"
    },
    "to": {
      "locode": "NLRTM",
      "name": "Rotterdam",
      "country": "Netherlands",
      "country_code": "NL",
      "lat": 51.90438,
      "lng": 4.44245,
      "source": "network"
    },
    "routing_mode": "short",
    "avoided": [],
    "route": {
      "label": "via Suez Canal",
      "distance": {
        "nm": 10588.6,
        "km": 19610.1
      },
      "eca": {
        "nm": 2340.5,
        "non_eca_nm": 8248.1,
        "share": 0.221,
        "zones": [
          {
            "id": "north-sea",
            "name": "North Sea ECA",
            "nm": 405.7
          },
          {
            "id": "mediterranean",
            "name": "Mediterranean Sea ECA",
            "nm": 1934.8
          }
        ]
      },
      "transit": {
        "speed_knots": 14.0,
        "hours": 756.3,
        "days": 31.51
      },
      "passages": [
        {
          "id": "gibraltar",
          "name": "Strait of Gibraltar"
        },
        {
          "id": "suez",
          "name": "Suez Canal"
        },
        {
          "id": "malacca",
          "name": "Strait of Malacca"
        },
        {
          "id": "babalmandab",
          "name": "Bab-el-Mandeb"
        }
      ]
    },
    "alternatives": [
      {
        "label": "via Panama Canal",
        "distance": {
          "nm": 13508.5,
          "km": 25017.7
        },
        "eca": {
          "nm": 498.0,
          "non_eca_nm": 13010.5,
          "share": 0.0369,
          "zones": [
            {
              "id": "us-caribbean",
              "name": "US Caribbean Sea ECA",
              "nm": 121.2
            },
            {
              "id": "north-sea",
              "name": "North Sea ECA",
              "nm": 376.7
            }
          ]
        },
        "transit": {
          "speed_knots": 14.0,
          "hours": 964.9,
          "days": 40.2
        },
        "passages": [
          {
            "id": "panama",
            "name": "Panama Canal"
          }
        ],
        "avoids": [
          {
            "id": "suez",
            "name": "Suez Canal"
          }
        ],
        "extra": {
          "nm": 2919.9,
          "days": 8.69
        }
      }
    ]
  },
  "meta": {
    "took_ms": 120
  }
}