You need to programmatically detect severe weather disruptions that can impact cargo at specific ports, and you want a clean PHP workflow that returns results you can act on. By the end of this guide, you will know how to authenticate, fetch, parse, and operationalize FreightPulse “Severe Weather Disruptions” data—plus have copy‑pasteable PHP and JavaScript snippets you can drop into your stack.
What the Severe Weather Disruptions lookup provides
This lookup focuses on weather hazards that can affect maritime cargo operations at a given port. Keep the following facts in mind as you integrate:
- 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.
- Lookup: Severe Weather Disruptions
- curl: curl -H "X-API-Key: YOUR_API_KEY" "https://freightpulsehq.com/api/v1/disruptions?port=USLAX&type=severe_weather"
- Natural hazards only (GDACS/USGS/NOAA). Do not invent an event or cover strikes/canals.
Authentication and request shape
Requests include an X-API-Key header. If you test without a key, you are limited to 100 requests per day per IP. Use query parameters to scope your call:
- port: a port code such as USLAX (Los Angeles)
- type: severe_weather (category constrained to weather hazards)
Example endpoint: https://freightpulsehq.com/api/v1/disruptions?port=USLAX&type=severe_weather
Quick test with curl
Run this in your terminal to verify connectivity and headers are set correctly.
curl -H "X-API-Key: YOUR_API_KEY" "https://freightpulsehq.com/api/v1/disruptions?port=USLAX&type=severe_weather"
Understanding the response envelope
Responses are wrapped in a success/data envelope. Copy the sample below to confirm your JSON handling path. The field names and envelope structure are what your code should rely on for validation and parsing.
{
"success": true,
"data": {
"timestamp": "2026-10-11T00:00:19+00:00",
"source": "EIA (U.S. Energy Information Administration)",
"currency": "USD",
"unit": "gallon",
"data": {
"diesel": {
"national_average": 6.199,
"change_week": -0.183,
"change_percent": -2.87,
"updated_at": "2026-10-05",
"regions": {
"east_coast": 5.951,
"midwest": 6.286,
"gulf_coast": 5.819,
"rocky_mountain": 6.267,
"west_coast": 7.229,
"california": 8.082
}
},
"gasoline": {
"national_average": 4.354,
"change_week": -0.111,
"change_percent": -2.49,
"updated_at": "2026-10-05",
"grades": {
"regular": 4.354,
"midgrade": 4.99,
"premium": 5.4
}
},
"bunker_fuel": {
"available": false,
"note": "No known free source (Rotterdam/Singapore/Houston) — requires a paid provider (e.g. Ship & Bunker, Argus)."
}
},
"historical": {
"diesel_30d_avg": 6.349,
"diesel_90d_avg": 5.686,
"diesel_yoy_change": 67,
"gasoline_30d_avg": 4.404,
"gasoline_90d_avg": 4.155,
"gasoline_yoy_change": 39.4
}
},
"meta": {
"request_id": "82f8dc19-b0a6-4249-aea0-584078406a33"
}
}
What your code should use:
- success (boolean): gatekeep downstream logic; stop early if false.
- data (object): the payload container for the request you performed.
- data.timestamp (ISO 8601, UTC offset): normalize to UTC for comparisons.
- meta.request_id: log for tracing and support tickets.
Notes on semantics and units for operational code paths:
- Timestamps include timezone offsets (e.g., +00:00). Standardize to UTC when storing.
- Currency and unit fields will appear in datasets that have pricing or measurement context. Do not transform or present any freight-rate USD figure as “today’s price.”
PHP: Fetch and parse Severe Weather Disruptions
The snippet below requests severe weather disruptions for USLAX and demonstrates header auth, timeouts, basic retries, and JSON validation. It reads the standard envelope and is safe to embed in a job runner or controller.
<?php
$endpoint = "https://freightpulsehq.com/api/v1/disruptions?port=USLAX&type=severe_weather";
$apiKey = "YOUR_API_KEY";
// Basic retry wrapper (3 attempts with exponential backoff)
function http_get_with_retries($url, $headers, $attempts = 3) {
$delay = 0.5; // seconds
for ($i = 1; $i <= $attempts; $i++) {
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_CONNECTTIMEOUT => 5,
CURLOPT_TIMEOUT => 15
]);
$body = curl_exec($ch);
$err = curl_error($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($err) {
if ($i === $attempts) {
throw new RuntimeException("Curl error after $i attempts: $err");
}
} elseif ($code >= 500) {
if ($i === $attempts) {
throw new RuntimeException("Server error $code after $i attempts");
}
} else {
return [$code, $body];
}
usleep((int)($delay * 1000000));
$delay *= 2;
}
throw new RuntimeException("Unreachable code in http_get_with_retries");
}
list($status, $raw) = http_get_with_retries(
$endpoint,
["X-API-Key: $apiKey"]
);
if ($status !== 200) {
throw new RuntimeException("Unexpected HTTP $status: $raw");
}
$decoded = json_decode($raw, true);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new RuntimeException("Invalid JSON: " . json_last_error_msg());
}
if (!isset($decoded['success']) || $decoded['success'] !== true) {
// Optionally inspect error fields if present
throw new RuntimeException("API reported failure or missing success flag");
}
if (!isset($decoded['data']) || !is_array($decoded['data'])) {
throw new RuntimeException("Missing data object in response");
}
// Minimal example: capture envelope fields that are always safe to rely on.
$timestamp = isset($decoded['data']['timestamp']) ? $decoded['data']['timestamp'] : null;
$requestId = isset($decoded['meta']['request_id']) ? $decoded['meta']['request_id'] : null;
// Your business logic goes here:
// - Inspect disruptions entries inside $decoded['data'] (when present for your query).
// - Map to internal event model and store.
// - Use $timestamp for freshness checks (normalize to UTC if needed).
// Example logging
error_log("FreightPulse disruptions fetch ok. ts=" . ($timestamp ?? 'n/a') . " req=" . ($requestId ?? 'n/a'));
echo "OK\n";
JavaScript (Node.js): Same endpoint, minimal parsing
If you prefer a lightweight Node worker or serverless function, use native fetch (Node 18+). It validates the envelope and exposes the payload for your downstream logic.
import fetch from 'node-fetch';
const url = 'https://freightpulsehq.com/api/v1/disruptions?port=USLAX&type=severe_weather';
const headers = { 'X-API-Key': 'YOUR_API_KEY' };
async function getSevereWeatherDisruptions() {
const res = await fetch(url, { headers, redirect: 'follow' });
if (!res.ok) {
const text = await res.text();
throw new Error(`HTTP ${res.status}: ${text}`);
}
const json = await res.json();
if (!json || json.success !== true || typeof json.data !== 'object') {
throw new Error('Invalid envelope: missing success=true or data object');
}
const ts = json.data.timestamp ?? null;
const reqId = json.meta?.request_id ?? null;
// TODO:
// - Inspect fields inside json.data that describe disruptions for severe weather.
// - Normalize timestamps to UTC before persistence.
// - Gate any user-facing messaging by success and by the presence of disruption objects.
return { ts, reqId, payload: json.data };
}
getSevereWeatherDisruptions()
.then(({ ts, reqId, payload }) => {
console.log('Fetch ok', { ts, reqId });
// Process payload...
})
.catch(err => {
console.error('Fetch failed', err);
process.exitCode = 1;
});
Operational details that will save you time
- Rate limits: Guests without an API key are limited to 100 requests/day per IP. Use an API key in production.
- Envelope: Always check success first. Treat any missing or malformed data object as a hard error.
- Timestamps and timezone: Timestamps are ISO 8601 with explicit offsets. Store as UTC and convert at render time.
- Caching: If you poll frequently, cache by port and type. Use data.timestamp to decide cache freshness. Avoid hammering the endpoint during backoffs.
- Port congestion: FreightPulse port congestion references IMF PortWatch and is lagged approximately 6–7 days (7‑day average vs 90‑day baseline). Do not expect or present it as live AIS wait times.
- Scope: Severe Weather Disruptions covers natural hazards sourced from GDACS/USGS/NOAA. Do not conflate with labor strikes or canal restrictions.
- Output discipline: Do not quote or imply any freight-rate USD figure as “today’s price.”
How to productionize the PHP workflow
1) Normalize and validate inputs
Gate incoming port codes to a whitelist you support (e.g., USLAX). Keep type fixed to severe_weather for this workflow so non-weather categories never slip in.
2) Resilience and timeouts
- Connect timeout: 5s, read timeout: 15s are a good starting point; adjust per SLOs.
- Retry on 5xx and network errors with exponential backoff (start at 500ms, double to a max window you can tolerate).
3) Envelope-first parsing
- Require success === true.
- Require data to be an object; fail closed otherwise.
- Log meta.request_id for correlation in centralized logging.
4) Caching and deduplication
- Cache key: disruptions:USLAX:severe_weather.
- Use data.timestamp to detect freshness and avoid rebroadcasting identical events.
5) Alerting and UX
- Use the presence of disruptions in the data object to decide whether to send notifications or annotate ETAs. Keep messaging precise to weather hazards only.
- Avoid implying live vessel queues or non-weather causes. Keep notes aligned to natural hazards.
End-to-end test checklist
- 401/403 handling when the X-API-Key is missing or invalid.
- 429 handling if you exceed guest limits; ensure backoff and surface actionable logs.
- Cold-start and retry path logging includes meta.request_id when present.
- UTC normalization of timestamps verified in storage and analytics layers.
- Feature flag that can disable external calls and trigger cached responses for incident modes.
FAQ
Q: Can I call the endpoint without an API key?
A: Yes, but you are limited to 100 requests per day per IP. Use X-API-Key: YOUR_API_KEY for production workloads.
Q: Are the disruptions live measurements of port congestion?
A: No. Port congestion references IMF PortWatch and is lagged roughly 6–7 days with a 7‑day average vs a 90‑day baseline. It is not live AIS wait times.
Q: What kinds of disruptions are included here?
A: Natural hazards only, using sources like GDACS/USGS/NOAA. Do not use this feed for strikes, canal restrictions, or other non-weather events.
Q: How should I present prices or currency fields if they appear?
A: Do not quote any freight-rate USD amount as “today’s price.” If a payload includes currency or unit fields for other datasets, preserve them without making pricing claims.
Q: How do I learn about other query parameters or response fields?
A: See the official API reference: Documentation.
Ready to integrate Severe Weather Disruptions into your stack? Create your API key in minutes and start testing with the same curl shown above: Register.