Home → Blog

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:

Illustration: How to Get Severe Weather Disruptions

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:

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:

Notes on semantics and units for operational code paths:

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

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

3) Envelope-first parsing

4) Caching and deduplication

5) Alerting and UX

End-to-end test checklist

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.