API Reference

Complete reference for the Searoutesnav REST API. The base URL for all requests is https://api.searoutesnav.com. All endpoints return JSON. Authenticated endpoints require a bearer token obtained from POST /auth/login. See Authentication.

Authentication

POST/auth/loginNo auth

Authenticate with email and password and receive a bearer token.

{ "email": "you@example.com", "password": "your-password" }

Response 200

{ "access_token": "eyJ0eXAiOi...", "token_type": "bearer", "user": { "id": 1, "email": "you@example.com", "full_name": "Jane Doe", "company_name": "Acme Shipping", "plan_type": "trial", "daily_query_limit": 25, "is_active": true, "plan_expires_at": null } }

Returns 401 on invalid credentials.

POST/auth/logout

Revoke the bearer token used for the request.

GET/auth/me

Return the profile of the currently authenticated user.

Response 200

{ "id": 1, "email": "you@example.com", "full_name": "Jane Doe", "company_name": "Acme Shipping", "phone": "+1 555 0100", "address": "1 Harbor Rd", "city": "New York", "country": "US", "plan_type": "trial", "daily_query_limit": 25, "is_active": true, "created_at": "2026-01-01T00:00:00Z", "plan_expires_at": null }
GET/auth/usage

Return today's query usage and the remaining daily quota for the authenticated user.

POST/forgotten-passwordNo auth

Email a new password to the account (requires SMTP configured on the server).

{ "email": "you@example.com" }

Routing

POST/calculate-route

Calculate a sea route between two points, given either coordinates or port ids. Throttled against your daily query limit. Each origin/destination is supplied as either { "coordinates": [lon, lat] } or { "port_id": 123 }.

Request body

NameTypeRequiredDescription
originobjectYescoordinates [lon, lat] or port_id
destinationobjectYescoordinates [lon, lat] or port_id
speed_kmhnumberNoVessel speed for duration estimates
resolution_kmenumNoGrid resolution: 5, 10, 20, 50, 100
suez / panama / gibraltar / kielbooleanNoAllow/forbid passage through each strait/canal
include_portsbooleanNoInclude intermediate ports in the response
waypoint_countintegerNoTarget number of returned waypoints
waypoint_strategyenumNoWaypoint sampling: 'nth', 'count', 'simplify', 'none'
vesselobjectNotype (container|bulker|tanker, required), size_class, draft_m, beam_m, loa_m, fuel_tonnes_per_day, fuel_type (HFO|VLSFO|MGO)
fuel_price_usd_per_tonnenumberNoUsed for cost estimates in the emissions block

Example request

{ "origin": { "port_id": 101 }, "destination": { "coordinates": [-0.13, 51.5] }, "speed_kmh": 37, "resolution_km": 20, "vessel": { "type": "container", "fuel_type": "HFO" } }

Response 200

{ "success": true, "distance_km": 5821.4, "duration_hours": 157.3, "route_coordinates": [[lon, lat], ...], "waypoints": [[lon, lat], ...], "restricted_passes": ["suez"], "vessel": { "type": "container", "service_speed_kn": 20, ... }, "emissions": { "fuel_tonnes": 410.2, "co2_tonnes": 1277.8, "cost_usd": 246120 } }

Errors: 401 unauthenticated, 404 port not found, 429 daily query limit exceeded.

POST/calculate-matrix

Compute an origins × destinations distance/duration matrix. Each cell counts as one query against your daily budget; the matrix is capped at 10,000 cells.

Request body

NameTypeRequiredDescription
originsarrayYesList of { coordinates } or { port_id }
destinationsarrayYesList of { coordinates } or { port_id }
speed_kmhnumberNoVessel speed for duration estimates
resolution_kmenumNoGrid resolution: 5, 10, 20, 50, 100
suez / panama / gibraltarbooleanNoAllow/forbid each strait/canal
vesselobjectNoSame shape as /calculate-route
fuel_price_usd_per_tonnenumberNoUsed for cost estimates

Response 200

{ "success": true, "resolution_km": 20, "cells": 9, "origins": [ ... ], "destinations": [ ... ], "rows": [[{ "distance_km": ..., "duration_hours": ... }, ...], ...], "units": { "distance": "km", "duration": "hours" } }

Errors: 422 empty/oversized matrix, 429 exceeds remaining daily budget.

GET/route/{slug}

Fetch a saved port-to-port route by its SEO slug.

Path parameters

NameTypeRequiredDescription
slugstringYesRoute slug, e.g. new-york-to-london

Returns 404 if the slug is unknown.

GET/example-routes

Return a set of example route requests useful for getting started.

GET/route-history

Return the authenticated caller's most recent route calculations.

Query parameters

NameTypeRequiredDescription
limitintegerNoMaximum number of entries to return

Ports

GET/search-ports

Autocomplete port names for use as route origins/destinations.

Query parameters

NameTypeRequiredDescription
qstringYesSearch term (port name prefix)
limitintegerNoMaximum number of results

Response 200

[ { "port_name": "Rotterdam", "lat": 51.95, "lon": 4.14, "port_id": 2451, "country": "NL" } ]

Emissions

POST/v1/emissions/sea

Estimate GLEC-aligned (ISO 14083) well-to-wake greenhouse-gas emissions for a navigable sea route. The route is derived from the origin/destination the same way as /calculate-route. Counts against your daily query limit.

Request body

NameTypeRequiredDescription
routeobjectYesorigin & destination, each as { "port_id": 123 } or { "lat": .., "lon": .. }; optional avoid[] (seca, piracy, suez, panama, gibraltar, malacca, dover, bering, magellan, babelmandeb, kiel, corinth, northwest, northeast) and resolution_km
cargoobjectNoteu (> 0) for containers, or mass_tonnes (> 0) otherwise; container_type, reefer (default false)
vesselobjectNotype (container|feeder_container|deep_sea_container|dry_bulk|tanker|general_cargo|ro_ro|vehicle_carrier|ferry); optional imo, name, capacity_teu, deadweight_tonnes, fuel_type
fuelobjectNoconsumed_tonnes (> 0) and type (HFO|VLSFO|MGO|MDO). Supplying it enables the fuel-based method
calculationobjectNomethod (auto|fuel_based|activity_based|carrier_intensity|default_maritime, default auto), boundary (TTW|WTT|WTW, default WTW)
frameworkobjectNoname (default "GLEC"), version (default "3.0")
carrierobjectNoOptional carrier { code, name } for carrier-intensity factors

Example request

{ "route": { "origin": { "port_id": 2451 }, "destination": { "lat": 1.29, "lon": 103.85 } }, "cargo": { "teu": 1200, "reefer": false }, "vessel": { "type": "container" }, "fuel": { "consumed_tonnes": 410.2, "type": "HFO" }, "calculation": { "method": "auto", "boundary": "WTW" } }

Response 200

{ "calculation_id": "em_9f2c1a...", "status": "ok", "framework": { "name": "GLEC", "version": "3.0" }, "method": "fuel_based", "route": { "distance_km": 15320.4, "distance_nm": 8272.9, "provider": "searoutesnav" }, "activity": { "value": 18384480, "unit": "TEU_KM" }, "emissions": { "ttw_kg_co2e": 1281000, "wtt_kg_co2e": 264000, "wtw_kg_co2e": 1545000, "wtw_tonnes_co2e": 1545.0 }, "factor": { "id": "glec_container", "value": 0.084, "unit": "kg_co2e_per_teu_km", "boundary": "WTW", "source": "GLEC", "version": "3.0" }, "data_quality": { "level": "vessel_class", "confidence": "medium" }, "compliance_statement": "GLEC-aligned. ISO 14083 reference." }

Errors: 401 unauthenticated, 404 no compatible emission factor, 422 validation error, 429 daily limit exceeded, 503 emissions service not initialized.

POST/v1/emissions/sea/test

Dry-run an emissions request: validate the inputs and preview which method, factor and boundary would be used, without running the calculation or consuming any quota. Accepts the same body as /v1/emissions/sea.

Response 200

{ "valid": true, "would_calculate": true, "method": "fuel_based", "strategy_reason": "fuel.consumed_tonnes supplied", "boundary": { "requested": "WTW", "effective": "WTW" }, "data_quality": { "level": "vessel_class", "confidence": "medium" }, "factor": { "id": "glec_container", "boundary": "WTW", "source": "GLEC" }, "notes": [], "improvements": ["Provide vessel.imo for vessel-specific factors"] }

Errors: 401 unauthenticated, 422 undecodable JSON, 503 emissions service not initialized.

Statistics

GET/route-statistics

Return aggregate route metrics.

GET/cache-statistics

Return route cache and deduplication metrics.