Ask someone when a ship "arrives" at a port and you'll get an answer that sounds obvious. It arrives when it gets there. When it docks. When the cargo comes off. When the captain stops driving.
All of these are different events. And if you're building anything that depends on knowing where ships are and what they're doing — a logistics dashboard, an emissions tracker, a demurrage calculator, a trading signal — the difference between them is the difference between software that works and software that quietly lies to you.
This is a piece about what a port event actually is, why the timestamp on it is more philosophically loaded than it has any right to be, and how to pull clean data out of an API without tripping over the assumptions baked into the question.
The fridge magnet version
Here's the mental model most people start with: ships sail around, and every so often one of them enters a port. The port notices. A row gets written somewhere. That row is a "port event."
That model is wrong. Not approximately wrong — wrong in a way that will burn you the first time you trust it.
In reality, no port "notices" anything. There is no welcome desk at the edge of Singapore harbor. What actually happens is this: commercial vessels of any size that matters — the rule is nominally 300 gross tons on international voyages, 500 GT on domestic ones, plus all passenger ships, but the operational answer is "anything commercially significant" — are required by SOLAS to broadcast their position, speed, heading, and identity. Fishing fleets and pleasure craft are mostly invisible. The protocol is called AIS (Automatic Identification System), broadcasting on two dedicated VHF channels (161.975 and 162.025 MHz) in the maritime band — pure digital TDMA, not voice, distinct from the channels humans actually talk on. Smaller vessels often carry the lighter Class B variant voluntarily.
Coastal stations receive these broadcasts within roughly 40–60 nautical miles of shore; satellites fill in the open ocean, with gaps depending on constellation coverage and how badly signals collide in busy lanes. The aggregate raw stream runs into the hundreds of millions to over a billion messages per day globally — scattered across the planet with no semantic meaning attached. Each message carries an MMSI, a nine-digit identifier that is the actual join key if you ever want to correlate a port event back to the raw position stream.
A "port event" is something a computer infers from that stream. It's a derived fact, not a recorded one. (The port events in our own API come from port-call records rather than from our own AIS geofencing. The same questions apply to them.)
Inferring a thing that didn't actually happen
To turn position fixes into port events, you need two things: a definition of what a port is in geographic terms, and a rule for when a ship has interacted with it.
The first one sounds easy and isn't. Ports aren't points; they're sprawling, irregular regions that include anchorages outside the breakwater, terminal berths inside it, sometimes a river pilot boarding area many kilometers offshore, and frequently a chunk of open sea where ships wait — sometimes for days, sometimes for weeks — for a berth to free up. Singapore's anchorage zones extend well into the strait. Houston's ship channel runs roughly fifty nautical miles from open water to the inner turning basin, serving a string of independently operated terminals that are colloquially "the port" but legally several different things.
So the first decision is: where does the port end? Serious port-event systems use polygons — hand-drawn or algorithmically refined boundaries, layered: an outer "port limits" polygon, inner anchorage polygons, and individual berth polygons. A vessel crossing one of these boundaries generates a candidate event. The providers who skip the layering and use a single outer polygon are selling you noise — every anchorage stay becomes "arrived," every drift across the line becomes a fresh port call.
The second decision is what counts as a crossing. A naive "is the ship inside the polygon?" check produces nonsense: GPS noise causes vessels at the edge to flicker in and out, generating dozens of fake arrival/departure pairs per hour. Real systems apply hysteresis (you have to be inside for N minutes before it counts) and speed thresholds — a moored ship reports near-zero speed-over-ground, though you have to filter the AIS sentinel codes near 102 knots. The standard reserves 1023 (102.3 knots) for "SOG unavailable" and 1022 (≥102.2 knots) as an overflow marker; both will otherwise inject impossible speeds into your data.
What comes out the other end is an event stream: arrival and departure, plus berth events in systems that track berth polygons. Each one with a timestamp.
And the timestamps are where it gets interesting.
Why sub-minute matters
Query a port events endpoint for Singapore, say /portevents/port/SGSIN using the UN/LOCODE, and look at how finely the timestamps are resolved. The hour, the nearest five minutes and the second are very different answers.
The demurrage case is the one that matters most, and it gets the least attention. Emissions models get the press; trading signals get the venture money. But the demurrage clock — the meter that charges a charterer for keeping a ship waiting — starts ticking at a contractually defined moment, often tied to Notice of Readiness tendering at the port limits. NOR is a document the master serves, not an AIS event; but AIS-derived port event timestamps are increasingly used as corroborating evidence, and a charterer's lawyer disputing a \$40,000-per-day demurrage claim on a Capesize bulker (an illustrative figure — real rates swing widely with the market) will absolutely cross-reference your data against the NOR timing. If your provider rounded to the nearest hour, you have just introduced uncertainty into someone's evidence.
Emissions estimates drift quietly across a fleet when timestamps are coarse, and the trading case is the most fragile of all: watching how fast ships cycle through berths at Port Hedland is, in effect, watching iron ore loading throughput in something close to real time. If your berth timestamp is fuzzy by twenty minutes, your derivative is noise.
The reason the data can be sub-minute is that AIS Class A position reports arrive every 2 to 10 seconds for a vessel underway — strictly, every 10 seconds at port-approach speeds (0–14 knots), every 6 seconds in the 14–23 knot range, every 2 seconds above 23 knots, with course changes collapsing the interval to 2–3 seconds across the board. Class B transponders report every 30 seconds when moving, dropping to 3 minutes when slow; newer Class B+ devices match Class A rates. Stationary vessels at anchor with reported SOG ≤ 3 knots drop to once every 3 minutes — though GPS noise will sometimes keep an anchored ship in the faster-reporting mode anyway, which is one reason boundary flicker is so persistent.
In practice? A lot of providers downsample for storage and the precision dies upstream. If all your timestamps end in :00:00, that's your answer.
Querying it without tripping
The endpoint is GET /portevents/port/{unlocode}. UN/LOCODE is the five-character code maintained by UN/CEFACT — two letters of country code, three characters of location, occasionally including digits (GB2WB is a real one). SGSIN is Singapore. NLRTM is Rotterdam. USNYC is New York; though if you're querying the New York/New Jersey container complex specifically, your provider may use USNWK (Newark) for the New Jersey terminals — the boundary varies by data source, and "the port of New York" turns out not to be one thing. UN/CEFACT publishes updates twice a year, so if you're building something that runs unattended for years, track the changes.
The first thing that'll burn you is reading more into an event than it says. An arrival can be logged while the vessel is still miles from any berth, anchored, waiting. A departure means it left. Our port events record arrivals and departures only; time alongside is not reported separately, so arrival-to-departure includes any wait at anchor. That is not the same as "time spent loading", and the difference can be days. Events are kept for 31 days.
Coverage is uneven. Fishing fleets, very small craft, and naval vessels — which are SOLAS-exempt and may suppress AIS in operational contexts, though plenty of warships and auxiliaries transmit routinely in commercial ports — are inconsistent at best. Query a fishing port and the silence is the answer.
And events arrive out of order. Satellite AIS latency means transmissions from quieter ports can be buffered until the next overhead pass; for busy ports the more common cause of late arrivals is provider ingestion batching. Either way: your code should not assume chronological order, and providers that stamp ingestion time instead of transmission time will quietly destroy your analysis.
The thing under the thing
"A ship arrived at a port" is not an observed fact. It's a model. Somewhere between the radio signal and the JSON, a decision was made about where the port ends and what counts as being inside it. That decision is invisible in the response, and it shapes everything downstream.
The nice thing about port events, compared to most derived data, is that the questions are easy to write down: where does the port end, what counts as inside, and which clock produced the timestamp. Ask them of any source you use, ours included.
You just have to remember that the ship didn't arrive. Something decided it had.


Top comments (0)