Three endpoints that count rather than list: how much traffic a port handled over a period, how its berths performed, and what happened at one berth in particular.Port Insights answers who and when. This answers how many, how long, and how busy.
GET /v1/analytics/ports/{id_type}/{id}/arrivals-departures
How many vessels arrived and left over this period, broken down how I asked?
GET /v1/analytics/ports/{id_type}/{id}/berths
Which berths does this port have, and how long do vessels sit at them?
GET /v1/analytics/ports/{id_type}/{id}/berths/{berth_id}
Everything about one berth, in one response
These endpoints sit behind a base path of their own
Port Analytics is served by our maritime analytics service, which the gateway reaches at /maritime-analytics. Call it at https://api.polestar-production.com/maritime-analytics/v1/analytics/ports/.... The reference pages show the path the service sees, without that prefix, because every other Insights endpoint carries its service prefix in the path itself and these carry it in the base URL.
id_type is id for the internal UUID or unlocode for the UN/LOCODE, and {id} is the value. If your data already carries a UN/LOCODE you can skip the port search entirely.
arrivals-departures counts port-level movements and buckets them. group_by and period_aggregation are both required, and the combination decides the shape of the response:
group_by
period_aggregation
What you get
Chart it as
NONE
DAILY, WEEKLY, MONTHLY, QUARTERLY or YEARLY
One data point per period, each holding a single combined arrival and departure count
A line over time
VESSEL_TYPE
any period
One data point per period, each holding one item per vessel type
A stacked or clustered bar
VESSEL_TYPE
NONE
A single data point holding one item per vessel type, summed across the whole range
A donut or a pie
When group_by is NONE, every items array holds exactly one element with group_by_key set to "none". Vessel types with nothing in a period are left out of that period rather than returned as zero.Narrow the traffic with vessel_types, vessel_class and flag_codes, all repeatable. The totals object is calculated after every filter has been applied, so it agrees with the data array rather than describing the unfiltered port.Alongside the counts the response carries dwell_series, average and median hours at berth per period, and top_visitors, the vessels calling most often over the range. top_visitors returns ten entries by default and up to 50.
The period key is the end of the period, not the start
period_key is always the last calendar day of its bucket: the Sunday that closes a week, the last day of a month or quarter. It stays the end of the full period even when your date_end falls part way through one, so a chart axis built from it will not shift as you extend the range.
berth_type on this endpoint filters the dwell series alone. Arrival and departure counts ignore it. Pass it when you want dwell figures for container berths and the movement totals for the whole port.
Port Analytics counts commercial vessels only, across 11 categories: Bulk Carrier, Bulk/Oil Carrier, Chemical Tanker, Container (FC), Dry Cargo Barge, General Cargo, Liquified Gas Carrier (LNG), Oil Tanker, Other Tanker, Specialised Carrier and Tank Barge.Zone Analytics counts all 16 categories, commercial and not. A zone drawn over a port will not return the same numbers, and the difference is coverage rather than data quality.
berths returns every berth at a port, grouped by terminal operator, with dwell statistics for the period you ask for. Dwell time is the hours a vessel spends at a berth, measured from arrival_time to departure_time, and each berth reports it as minimum, average, median and maximum across the visits in range.
The kpi block is the summary card: total_berths, min_dwell_time, max_dwell_time and terminal_operators. Under it, terminals holds one entry per operator, each with its berths and their specifications: structural type, facility, length, maximum LOA, maximum deadweight and depth at low water.Filter with berth_type for the structural kind, Quay or Jetty, and terminal_name for the operator. Paging is by berth, limit defaulting to 500.
berths/{berth_id} returns everything a berth page needs in a single response, under three top-level keys: berth_details, dwell_time_series and occupancy:
berth_details, the specification card. The static fields do not move with your query; avg_dwell_time and median_dwell_time are recalculated for your date range and flag filter
dwell_time_series, the chart points. A period with no visits returns null rather than 0, so an empty week is visibly empty rather than a dip to zero
occupancy.visits and occupancy.gaps, the individual vessel visits and the idle time between them
occupancy.top_vessels, ranked by total dwell across the whole range
vessel_flag takes ISO 3166-1 alpha-3 codes here. The occupancy timeline pages by day rather than by record: page_size is a number of days, defaulting to 14.
The response tells you how to render itself
The query block carries two values we derive from the length of your date range, so you do not have to work out the thresholds yourself. view_mode is gantt for a range of 90 days or less and table beyond that. dwell_series_granularity is daily for 30 days or less and weekly beyond that. Draw the visits-and-gaps timeline when view_mode is gantt, and the top-vessels table when it is table, where gaps comes back empty.
Two endpoints on this site report port arrivals and departures, and they return different things.
Returns
Use when
GET /zone-port-insights/v1/zone-and-port-traffic/{id_type}/{id}
Every movement event, one row per arrival or departure
You need the movements themselves: a timeline, an audit trail, a per-vessel history
GET /v1/analytics/ports/{id_type}/{id}/arrivals-departures
Counts of those movements, bucketed and grouped
You need volume: a trend, a distribution, a comparison between periods
The same split holds on the berth side. port-berth-traffic returns BERTH_ARRIVAL and BERTH_DEPARTURE events; the two berth endpoints here return occupancy and dwell built from them.
date_start and date_end are required on all three endpoints, inclusive, and yyyy-MM-dd. We treat a date_end in the future as today (UTC). Six rules apply to the berth endpoints and are worth respecting everywhere:
Code
Status
Condition
ERROR_300
400
date_start is after date_end
ERROR_301
400
id_type is neither id nor unlocode
ERROR_302
404
No port matches the identifier
ERROR_303
400
The range spans more than two years
ERROR_304
400
date_start is before 2025-01-01
ERROR_305
404
No berth matches the berth_id
Historical data starts on 2025-01-01. A range reaching back before it is rejected rather than truncated.