---
title: "Find a port by name, country, or UN/LOCODE (no key)"
method: GET
path: "/api/v1/ports"
tags: ["Port lookup"]
---

# Find a port by name, country, or UN/LOCODE (no key)

`GET /api/v1/ports`

## Request

- Base URL: `https://arcnautical.com`
- URL: `https://arcnautical.com/api/v1/ports`
- Auth: none required

Resolves a port name to the UN/LOCODE that route.origin and route.destination require. Requires NO API key. Covers the ports the routing graph can compute against, so a code returned here is guaranteed to be routable. An exact LOCODE match is returned first, which makes this also the way to confirm a code you already hold. Every result carries match_score and match_type so a caller can tell a confident resolution from a weak one programmatically rather than trusting position in the list.

## Query parameters

- `query` string, required
- `limit` integer

## Response `200`

Matching ports, best match first. An empty array means no port matched.

- PortSearchResponse: Ports matching the query, best match first. Returned by the keyless GET /api/v1/ports.
  - `ports` Port[], required
    - `locode` string, required: Five-character UN/LOCODE. This is the value route.origin and route.destination take.
    - `name` string, required
    - `country` string, required
    - `country_code` string, required: ISO 3166-1 alpha-2 country code.
    - `lat` number, required
    - `lon` number, required
    - `match_score` integer, required: How strong this match is, 0-100. Results are ordered by it. Publishing it means a caller can detect a weak resolution instead of taking the first row: a query that only matched the COUNTRY name scores 20, and auto-selecting that is almost always wrong.
    - `match_type` 'exact_locode' | 'exact_name' | 'name_prefix' | 'name_word' | 'locode_partial' | 'name_partial' | 'country', required: What matched. exact_locode (100) and exact_name (95) are safe to auto-select; country (20) means the query appeared in the country name only and should be shown to a human. exact_name, name_prefix and name_word also cover the port's official local and former names, so lisboa is an exact_name match on Lisbon (PTLIS).

## Other responses

- `422`: Missing or too-short query, or a limit outside 1-100. Uses the standard ApiErrorEnvelope.

---

[API](https://skmtc.dev/arcnautical/apis/arcnautical-api.md) · [All operations](https://skmtc.dev/arcnautical/apis/arcnautical-api/llms.txt) · [OpenAPI document](https://skmtc.dev/arcnautical/apis/arcnautical-api/revisions/40cd2659cdd7?raw)
