Home → Blog

You need a reliable way to programmatically check port congestion for Rotterdam (NLRTM) so you can adjust vessel ETAs, allocate yard resources, or pre-book feeder capacity. By the end of this guide you will query the FreightPulse GET /api/v1/port-congestion endpoint for Rotterdam using Python, interpret the returned congestion fields correctly, and wire them into transportation operations that depend on lagged, daily AIS-derived metrics.

What this API returns for Rotterdam and how to use it

The FreightPulse port congestion endpoint provides a daily, lagged signal derived from IMF PortWatch (UN Global Platform AIS data). It compares the most recent 7-day average port calls to a 90-day baseline for the same port. This is not a live AIS wait-time feed and does not measure anchorage or berth queue length. For Rotterdam, you will query port=NLRTM and interpret three key fields:

Illustration: API to Check Congestion at Rotterdam

Operationally, consider this a macro congestion indicator suitable for planning buffers, flagging risk, or trend reporting—not for real-time dispatch decisions.

Authentication, quotas, and request format

Authentication uses an HTTP header: X-API-Key: YOUR_API_KEY. Guests without a key are allowed 100 requests per day per IP. Every response is wrapped in an envelope like {"success": true, "data": {...}} with a top-level meta.request_id for traceability. The endpoint and parameters for Rotterdam:

There is no separate, official fixture JSON published for NLRTM beyond the live response format shown below. Data updates daily but are lagged approximately 6–7 days relative to calendar time.

Quickstart with cURL and field mapping

Copy and run the cURL below to retrieve the most recent Rotterdam congestion snapshot:

curl -H "X-API-Key: YOUR_API_KEY" "https://freightpulsehq.com/api/v1/port-congestion?port=NLRTM"

Official sample JSON (copying field names and values exactly):

{
"success": true,
"data": {
"results": [
{
"port": "Rotterdam",
"locode": "NL RTM",
"country": "The Netherlands",
"congestion": "moderate",
"as_of": "2026-10-09",
"metrics": {
"recent_avg_portcalls_per_day": 84,
"baseline_avg_portcalls_per_day": 84.5,
"ratio_vs_baseline": 0.99
}
}
],
"global_summary": {
"ports_high_congestion": 0,
"ports_moderate": 1,
"ports_low": 0
},
"meta": {
"source": "IMF PortWatch (portwatch.imf.org) - UN Global Platform AIS data",
"data_lag_days": "~6-7 (daily updates, not real-time)",
"methodology": "congestion level is an approximation: last 7 days' avg port calls vs 90-day baseline for the same port. Does not measure vessel wait/anchorage time."
}
},
"meta": {
"request_id": "1fc29aad-ed56-47a8-bdaa-f7a4e6745c09"
}
}

How to read this:

Python integration for Rotterdam (NLRTM)

The snippet below queries Rotterdam once, parses the congestion category and ratio_vs_baseline, and applies a simple policy mapping to produce scheduling buffers. Adjust the thresholds to your internal standards; values here only demonstrate how to read and use the fields.

import os
import time
import requests

API_URL = "https://freightpulsehq.com/api/v1/port-congestion"
PORT = "NLRTM"
API_KEY = os.getenv("FREIGHTPULSE_API_KEY", "YOUR_API_KEY")

def fetch_rotterdam_congestion(session: requests.Session) -> dict:
resp = session.get(
API_URL,
params={"port": PORT},
headers={"X-API-Key": API_KEY},
timeout=20
)
resp.raise_for_status()
payload = resp.json()
if not payload.get("success"):
raise RuntimeError("API returned success=false")
results = payload.get("data", {}).get("results", [])
if not results:
raise ValueError("No results for NLRTM in response")
return results[0]

def buffer_minutes_for(congestion: str, ratio: float) -> int:
# Example policy:
# - Start with ratio-based increments
# - Override with categorical floor if needed
ratio_buf = 0
if ratio < 0.95:
ratio_buf = 10
elif ratio < 1.05:
ratio_buf = 20
else:
ratio_buf = 35

cat_floor = {
"low": 10,
"moderate": 20,
"high": 45
}.get(congestion.lower(), 20)

return max(ratio_buf, cat_floor)

def main():
with requests.Session() as session:
data = fetch_rotterdam_congestion(session)
port = data.get("port")
locode = data.get("locode")
congestion = data.get("congestion")
as_of = data.get("as_of")
metrics = data.get("metrics", {})
ratio = metrics.get("ratio_vs_baseline")

print(f"Port: {port} ({locode}), as_of={as_of}")
print(f"Congestion: {congestion}, ratio_vs_baseline={ratio}")

minutes = buffer_minutes_for(congestion, float(ratio))
print(f"Recommended scheduling buffer: {minutes} minutes")

if __name__ == "__main__":
# Simple retry on transient network failures
for attempt in range(3):
try:
main()
break
except (requests.RequestException, ValueError) as e:
if attempt == 2:
raise
time.sleep(2 ** attempt)

Notes for production use:

Operational guidance: Rotterdam-specific usage in transportation workflows

Because the Rotterdam signal is a smoothed 7-day average vs a 90-day baseline, it’s best applied to tactical planning and service-level buffers rather than to minute-by-minute berth management. Some practical patterns:

Do not conflate this with live AIS wait times or queue lengths. If you need to react to sudden berth closures or weather in real time, pair this with your operational feeds and TOS alerts.

Data handling: dates, caching, and comparisons

Dates and intervals:

Caching and re-use:

Comparisons and thresholds:

Error handling and edge cases

While integrating, plan for:

Security, observability, and rollout checklist

Security:

Observability:

Rollout steps:

Reference: official cURL and field names

Use the documented header and query parameter exactly as shown below. This is the same call demonstrated earlier, repeated here for easy copy-paste during implementation:

Key fields to persist for Rotterdam:

FAQ

Is this live AIS wait-time data?
No. It is a lagged (~6–7 days) metric based on IMF PortWatch AIS-derived aggregates. It compares recent 7-day average port calls to a 90-day baseline and does not measure anchorage or berth wait times.

What’s the correct port code for Rotterdam?
Use port=NLRTM in the query parameter. The response may include a locode formatted as “NL RTM.”

How often should I poll the endpoint?
Once per day is sufficient. The dataset updates daily with a 6–7 day lag, so more frequent polling won’t yield fresher values and may consume your guest quota (100 requests/day per IP without a key).

How do I authenticate?
Send your key in the header X-API-Key: YOUR_API_KEY. All responses are wrapped in {"success": true, "data": {...}} so check the success flag before use.

Can I use these numbers to quote live freight rates?
No. Do not treat this as a current price signal. It’s a congestion indicator and should not be presented as today’s freight-rate USD fare.

Ready to integrate Rotterdam congestion into your transportation stack? Create an API key and start testing today: Register. For parameter details and endpoint behavior, see the Documentation.