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.
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
- Auth: header X-API-Key: YOUR_API_KEY. Guest without key: 100 requests/day per IP.
- Envelope: {"success":true,"data":{...}}
- Port congestion is IMF PortWatch, lagged ~6-7 days, 7-day avg vs 90-day baseline — not live AIS.
- Do not quote a freight-rates USD fare as today’s price.
- Port: New York-New Jersey (New York)
- curl: curl -H "X-API-Key: YOUR_API_KEY" "https://freightpulsehq.com/api/v1/port-congestion?port=New%20York"
- No official congestion JSON is published for New York. Show the curl and field names (congestion, ratio_vs_baseline, as_of). Do not reuse the USLAX 0.85 fixture.
Endpoint, method, and parameters
Use a simple GET to query congestion for the New York–New Jersey port:
- Method: GET
- URL: https://freightpulsehq.com/api/v1/port-congestion?port=New%20York
- Auth: HTTP header X-API-Key: YOUR_API_KEY (guest traffic without a key is allowed but rate-limited)
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
- data.results[0].congestion: A string label like low, moderate, or high. Use it for dashboards and thresholding.
- data.results[0].metrics.ratio_vs_baseline: Numerical ratio of 7‑day average port calls vs the 90‑day baseline (e.g., 1.01). Use it for rules, alerts, and comparisons.
- data.results[0].as_of: ISO date (YYYY-MM-DD) that the observation covers. Aligns your job schedules and caches.
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.
- ratio_vs_baseline ≈ 1.00: Near baseline activity; treat as steady state.
- Above 1.00: More port calls than the 90-day average. Depending on methodology, this can correspond to increased throughput or operational churn. Always pair with the qualitative congestion label for operator-facing views.
- Below 1.00: Fewer port calls than baseline; evaluate alongside seasonal patterns.
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.
- Suggested schedule: Once per day shortly after your data ingestion window.
- Cache/TTL: Since the series updates daily, a 24-hour cache is appropriate; refresh if the as_of date advances.
- Idempotence: The same as_of value can appear for up to a day; do not generate duplicate alerts for identical as_of + port keys.
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].
- Missing fields: Fail closed if congestion, ratio_vs_baseline, or as_of is absent.
- Empty results: If data.results is empty, retry after backoff and log; do not substitute values from other ports.
- Parsing: as_of is a date string (YYYY-MM-DD) with no time zone component; store it as a date for stable dedup keys.
Alerting patterns that avoid noise
- Use ratio thresholds with hysteresis (e.g., enter alert at ≥1.10; clear alert at ≤1.05) to prevent flapping.
- Combine qualitative and quantitative signals: Only notify if congestion == "high" OR ratio_vs_baseline ≥ chosen threshold.
- Daily dedup: Key by port + as_of + label to avoid duplicate pages when reprocessing the same day.
Common integrations
- ETL: Extract congestion, ratio_vs_baseline, as_of, and port into a warehouse table keyed by (port, as_of).
- Ops dashboards: Show the label prominently; show the ratio for context and trending.
- Planning heuristics: If congestion is high for N consecutive as_of days, bias sailing schedules, yard labor, or drayage buffers.
Security, quotas, and environments
- Authentication: Use the X-API-Key header. Keep YOUR_API_KEY in a secret store (env var, vault) rather than code.
- Guest access: Without a key you can make up to 100 requests/day per IP. Use a key for CI/CD, production jobs, and higher throughput.
- Environment split: Point dev/staging to the same endpoint but with distinct keys and separate caches to avoid cross-talk.
Operational checklist for New York–New Jersey
- Call GET /api/v1/port-congestion?port=New%20York once daily with X-API-Key.
- Parse congestion, metrics.ratio_vs_baseline, and as_of from data.results[0].
- Store with a (port, as_of) primary key. Upsert to avoid duplicates.
- Alert with hysteresis thresholds on ratio_vs_baseline; render congestion for user-facing status.
- Cache for 24 hours; refresh when as_of changes.
Troubleshooting
- HTTP 401/403: Verify your X-API-Key is present and not stripped by proxies. In curl, confirm quotes around the header.
- success=false: Log the response body; do not assume a shape for data. Retry with exponential backoff.
- No results: Ensure the exact port parameter is "New York" (URL-encoded) for New York–New Jersey.
- Unexpected label: Inspect metrics.recent_avg_portcalls_per_day and baseline_avg_portcalls_per_day to understand the ratio.
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.