Five endpoints that answer questions about a place instead of a ship: which ports exist, who is in one now, who is on the way, who arrived and left, and what happened at the berths.Find a port first. Everything else takes its identifier.
Which ports can I see, and what is this one called?
GET /zone-port-insights/v1/vessels-in-zone-or-port/{id_type}/{id}
Who is inside right now?
GET /zone-port-insights/v1/inbound-vessels/{id_type}/{id}
Who is on the way here?
GET /zone-port-insights/v1/zone-and-port-traffic/{id_type}/{id}
Who came and went over this period?
GET /zone-port-insights/v1/port-berth-traffic/{id_type}/{id}
What happened at the berths?
The search, vessels-in-zone-or-port and zone-and-port-traffic serve zones as well, which is why they are documented in the shared Zones & Ports section. The identifier you pass decides whether you get a port answer. Inbound vessels and berth traffic are Port & Trade endpoints alone.
Five filters help you find a port, all optional and combinable: name_contains (case-insensitive substring), unlocode, country_code (three letters), sub_division_code, and wpi_number for the World Port Index.The search returns zones and ports in one list, so a name match can bring back an area as well as the port. types and sub_type filter by kind of area; Zone & Port Types lists the port types. For one port in full, pass its internal id to GET /zone-port-insights/v1/zones/{id}.
The other four endpoints carry {id_type}/{id} in the path, and id_type tells the service how to read the id that follows.On vessels-in-zone-or-port, zone-and-port-traffic and port-berth-traffic it is ID or UNLOCODE, matched case-insensitively, which is the spelling the examples below use. inbound-vessels declares the pair in lower case, id and unlocode, and its own example follows suit.
UN/LOCODE is the shortcut: if your data already carries one, you can skip the search entirely.
An out-of-scope port returns 403, not 404
We check access against the ports your account is entitled to. An identifier outside them comes back as 403, so the two responses mean different things. 404 means no such port exists; 403 means it exists and your subscription does not cover it. The second is a commercial question, not a bug in your code. Both codes are declared on vessels-in-zone-or-port, zone-and-port-traffic and port-berth-traffic.
vessels-in-zone-or-port returns what is inside the boundary at the moment of the call. Each vessel carries when it entered, the position it entered at, and its latest known position:
Paging is the only filter. For a congestion or occupancy view, compare each vessel's latest position against its entered position to see which have not moved since they arrived.
inbound-vessels returns the vessels naming this port as their destination in their AIS messages. Each entry carries the vessel's identity (name, type, IMO, MMSI, callsign and flag), the destination we parsed, the ETA it reported, and its latest position.The destination field is free text, typed aboard the vessel. We clean it and match it against the port library to work out which place it names. A vessel can retype it or change course, and plenty never arrive.
Four filters narrow it, all optional:
reported_eta_gte and reported_eta_lte bound the reported ETA, ISO-8601 UTC. reported_eta_lte cannot be earlier than reported_eta_gte
last_destination_update_after drops destinations we parsed before the moment you give, which is how you ignore stale intent
exclude_arrived leaves out vessels that have already reached the port, and defaults to true
Reported, not observed
Everything on this endpoint comes from what a vessel says about itself. zone-and-port-traffic and port-berth-traffic report what we watched happen instead, so the two will not agree.
zone-and-port-traffic takes a time range and, for a port, returns the port-level movement events:
Event
Means
PORT_AREA_ARRIVAL
The vessel enters the port area
PORT_ARRIVAL
The vessel has stopped inside the port area
PORT_DEPARTURE
The vessel is moving again but still inside the port area
PORT_AREA_DEPARTURE
The vessel exits the port area
timestamp_start is required: UTC, yyyy-MM-ddTHH:mm:ss, optional trailing Z, and it cannot be in the future. timestamp_end is optional and defaults to the time of the request, and we treat a value in the future as the current time. Filter with event_type, repeatable.
The berth events are deliberately not here. Ask port-berth-traffic for those.
For counts rather than movements, use Port Analytics
This endpoint returns one row per movement. Port Analytics answers the same question as a total: arrivals and departures bucketed by day, week, month, quarter or year, and split by vessel type if you ask.
port-berth-traffic returns BERTH_ARRIVAL and BERTH_DEPARTURE for one port, each event carrying the berth it happened at. Same time-range parameters as above.
Two event sets, two endpoints, on purpose
Each operation validates event types against its own set and rejects anything outside it. Port-area, port and zone events belong to zone-and-port-traffic, and the berth pair to port-berth-traffic. Asking one endpoint for another's events returns an error, so a typo fails loudly instead of looking like no data.