You need a dependable way to quantify how busy Los Angeles-Long Beach is right now without chasing live AIS “ships at anchor” snapshots. By the end of this guide you’ll be able to pull lagged congestion metrics from FreightPulse for USLAX, interpret the 7‑day average vs 90‑day baseline, and ship a small integration that you can cache inside your workflow.
What this congestion metric is (and isn’t)
FreightPulse congestion data for Los Angeles-Long Beach (USLAX) comes from IMF PortWatch and is lagged by roughly 6–7 days. It is not a live AIS estimate of vessels waiting off the port. Instead, it summarizes recent activity with a 7‑day rolling average and compares it to a 90‑day baseline.
This design is intentional: the signal is stable enough for planning and trending, less prone to hour-by-hour volatility, and easier to integrate into scheduling, pricing, and exception-alert workflows.
Endpoint you will call
The port congestion endpoint is a straightforward GET that accepts a port code and returns a standardized envelope. Authentication is via an API key header. A guest without a key can make up to 100 requests per day per IP, but you should still structure your code to cache responses because the dataset is lagged and not changing minute-to-minute.
Official cURL you can paste and run:
curl -H "X-API-Key: YOUR_API_KEY" "https://freightpulsehq.com/api/v1/port-congestion?port=USLAX"
Field notes:
- HTTP method: GET
- Header: X-API-Key: YOUR_API_KEY
- Query parameter: port=USLAX (Los Angeles-Long Beach)
- Envelope: {"success": true, "data": {...}} — always check success before using data
If you’re new to the API, read the Documentation for general patterns you can reuse (authentication, response shapes, and error handling).
Los Angeles-Long Beach example response and how to read it
The following is the documented fixture for USLAX (as_of 2026‑08‑14 — not live today). Keep these values intact when building mocks or unit tests:
{
"success": true,
"data": {
"results": [
{
"port": "Los Angeles-Long Beach",
"locode": "US LAX",
"country": "United States",
"congestion": "moderate",
"as_of": "2026-08-14",
"metrics": {
"recent_avg_portcalls_per_day": 8.7,
"baseline_avg_portcalls_per_day": 10.2,
"ratio_vs_baseline": 0.85
}
}
]
}
}
How to interpret the key fields you’ll actually use:
- data.results[0].congestion: A categorical summary such as “moderate”. Use this for dashboards or quick status flags.
- data.results[0].as_of: The date stamp (YYYY‑MM‑DD) for the statistics. The dataset is lagged ~6–7 days; treat this as a historical tick, not “now”.
- metrics.recent_avg_portcalls_per_day: 7‑day rolling average of daily port calls. Unit: port calls per day.
- metrics.baseline_avg_portcalls_per_day: 90‑day baseline average. Same units.
- metrics.ratio_vs_baseline: The ratio of recent to baseline levels (unitless). Values below 1.0 indicate activity below baseline; above 1.0 indicates above-baseline activity.
For programmatic consumers, you’ll pair the categorical “congestion” field with ratio_vs_baseline and the two averages to decide whether to trigger actions (e.g., allocate additional buffer time when the ratio is meaningfully below 1.0).
Production-ready Python example for USLAX
This snippet fetches congestion for Los Angeles-Long Beach, validates the envelope, and extracts the fields you need. It also demonstrates basic caching guidance via a comment because the metric is lagged and stable intra-day.
import os
import sys
import json
import time
import urllib.request
API_URL = "https://freightpulsehq.com/api/v1/port-congestion?port=USLAX"
API_KEY = os.getenv("FREIGHTPULSE_API_KEY", "YOUR_API_KEY")
def fetch_uslax_congestion():
req = urllib.request.Request(API_URL, method="GET")
req.add_header("X-API-Key", API_KEY)
try:
with urllib.request.urlopen(req, timeout=20) as resp:
raw = resp.read().decode("utf-8")
payload = json.loads(raw)
except Exception as e:
raise RuntimeError(f"Request failed: {e}")
# Validate the envelope
if not isinstance(payload, dict) or not payload.get("success"):
raise ValueError(f"Unexpected response shape or success=false: {payload}")
data = payload.get("data", {})
results = data.get("results", [])
if not results:
raise ValueError("No results in response")
row = results[0]
# Required fields
port = row.get("port")
locode = row.get("locode")
as_of = row.get("as_of")
congestion = row.get("congestion")
metrics = row.get("metrics", {})
recent = metrics.get("recent_avg_portcalls_per_day")
baseline = metrics.get("baseline_avg_portcalls_per_day")
ratio = metrics.get("ratio_vs_baseline")
if None in (port, locode, as_of, congestion, recent, baseline, ratio):
raise ValueError(f"Missing required fields in response for {locode}")
return {
"port": port,
"locode": locode,
"as_of": as_of,
"congestion": congestion,
"recent_avg_portcalls_per_day": recent,
"baseline_avg_portcalls_per_day": baseline,
"ratio_vs_baseline": ratio,
}
def main():
# Caching tip: since the source is lagged by ~6–7 days and updates daily at most,
# cache this response for hours to reduce calls and stay within guest limits.
result = fetch_uslax_congestion()
print(json.dumps(result, indent=2))
if __name__ == "__main__":
sys.exit(main())
Turning the numbers into an operational signal
For Los Angeles-Long Beach, you can form a practical rule by combining the ratio and the qualitative label:
- Use congestion for a human‑readable badge: normal, moderate, severe, etc.
- Use ratio_vs_baseline to gate automation. For example, if ratio_vs_baseline is meaningfully below 1.0 for several consecutive days, consider increasing schedule buffers or rebalancing yard resources.
- Use recent_avg_portcalls_per_day and baseline_avg_portcalls_per_day when you need an absolute magnitude to estimate throughput or to run sensitivity checks in planning models.
Because the data is a 7‑day average, it smooths daily spikes. This helps prevent alert fatigue while still capturing shifts in port activity at USLAX.
Integration details that save time
- Authentication: Send the header X-API-Key with YOUR_API_KEY. If you don’t have a key, you can still test as a guest (100 requests/day per IP), but add caching.
- Envelope shape: Always expect {"success": true, "data": {...}}. Treat success=false or missing keys as errors in your client.
- Lag and freshness: Data is lagged by ~6–7 days from IMF PortWatch. Do not treat it as live AIS wait times. If you need intra‑day changes, design a separate layer and keep this as your stability anchor.
- Time semantics: as_of is a date string (YYYY‑MM‑DD). Treat it as the effective date of the statistics. If you store it, use it as a partition key for caching and backfills.
- Units: recent_avg_portcalls_per_day and baseline_avg_portcalls_per_day are counts per day. ratio_vs_baseline is unitless.
- Caching: Since the underlying data updates at most daily, caching for 6–24 hours is typical. In CI, pin to a fixture (see the documented JSON above) to keep tests deterministic.
- Pagination: The response returns a results array. For a single port query like USLAX you will typically get one element; still, write your client to handle arrays defensively.
- Error handling: Network timeouts and non-2xx codes can occur; treat them as transient and retry with backoff. If success=false, log and surface the message if present.
Origin catalog facts
- 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: Los Angeles-Long Beach (USLAX)
- curl: curl -H "X-API-Key: YOUR_API_KEY" "https://freightpulsehq.com/api/v1/port-congestion?port=USLAX"
- Documented fixture (as_of 2026-08-14 — not live today):
Validation workflow for USLAX
When you wire this into a production pipeline for Los Angeles-Long Beach, validate on three levels:
- Schema: Ensure the envelope is present and results is an array with at least one element. Fail fast if not.
- Semantics: Check that as_of is within the plausible 6–7 day lag window relative to your system date; if it’s older than expected, surface a “stale data” warning but do not crash your pipeline.
- Numerics: Verify recent_avg_portcalls_per_day and baseline_avg_portcalls_per_day are positive numbers and ratio_vs_baseline is between 0 and a reasonable upper bound (e.g., 3). If out of range, quarantine the tick for manual review.
This prevents a single malformed tick from propagating into planning systems.
Common pitfalls to avoid
- Treating the metric as live: It is not. It’s IMF PortWatch with a ~6–7 day lag and a 7‑day average.
- Re-querying too often: The data will not change materially intra‑day. Cache it.
- Assuming a single record: Your code should handle results as an array even if you expect one record for USLAX.
- Confusing categories with thresholds: The qualitative congestion string is provided; do not attempt to reverse‑engineer the classification unless your use case requires it.
FAQ
Is this the same as tracking ships at anchor off Los Angeles-Long Beach?
No. This is IMF PortWatch data with a ~6–7 day lag and a 7‑day rolling average compared to a 90‑day baseline. It is not a live AIS wait-time feed.
How often should I refresh USLAX congestion in production?
Once per day is typical. Many teams cache for 6–24 hours given the lagged nature of the source.
What’s the minimum I need to display a reliable status?
Show congestion (string), as_of (date), and ratio_vs_baseline (number). Optionally include the recent and baseline port calls per day to add context.
Do I need an API key to test?
No, you can make up to 100 requests/day per IP as a guest. For sustained use, add X-API-Key: YOUR_API_KEY and manage caching.
Can I use these metrics to set freight rates today?
Do not quote a USD freight rate as “today’s price” based solely on these metrics. They are lagged indicators for congestion, not live pricing.
Get an API key and put this into your pipeline in minutes. Create your account at Register, then pull the USLAX endpoint and cache the 7‑day average vs 90‑day baseline. If you need more details on envelopes, fields, and conventions, see the Documentation.