User guide
Port Flow gives a real-time view of maritime flows across 51 strategic ports (ARA, bunkering, LNG export). This page explains how to read the dashboard, who benefits, and how to integrate the data into your pipelines.
Who it's for
- Commodity traders (oil, LNG, chemicals) — accurate ETAs and congestion indices feed pricing models. The platform's primary target.
- Freight forwarders — early warning on demurrage exposure, routing decisions.
- Marine insurers — anomaly detection (loitering, abnormal dwell), risk pricing.
- Data scientists / quants — historical feed for macro strategy backtesting (port activity = economic proxy).
Read the dashboard in 30 seconds
- Port selector top-right — switch the observed port. The native name shows in parentheses when the active language differs (e.g. Antwerp (Antwerpen), Hamburg, الفجيرة).
- Language selector next to it — 8 business languages: FR, EN, NL, DE, ES, AR (with auto RTL), ZH, JA.
- All / Tankers toggle — instantly filters the map and counters to the 5 tanker sub-classes (crude, product, chemical, LNG, LPG).
- KPI row — total vessels, stationary (congestion proxy), underway, moored, inbound/h, active voyages tracked.
- Map — color = AIS category, size = state. Dashed rectangles are named zones (anchorage, berth, channel).
- Active voyages — table sorted by predicted ETA. The "broadcast ETA" column is what the crew entered; compare against the model's deltas.
- ETA precision — our model's RMSE vs the broadcast ETA's RMSE. This is the main quality indicator.
- Anomalies — vessels at anchor abnormally long for their class. Critical to monitor for congestion or operational oddities.
- 6-hour flow — inbound / outbound / stationary over the last 6 hours. Short-term trend.
ETA precision page
Accessible via the ETA precision button or /precision. Public view aimed at demonstrating model quality to prospects. Three key indicators: model RMSE, broadcast RMSE, % gap. List of the 50 most recent closed voyages with error in hours (green < 1h, amber < 3h, red beyond). Methodology at the bottom. 7/30/90-day window filter.
API integration
Public API at /api/v1, authenticated via bearer token. OpenAPI spec at /api/v1/openapi.json.
# Generate an API key from /account (Starter plan and above), # then use it as a Bearer token: # List ports curl -H "Authorization: Bearer YOUR_API_KEY" \ https://portflow.uk/api/v1/ports # Rotterdam snapshot curl -H "Authorization: Bearer YOUR_API_KEY" \ https://portflow.uk/api/v1/ports/rotterdam/snapshot # Active tanker voyages curl -H "Authorization: Bearer YOUR_API_KEY" \ "https://portflow.uk/api/v1/ports/rotterdam/voyages/active?tankersOnly=1"
Available endpoints: /ports, /ports/{id}/snapshot, /ports/{id}/vessels, /ports/{id}/voyages/active, /ports/{id}/voyages/closed, /ports/{id}/anomalies, /webhooks.
Webhooks (alerts)
Subscribe to an event to receive an HMAC-SHA256-signed POST when a threshold is crossed.
# Subscribe to congestion > 30 stationary vessels at Rotterdam
curl -X POST -H "Authorization: Bearer your-secret-token" \
-H "content-type: application/json" \
-d '{
"url": "https://your-app.example/hooks/port-flow",
"port": "rotterdam",
"event": "congestion.threshold",
"threshold": 30
}' \
https://portflow.uk/api/v1/webhooks
# Response — keep the secret to verify the signature
{ "id": "sub_…", "secret": "…", "url": "…", … }Headers on every delivery: X-Port-Flow-Event and X-Port-Flow-Signature: t=<ts>,v1=<hex> (HMAC-SHA256 of the timestamp-prefixed payload). Receiver-side verification: hmac_sha256(secret, "{ts}.{body}").
Supported events: congestion.threshold / congestion.cleared, anomaly.detected, voyage.arrived.
Known limitations
- AIS coverage is weak in the Mediterranean and Persian Gulf with aisstream.io (community network). Algeciras, Fujairah, Ras Laffan often show few or no vessels in v1. Fix: switch to a commercial provider (Spire, Orbcomm) — on the roadmap.
- Cargo classification at ~85% (tankers) / ~95% (containers). False positives on unnamed vessels.
- On worker startup, a 60-second grace period prevents already-present vessels from counting as "inbound". Inbound/h KPIs naturally calibrate afterwards.
- ETA model v2 (distance/SOG + seasonal correction + congestion + weather). Beats the broadcast ETA on voyages > 6h; less of an edge on short voyages.
- Multi-regime sanctions screening built in (UKSL + OFAC + UN-SC + EU) — see methodology page. Customers can also layer their own lists via the API.
Deployment checklist
- Create an aisstream.io.
- cp .env.example .env.local, fill in AISSTREAM_API_KEY and PORT_API_TOKENS.
- npm install && npm run dev.
- Check the AIS Live banner top-right (green = stream incoming).
- Wait 60s + a few minutes for voyages to start opening (depending on traffic).
- The /precision page will show numbers after the first closed voyages (predicted ETA + actual arrival).