Home → Blog

You need a reliable way to track New York–New Jersey port congestion with clear, parseable signals you can wire into planning, ETAs, or carrier ops. By the end of this guide, you’ll query FreightPulse for the New York–New Jersey port, interpret the 7‑day vs 90‑day congestion signal, and integrate it into your own system with production-friendly code.

What this congestion metric is (and is not)

FreightPulse exposes a congestion level derived from IMF PortWatch. It is not a live AIS anchorage or wait-time feed. Instead, it compares the last 7 days of average port calls to a 90‑day baseline for the same port. That ratio anchors a qualitative congestion label (low, moderate, high) alongside the date the metric is valid for.

Illustration: New York-New Jersey Port Congestion

This makes the series stable enough for planning and trend analysis while avoiding the volatility of per-vessel delay telemetry. Expect daily updates with a lag of roughly one week from the present day.

Origin catalog facts you should copy into your implementation notes

Endpoint, method, and parameters

Use a simple GET to query congestion for the New York–New Jersey port:

The response is wrapped in an envelope with a boolean success field and a data object containing results and metadata. The congestion result exposes a qualitative label and the exact ratio that drives it, along with an as_of date for the observation window.

Official curl and JSON sample for New York–New Jersey

Copy, paste, and run the curl below. It’s safe to try with or without an API key (guest quotas apply):

Live FreightPulse congestion for New York.
Source: live

cURL:

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

JSON:

{
"success": true,
"data": {
"results": [
{
"port": "New York-New Jersey",
"locode": null,
"country": "United States",
"congestion": "moderate",
"as_of": "2026-10-02",
"metrics": {
"recent_avg_portcalls_per_day": 10,
"baseline_avg_portcalls_per_day": 9.9,
"ratio_vs_baseline": 1.01
}
}
],
"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": "d87de480-23a4-4bdb-be77-e800e4dae656"
}
}

Fields you will actually wire up

You may also log recent_avg_portcalls_per_day and baseline_avg_portcalls_per_day for diagnostics or to show users the underlying signal that produced the ratio.

Quick start: one-liner curl you can drop into a cron job

This prints a tab-separated line with as_of, port, congestion, and ratio_vs_baseline. Replace jq with your favorite JSON parser if not available.

Python integration example

The snippet below calls the same endpoint, extracts congestion, ratio_vs_baseline, and as_of, and emits a normalized record ready for storage or alerting.

import os
import requests
from datetime import datetime

API_KEY = os.getenv("FREIGHTPULSE_API_KEY", "YOUR_API_KEY")
URL = "https://freightpulsehq.com/api/v1/port-congestion"
PARAMS = {"port": "New York"}
HEADERS = {"X-API-Key": API_KEY}

def fetch_nynj_congestion():
resp = requests.get(URL, headers=HEADERS, params=PARAMS, 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 congestion results for New York-New Jersey")

rec = results[0]
congestion = rec.get("congestion")
as_of = rec.get("as_of")
ratio = rec.get("metrics", {}).get("ratio_vs_baseline")

if congestion is None or as_of is None or ratio is None:
raise ValueError("Missing required fields: congestion, as_of, ratio_vs_baseline")

# Normalize date if needed
# as_of is YYYY-MM-DD (no time component). Keep as string or parse to date.
as_of_date = datetime.strptime(as_of, "%Y-%m-%d").date()

return {
"port": rec.get("port"),
"as_of": as_of_date.isoformat(),
"congestion": congestion,
"ratio_vs_baseline": float(ratio),
}

if __name__ == "__main__":
record = fetch_nynj_congestion()
print(record)

How to interpret the New York–New Jersey signal

Use congestion for quick UI badges and policy routing (e.g., “moderate” triggers amber). Drive automations with ratio_vs_baseline: it is continuous and comparable over time, so you can alert on threshold-crossing without changing labels across releases.

Remember: this measure does not quantify vessel wait times or anchorage delays. It’s a throughput/comparative activity proxy derived from AIS-sourced port call counts.

Data freshness, lag, and caching

IMF PortWatch updates daily with a ~6–7 day lag to present time. Do not treat this as real-time or intraday telemetry. For most workflows, a daily fetch is appropriate.

Error handling and envelope parsing

The outer shape is always {"success": true|false, "data": {...}} (the data key is present on success). Treat non-2xx HTTP codes and success=false as errors. When success=true, the New York–New Jersey record will be in data.results[0].

Alerting patterns that avoid noise

Common integrations

Security, quotas, and environments

Operational checklist for New York–New Jersey

Troubleshooting

Reference links

FAQ

Is this a live wait-time or anchorage delay metric?

No. It is derived from IMF PortWatch, comparing the last 7 days of average port calls to a 90‑day baseline. It is updated daily but lags present time by roughly 6–7 days. It does not measure individual vessel dwell or anchorage times.

What time zone is as_of in?

as_of is an ISO date (YYYY-MM-DD) without a time component. Treat it as a date-based observation. If you need a timestamp, store midnight UTC on that date in your system, but keep the original date string for idempotency.

Can I query multiple ports in one call?

This guide focuses on the New York–New Jersey port via port=New%20York. If you need bulk coverage, consult the API reference for multi-port options. If not available, loop over ports client-side with appropriate rate limiting.

How should I cache results?

Because updates are daily and lagged, a 24-hour cache is generally appropriate. Refresh when the as_of date for a port advances. Avoid caching past the next expected refresh window to keep dashboards current.

What if the congestion label conflicts with my internal rules?

Prefer ratio_vs_baseline for automations, and use congestion for user-facing summaries. If your internal rules require different thresholds, re-label locally from the ratio while still storing the original label for provenance.

Ready to wire this into your pipeline? Create an account and get an API key to move from guest limits to production throughput: Register. Then keep this page open while you implement: the curl, fields, and code snippet above are copy-pasteable and production-ready starting points.