You need a reliable way to programmatically check recent port congestion at Jebel Ali so you can plan sailings, manage buffers, and communicate expectations to operations and customers. By the end of this guide you will query the Jebel Ali congestion endpoint, parse the response in Python, understand the lagged IMF PortWatch methodology, and ship a small utility that your transportation stack can run on a schedule.
What this API provides (and what it does not)
The endpoint returns congestion indicators for Jebel Ali (AEJEA) based on IMF PortWatch data. The signal is lagged by about 6 to 7 days and reflects a 7-day moving average benchmarked against a 90-day baseline. It is not a live AIS wait-time feed, and it does not directly measure anchorage or berth waiting hours.
Because the metric is a relative change in port calls, treat it as an operational risk indicator rather than a real-time queue length. Use it to adjust safety stock, routing choices, or ETD/ETA buffers, but do not represent it as today’s live wait time. Do not quote any freight-rates USD fare as a current price based on this dataset.
Endpoint, parameters, and authentication
Endpoint:
- GET /api/v1/port-congestion?port=AEJEA
- Full URL: https://freightpulsehq.com/api/v1/port-congestion?port=AEJEA
Authentication:
- Header: X-API-Key: YOUR_API_KEY
- Guests without a key: up to 100 requests per day per IP
Response envelope:
- Top-level shape: {"success": true, "data": {...}}
- Fields you will use: congestion level, ratio_vs_baseline, as_of date, location metadata
Jebel Ali identifiers:
- Port name: Jebel Ali
- Locode: AE JEA
Documentation and account setup:
- Register for an API key
- Read the Documentation
Quickstart: cURL request for Jebel Ali (AEJEA)
Copy and run this request. It targets the Jebel Ali port explicitly via its locode and uses the documented header for authentication.
curl -H "X-API-Key: YOUR_API_KEY" "https://freightpulsehq.com/api/v1/port-congestion?port=AEJEA"
Official sample response and field map
The following is an official sample response. Use it to wire your parser and tests. Note the envelope and where each field lives. Values reflect IMF PortWatch-derived congestion, lagged and averaged, not live AIS wait times.
{
"success": true,
"data": {
"results": [
{
"port": "Jebel Ali",
"locode": "AE JEA",
"country": "United Arab Emirates",
"congestion": "moderate",
"as_of": "2026-10-09",
"metrics": {
"recent_avg_portcalls_per_day": 4.1,
"baseline_avg_portcalls_per_day": 4.7,
"ratio_vs_baseline": 0.87
}
}
],
"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": "b21bae2d-d4b2-46a6-ad86-11428a805221"
}
}
Fields to consume in operations workflows:
- data.results[0].congestion: Categorical congestion level (low, moderate, high)
- data.results[0].as_of: ISO date for the metric snapshot
- data.results[0].metrics.ratio_vs_baseline: Recent 7-day average port calls divided by the 90-day baseline
- data.results[0].metrics.recent_avg_portcalls_per_day and .baseline_avg_portcalls_per_day: Underlying counts per day
Python guide: request, parse, and normalize Jebel Ali congestion
The snippet below authenticates with the X-API-Key header, calls the endpoint for AEJEA, and extracts congestion, ratio_vs_baseline, and as_of. It includes minimal validation and a stable tuple you can cache or log.
Script: fetch and interpret congestion for Jebel Ali
import os
import sys
import time
import json
from typing import Tuple, Optional
import requests
API_URL = "https://freightpulsehq.com/api/v1/port-congestion?port=AEJEA"
API_KEY = os.getenv("FREIGHTPULSE_API_KEY", "YOUR_API_KEY")
def fetch_jebel_ali_congestion(session: Optional[requests.Session] = None) -> Tuple[str, float, str]:
s = session or requests.Session()
headers = {"X-API-Key": API_KEY}
resp = s.get(API_URL, headers=headers, timeout=20)
resp.raise_for_status()
payload = resp.json()
# Envelope: {"success": true, "data": {...}}
if not isinstance(payload, dict) or not payload.get("success"):
raise RuntimeError("API indicated failure or unexpected envelope")
data = payload.get("data", {})
results = data.get("results", [])
if not results:
raise RuntimeError("No results returned for AEJEA")
first = results[0]
congestion = first.get("congestion")
as_of = first.get("as_of")
metrics = first.get("metrics", {})
ratio = metrics.get("ratio_vs_baseline")
if congestion is None or ratio is None or as_of is None:
raise RuntimeError("Missing required fields: congestion, ratio_vs_baseline, or as_of")
# Basic normalization: clamp ratio to a sensible range if needed
try:
ratio = float(ratio)
except Exception as exc:
raise RuntimeError(f"Invalid ratio_vs_baseline: {ratio}") from exc
return congestion, ratio, as_of
def main() -> int:
try:
congestion, ratio, as_of = fetch_jebel_ali_congestion()
except Exception as e:
print(f"Error fetching congestion: {e}", file=sys.stderr)
return 1
# Example downstream usage: simple flags
status_flag = "OK"
if congestion == "high" or ratio < 0.8:
status_flag = "RISK"
elif congestion == "moderate":
status_flag = "WATCH"
print(json.dumps({
"port": "Jebel Ali",
"locode": "AE JEA",
"as_of": as_of,
"congestion": congestion,
"ratio_vs_baseline": ratio,
"status_flag": status_flag
}, ensure_ascii=False))
return 0
if __name__ == "__main__":
raise SystemExit(main())
Notes:
- Keep YOUR_API_KEY in development; replace it with a real key from your environment variable once you register.
- The script treats the ratio as a float and provides simple flags you can adapt to your SOPs.
- The response is lagged by about 6 to 7 days. Design your caching and alerts accordingly.
Operational semantics: units, timing, caching, and scheduling
Units and definitions:
- congestion: Categorical label derived from the ratio of recent to baseline port calls
- ratio_vs_baseline: Unitless ratio (for example, 0.87 means recent activity is 87 percent of the 90-day baseline)
- recent_avg_portcalls_per_day and baseline_avg_portcalls_per_day: Port calls per day averaged over the indicated windows
- as_of: ISO date. The dataset refreshes daily but remains lagged relative to the present date
Timing and updates:
- Data source: IMF PortWatch via UN Global Platform AIS
- Refresh cadence: daily ingestion
- Lag: approximately 6 to 7 days from the current date
Caching recommendations:
- Since values change daily at most, a cache TTL of 12 to 24 hours is typically safe
- Store the tuple of congestion, ratio_vs_baseline, and as_of keyed by port code AEJEA
- Invalidate if the as_of date increases or if the ratio shifts beyond a threshold you care about
Scheduling patterns:
- Run the collection job once every morning in the port’s local timezone or UTC
- Post-process to your TMS or planning system, tagging the as_of date to avoid confusing data recency
Error handling, quotas, and resilience
Quotas and authentication:
- Guests without a key are limited to 100 requests per day per IP
- Provide X-API-Key as documented; do not append query parameters for auth
HTTP and payload handling:
- Expect a 200 with the envelope containing success and data
- On non-2xx, back off and retry with exponential delays capped to a few minutes
- Validate presence of congestion, ratio_vs_baseline, and as_of before writing to production stores
Idempotency and logging:
- Log the as_of and ratio you ingest so downstream diffs are explainable
- Avoid alert loops by suppressing repeated notifications when the as_of date has not advanced
Applying the signal in transportation planning at Jebel Ali
Use the combination of congestion and ratio_vs_baseline to drive conditional logic in your sailing plans to and from Jebel Ali. For example, when congestion is moderate and ratio_vs_baseline drops below a chosen threshold, you can extend port buffer time or prioritize sailings with more schedule slack.
Because the metric is lagged and averaged, combine it with your carrier ETAs and internal dwell data to decide whether to re-route through alternative hubs. Always surface the as_of date to planners so they see how fresh the signal is relative to booking cutoffs and vessel ETDs.
Validation checklist before shipping to production
- Authentication header works with your registered key and rotates correctly in CI and production
- Parser reads congestion, ratio_vs_baseline, and as_of from data.results[0]
- Cache persists results for up to 24 hours and refreshes when as_of advances
- Alerts or flags update only on meaningful ratio or level changes to avoid noise
- Dashboards label the metric as IMF PortWatch-based, lagged, not live AIS
FAQ
Is this a live AIS wait-time feed?
No. It is IMF PortWatch-based and lagged about 6 to 7 days. It compares a recent 7-day average of port calls to a 90-day baseline and does not directly measure anchorage or berth waits.
What is the correct way to authenticate?
Send your key via the X-API-Key header. Guests without a key can make up to 100 requests per day per IP.
Which fields should I store for Jebel Ali?
congestion, metrics.ratio_vs_baseline, as_of, and optionally recent and baseline port calls for transparency.
How often should I poll the endpoint?
Daily is sufficient given the lag and cadence. Cache responses for 12 to 24 hours and check the as_of date.
Can I use these values to quote freight rates?
No. Do not quote a freight-rates USD fare as today’s price based on this congestion dataset.
Get an API key and wire this into your transportation planning today. Start with the cURL above, then drop the Python snippet into your scheduler. When you are ready, create your key via the Register page and review the Documentation for additional integration details.