---
title: "Compare Routes"
method: POST
path: "/api/v1/routes/compare"
tags: ["grandline"]
---

# Compare Routes

`POST /api/v1/routes/compare`

## Request

- Base URL: `https://grandline.luzomi.com`
- URL: `https://grandline.luzomi.com/api/v1/routes/compare`
- Auth: none declared

Returns all four route variants between two ports side-by-side so the
caller can compare distance, canal transits, and steaming time.

Each row in `grandline.port_distances` already carries pre-computed distances
for all four variants (primary / via_suez / via_panama / via_cape), so
a single SELECT delivers the full comparison.

The "canonical" pair is chosen as the row with the shortest primary
distance — variants that are NULL on that row (not all pairs have all
four variants populated) come back as `distance_nm: null`.

`recommended` is the name of the shortest non-null variant — usually
"primary" by definition, but the field is dynamic so future routing
enhancements (sanctions filters, vessel class restrictions) can shift
it without breaking the response schema.

## Query parameters

- `origin` union, required: Origin port ID (int) or port name (str)
  - string
  - integer
- `destination` union, required: Destination port ID (int) or port name (str)
  - string
  - integer

## Response `200`

Successful Response

- RouteCompareResponse
  - `origin_port_id` integer, required
  - `origin_port_name` string, required
  - `destination_port_id` integer, required
  - `destination_port_name` string, required
  - `origin_lat` number, nullable
  - `origin_lon` number, nullable
  - `destination_lat` number, nullable
  - `destination_lon` number, nullable
  - `variants` RouteVariant[], required
    - `name` string, required
    - `distance_nm` number, nullable, required
    - `delta_vs_primary_nm` number, nullable, required
    - `canal_transits` CanelTransit[]
      - `name` string, required
      - `type` string, required
    - `geojson` object, nullable
    - `steaming_days_at_speed` SteamingDayEstimate[]
      - `speed_knots` integer, required
      - `days` number, required
    - `availability` string
    - `note` string, nullable
  - `recommended` string, required

## Other responses

- `400`: Validation error with extra context
- `404`: Resource not found
- `422`: Validation Error
- `429`: Rate-limit exceeded — see X-RateLimit-* headers

---

[API](https://skmtc.dev/luzomi/apis/grandline-api.md) · [All operations](https://skmtc.dev/luzomi/apis/grandline-api/llms.txt) · [OpenAPI document](https://skmtc.dev/luzomi/apis/grandline-api/revisions/4ce06aea012b?raw)
