You need a numeric port_id to query congestion or expected arrivals, but you often only have a human-readable port name. By the end of this guide you’ll resolve a name into a stable port_id via Vessels API’s AIS Port Directory, handle the JSON envelope safely, cache the mapping, and then use that id with congestion or expected-arrivals endpoints—without burning extra quota.
Why resolve a port name into port_id first
Most operational endpoints in Vessels API take a port_id, not a free-text name. Names can be ambiguous and localized; ids are stable and efficient. The AIS Port Directory endpoint translates a name into its canonical id so you can:
- Prevent wasted requests to congestion or arrivals for the wrong location.
- Cache a compact id-to-name mapping for repeated use in your app.
- Keep user input flexible (name search) while your backend remains id-driven.
The directory call is lightweight and designed to be cached. Once you have the id, use it across congestion and arrivals without another lookup until your cache refresh window.
Endpoint and authentication
Base URL: https://vessels-api.com/api/V1. Authentication is via an X-API-Key header on every request. Response bodies are wrapped in a consistent envelope with these top-level fields:
- status: HTTP-like status code surfaced in the body.
- success: boolean indicating whether the operation succeeded.
- message: diagnostic text you can log or display for failures.
- data: the actual payload for a successful call.
Directory requests are made to GET /ports. Full reference is in the Documentation.
Request the port list (and resolve a port_id)
Below is a live example that returns the directory payload. You’ll extract the id you need from data and cache it in your app.
curl -H "X-API-Key: YOUR_API_KEY" \
"https://vessels-api.com/api/V1/ports"
Key handling notes:
- Always check success before using data. On failure, inspect message and do not assume data is present.
- When success is true, the data field contains the directory records. Use the attributes shown in the sample above to identify the matching port and read its id.
- If multiple ports match a user’s input, present the options client-side (e.g., autocomplete) and store the chosen port_id.
Python example: call /ports and extract port_id
import os
import requests
API_BASE = "https://vessels-api.com/api/V1"
API_KEY = os.getenv("VESSELS_API_KEY", "YOUR_API_KEY")
def get_ports():
url = f"{API_BASE}/ports"
headers = {"X-API-Key": API_KEY}
r = requests.get(url, headers=headers, timeout=15)
r.raise_for_status()
envelope = r.json()
# Envelope has {status, success, message, data}
if not envelope.get("success"):
raise RuntimeError(f"Directory failed: {envelope.get('message')}")
return envelope.get("data")
def resolve_port_id(ports, name_query):
# Minimal example: exact or case-insensitive match against any provided name fields
# Use the attributes available in the directory JSON returned above.
if not ports:
return None
name_lc = name_query.strip().lower()
for p in ports:
# Replace keys below with actual name fields from the sample you see in /ports data
for key in ("name", "port_name", "display_name"):
n = p.get(key)
if isinstance(n, str) and n.strip().lower() == name_lc:
return p.get("port_id") or p.get("id")
return None
if __name__ == "__main__":
ports = get_ports()
target_name = "Buenos Aires" # Example user input
pid = resolve_port_id(ports, target_name)
if pid is None:
print("No matching port found; show suggestions to the user.")
else:
print(f"Resolved '{target_name}' to port_id={pid}; cache this id for downstream calls.")
Implementation tips:
- Normalize names (trim, lowercase) and consider alternate fields that the directory returns for matching. Use the exact field names you see in the data payload.
- Cache the directory or a name→id mapping with a refresh window suited to your SLA. A daily refresh is typical for directories; tune to your needs.
- Guard against missing values: if a record lacks an expected attribute, skip it rather than failing the entire match process.
Use the id: congestion and expected arrivals
Once you have a port_id, you can query congestion or expected arrivals. There is no geofence path; resolution is always id-driven. The example below demonstrates a numeric congestion output for a specific port and date. If it’s not your target port, follow the same pattern: resolve the id via /ports, then call congestion for that id.
{
"status": 200,
"success": true,
"message": "OK",
"data": {
"port_id": "84",
"port_name": "Buenos Aires",
"period": "7d",
"snapshot": {
"timestamp_utc": "2026-02-09T10:30:00Z",
"vessels_in_anchorage": 14,
"vessels_at_berth": 9
}
}
}
What you should take from the example above:
- It shows a published numeric congestion response for a known port_id (Buenos Aires is id 84 in the sample) on 2026-02-09.
- To reproduce this for any other port, first look up that port’s id via GET /ports, then pass the id into the congestion or expected-arrivals endpoints.
- Time semantics: treat dates in responses as calendar dates; when you persist them, store them as ISO 8601 date strings and keep timezone handling consistent in your app. If a timestamp is included in any payload you consume, record the timezone or assume UTC for server-side scheduling.
Error handling, nulls, and idempotent caching
Envelope-first logic saves time. On every response from Vessels API:
- Check success. If false, log message and map to your retry/backoff policy. Do not dereference data.
- If data is present but a field is missing or null, handle it defensively. Prefer default display values (e.g., “Unknown”) on UI and skip-only-once logic in ETL.
- Cache the directory data and your resolved port_id values in a key-value store. Because ids are stable identifiers, cache invalidation is rare, but you should refresh the directory on a schedule that matches your operational tolerance.
- For downstream congestion/arrivals calls, avoid repeated hits for the same port_id and date range by adding a short-lived cache (e.g., minutes) if your UI refreshes frequently.
Build-and-ship checklist
- Register — Starter is $19.99/mo (2,500 calls) with a 7-day trial.
- Copy your X-API-Key and store it as a secret in your CI/CD or config management.
- Call GET /api/V1/ports and cache the mapping you need (e.g., name → port_id).
- Use the resolved port_id in GET /ports/congestion or /port/expected-arrivals for your workflows.
Developer tooling: MCP helpers
If you prefer to explore interactively, the MCP workspace exposes tools prefixed with ports_* to help discover available inputs and outputs. It’s a fast way to experiment with the directory and validate you’re extracting the right id before wiring up your production client.
Operational considerations
- Quotas: Budget your quota for directory bootstrap and periodic refresh. Use cached ids for most calls to keep your spend focused on congestion and arrivals.
- Pagination: If the directory returns paged results in your account, iterate until you have all items you need, or limit to the subset of regions your app supports. Respect the envelope structure while paging.
- Localization: Port names can appear in multiple languages. Match against all name fields provided in data and consider storing canonical and localized variants.
- Auditing: Persist the envelope.status and message on failures for support triage.
FAQ
How do I find the correct port_id when multiple ports share a similar name?
Use the directory fields returned in data (such as any region/country or alternative name attributes shown in the sample) to disambiguate. Present multiple matches to the user and store the chosen id.
What should I do when success is false?
Do not use data. Log message, surface a user-friendly error, and optionally retry based on your policy. For client errors, fix inputs; for transient errors, back off and retry.
Can I query congestion or arrivals by coordinates or geofence?
No geofence path is available. Always resolve the port_id via /ports and use that id for congestion or expected-arrivals.
How often should I refresh my port directory cache?
Directory content is relatively stable. A daily refresh is a common default; adjust to your operational needs or when you detect name changes that matter to your UI.
Where can I see all available fields for /ports?
Review the sample response above and the Documentation. Use the fields as published in your account responses.
Resolve port names to ids once, cache them, and ship congestion or arrivals features with confidence. Start your 7-day trial now: Register.