You need a reliable way to quantify Hong Kong port congestion for scheduling and risk scoring in transportation systems. By the end of this guide, you will be able to query Hong Kong (HKHKG) congestion from the FreightPulse Port Congestion API, interpret the fields derived from IMF PortWatch, and integrate the results into your shipping and routing workflows.
What this Hong Kong congestion API actually measures
The FreightPulse port congestion endpoint for Hong Kong (HKHKG) provides a 7-day average of port calls compared against a 90-day baseline for the same port. The data source is IMF PortWatch using UN Global Platform AIS data and is typically lagged by roughly 6–7 days. This is not a live AIS wait-time feed and it does not measure anchorage or berth queue durations. Instead, it’s a standardized throughput signal—recent port call volume relative to a longer historical baseline—that’s suitable for normalization and comparison over time.
Because the metric is a ratio against the port’s own baseline, it gracefully handles seasonality and structural differences between ports. For Hong Kong, you’ll read three key fields for most downstream use cases: congestion (categorical), ratio_vs_baseline (numeric), and as_of (date).
Endpoint and authentication
The endpoint is a simple GET with the port code parameter set to HKHKG. Authentication is via a header X-API-Key. Guest access is available without a key, limited to 100 requests per day per IP. Production integrations should set and rotate a key in a secure store.
- Method: GET
- URL: https://freightpulsehq.com/api/v1/port-congestion?port=HKHKG
- Auth: header X-API-Key: YOUR_API_KEY (guest without key allowed, 100 requests/day per IP)
- Envelope: {"success": true, "data": {...}}
You will receive results as a JSON envelope that includes a results array. For a single port query like HKHKG, you should expect one object in that array.
Quickstart: call Hong Kong congestion
Use this cURL to retrieve congestion metrics for Hong Kong. It returns data based on IMF PortWatch with a ~6–7 day lag, reflecting a 7-day average versus the 90-day baseline.
Source: live
cURL:
curl -H "X-API-Key: YOUR_API_KEY" "https://freightpulsehq.com/api/v1/port-congestion?port=HKHKG"
JSON:
{
"success": true,
"data": {
"results": [
{
"port": "Hong Kong",
"locode": "HK HKG",
"country": "Hong Kong SAR",
"congestion": "moderate",
"as_of": "2026-09-25",
"metrics": {
"recent_avg_portcalls_per_day": 36.6,
"baseline_avg_portcalls_per_day": 38.1,
"ratio_vs_baseline": 0.96
}
}
],
"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": "5d54ae22-3e6a-42d9-aa1a-d82e2c7d6d8d"
}
}
How to interpret the fields you will actually use
- data.results[0].congestion: a categorical label (e.g., low, moderate, high) derived from the ratio_vs_baseline. Use it for quick UI badges or alerts.
- data.results[0].metrics.ratio_vs_baseline: a float that compares the recent 7-day average of port calls to the 90-day baseline. Values below 1.0 suggest lower-than-baseline activity; above 1.0 suggests higher activity.
- data.results[0].as_of: the date (YYYY-MM-DD) of the last available reading, lagged ~6–7 days from “now.” Treat it as a historical snapshot rather than “today.”
- data.results[0].metrics.recent_avg_portcalls_per_day and baseline_avg_portcalls_per_day: counts of port calls per day. These are helpful for auditing and explaining the ratio.
- data.meta: contains source, data lag, and methodology notes. Keep this visible in internal docs to prevent teams from misinterpreting the metric as a live wait-time.
Origin catalog facts for Hong Kong (copy-paste reference)
- 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: Hong Kong (HKHKG)
- curl: curl -H "X-API-Key: YOUR_API_KEY" "https://freightpulsehq.com/api/v1/port-congestion?port=HKHKG"
- No official congestion JSON is published for HKHKG. Show the curl and field names (congestion, ratio_vs_baseline, as_of). Do not reuse the USLAX 0.85 fixture.
Production-grade integration in Python
The following example calls the Hong Kong endpoint, extracts the actionable fields, and shows how to guard against empty results and stale data. It uses only the fields documented above.
import os
import time
import requests
API_URL = "https://freightpulsehq.com/api/v1/port-congestion"
PORT = "HKHKG"
API_KEY = os.getenv("FREIGHTPULSE_API_KEY", "YOUR_API_KEY") # replace in production
def fetch_hk_congestion(session: requests.Session) -> dict:
headers = {"X-API-Key": API_KEY}
params = {"port": PORT}
resp = session.get(API_URL, headers=headers, params=params, timeout=15)
resp.raise_for_status()
payload = resp.json()
if not payload.get("success"):
raise RuntimeError("API returned success=false")
data = payload.get("data", {})
results = data.get("results", [])
if not results:
raise RuntimeError("No results for HKHKG")
row = results[0]
metrics = row.get("metrics", {})
return {
"port": row.get("port"),
"locode": row.get("locode"),
"country": row.get("country"),
"congestion": row.get("congestion"),
"as_of": row.get("as_of"),
"ratio_vs_baseline": metrics.get("ratio_vs_baseline"),
"recent_avg_portcalls_per_day": metrics.get("recent_avg_portcalls_per_day"),
"baseline_avg_portcalls_per_day": metrics.get("baseline_avg_portcalls_per_day"),
"source": data.get("meta", {}).get("source"),
"data_lag": data.get("meta", {}).get("data_lag_days"),
}
def main():
with requests.Session() as s:
# basic retry with backoff for transient network errors
for attempt in range(3):
try:
hk = fetch_hk_congestion(s)
break
except Exception as e:
if attempt == 2:
raise
time.sleep(2 ** attempt)
# Use the fields you actually need downstream
print("Port:", hk["port"], hk["locode"])
print("As of:", hk["as_of"])
print("Congestion:", hk["congestion"])
print("Ratio vs baseline:", hk["ratio_vs_baseline"])
print("Recent avg port calls/day:", hk["recent_avg_portcalls_per_day"])
print("Baseline avg port calls/day:", hk["baseline_avg_portcalls_per_day"])
print("Source:", hk["source"], "| Lag:", hk["data_lag"])
if __name__ == "__main__":
main()
Update cadence, lag, and caching strategy
Because the dataset is derived from IMF PortWatch and updated daily with a typical 6–7 day lag, you don’t need to poll more than once per day for HKHKG. Caching the envelope for 24 hours is sufficient for most dashboards and APIs. If you run job-based workflows, schedule a daily pull and persist the response with the as_of date as the key to maintain a clean historical series for Hong Kong.
Downstream services should clearly display the as_of date in the UI and reports. Treat the congestion label and ratio as historical signals that reflect recent throughput, not as live wait times. If your application needs real-time anchorage metrics, you will need to combine this signal with a separate live AIS source; do not reinterpret this API as that.
Common UI and automation patterns
- Badge and tooltip: Show congestion as a color-coded badge next to “Hong Kong (HKHKG),” with a tooltip that explains the 7-day vs 90-day baseline and the as_of date.
- Threshold alerts: Trigger an internal notification when ratio_vs_baseline departs from your target band, for example dropping below 0.90 for a sustained period (account for the lag and avoid over-triggering on single-day noise).
- Scenario planning: Combine ratio_vs_baseline with your terminal schedules to adjust buffer times in drayage or barge timing models.
- Indicators panel: Display recent_avg_portcalls_per_day and baseline_avg_portcalls_per_day under an “Audit” or “Methodology” section to keep operations teams aligned on what the ratio represents.
Error handling and operational safety
Use HTTP status codes and the success flag to gate processing. If you hit guest limits (100/day per IP without a key), back off and add an API key. Timeouts of 10–15 seconds and up to 3 retries with an exponential backoff is a sensible default for transportation backends.
If results is empty, stop the pipeline and log a structured error. For data integrity, persist the raw envelope along with the parsed fields so you can re-process if your internal schema changes.
Testing and validation tips
- Schema checks: Assert presence and types for congestion, as_of, and metrics.ratio_vs_baseline.
- Date discipline: Validate as_of is not “today” and typically trails by ~6–7 days; reject or flag anomalies if it is missing or unexpectedly stale.
- Monotonic drift watch: Track a simple moving average of ratio_vs_baseline to detect unusual structural shifts that may impact your routing assumptions.
- Compare volumes: Keep both recent_avg_portcalls_per_day and baseline_avg_portcalls_per_day for context when stakeholders challenge a ratio movement.
Non-functional considerations for transportation platforms
Latency is not a primary concern due to the inherent lag; prioritize reliability and clear user messaging. If you expose the metric in a public or partner-facing API, propagate the as_of field and a short description of the methodology so downstream consumers don’t misuse it as live AIS. Avoid over-frequent polling to stay within sensible request volumes and to prevent unnecessary load.
For multi-region deployments, cache the response close to your users to reduce cold-start latency. When you update parsing logic, test against preserved historical envelopes so you do not break existing dashboards.
Linking to docs and registration
You can find additional details and broader API documentation here: Documentation. To move from guest limits to a production API key, sign up here: Register.
Troubleshooting guide
- Empty results array: Confirm the port parameter is exactly HKHKG. Check your logs for envelope parsing issues and confirm resp.json() is successful.
- Rate or quota blocks: If you are calling without a key, consolidate calls to once daily per service and add a key via the X-API-Key header when you are ready for higher volume.
- Data looks “stale”: This dataset is lagged by about 6–7 days. Verify as_of and ensure your UI clarifies the lag to users. Cache for 24 hours to avoid noisy refreshes.
- Mismatch with on-the-ground wait anecdotes: This metric is throughput-based (port calls), not wait times. It should be used alongside live AIS if you need queue lengths.
FAQ
Is this a live congestion or anchorage wait-time metric?
No. It is a 7-day average of port calls versus a 90-day baseline from IMF PortWatch with a ~6–7 day lag. It does not measure vessel wait or anchorage time.
How often should I poll the HKHKG endpoint?
Once per day is sufficient because the underlying dataset updates daily and is lagged. Cache responses for 24 hours to reduce load and maintain consistency.
Which fields should I store for Hong Kong dashboards?
Store congestion, as_of, metrics.ratio_vs_baseline, recent_avg_portcalls_per_day, baseline_avg_portcalls_per_day, and the meta.source and data_lag_days for auditability.
Do I need an API key?
You can call without a key as a guest (100 requests/day per IP). For production workloads, register for an API key and pass it in the X-API-Key header.
Can I use this value as a freight rate or cost proxy?
No. Do not quote any USD freight rate from this endpoint. It supplies congestion signals only, not rate cards or live prices.
Next step
Set up a daily job that calls the HKHKG endpoint, parses congestion, ratio_vs_baseline, and as_of, and persists the envelope for audit and reprocessing. When you are ready to move beyond guest limits, create your key here: Register. For field-by-field details, see the Documentation.