Home → Blog

You need to programmatically detect earthquake-related disruptions that could impact ocean freight schedules at a specific port, and you want a clean PHP implementation that you can ship today. By the end of this guide, you’ll be able to call the FreightPulse Weather category disruptions endpoint for earthquakes, authenticate with X-API-Key, parse the standard response envelope, and safely integrate the feed into your ops or planning system without guessing fields or quoting live fares.

What you’ll integrate and why it matters

This guide focuses on Weather-category natural hazards—specifically, the FreightPulse “Earthquake Disruptions” lookup. The endpoint returns a standard envelope so you can reliably detect when new hazard data is available. You’ll learn:

Illustration: How to Get Earthquake Disruptions

Scope note: The Weather category here is limited to natural hazards data (GDACS/USGS/NOAA) and the FreightPulse disruption lookup for earthquakes. This guide does not cover labor actions, canals, or live AIS wait times.

Key API behaviors and constraints you must know first

Quick-start: Verify your access with the official curl

Paste this cURL into your terminal. It hits the Weather disruptions endpoint for earthquakes at the Los Angeles seaport (USLAX). Replace the key header value with YOUR_API_KEY or omit it if you’re testing as a guest (subject to guest limits):

curl -H "X-API-Key: YOUR_API_KEY" "https://freightpulsehq.com/api/v1/disruptions?port=USLAX&type=earthquake"

Tip: Persist your key in an environment variable (e.g., export FREIGHTPULSE_KEY=YOUR_API_KEY) and expand it in scripts to avoid hardcoding.

Official sample response structure

The FreightPulse API consistently wraps responses in an envelope of the form {"success":true,"data":{...}}. The official sample below shows the envelope and meta shape you should code against. Copy the JSON exactly for tests that validate envelope parsing and basic metadata extraction.

{
"success": true,
"data": {
"timestamp": "2026-10-09T00:00:25+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": "cbc16380-e0cb-40d9-b1ba-e5215487b1eb"
}
}

Fields you will actually use in code regardless of category:

Your Weather/earthquake integration should always read success and data before interpreting hazard-specific structures.

PHP: Call Earthquake Disruptions and parse the envelope

This PHP sample calls the disruptions endpoint for earthquakes at USLAX, sets the X-API-Key header, checks the envelope, and demonstrates safe guards for missing keys while remaining strictly aligned with the published envelope contract.

<?php
$endpoint = "https://freightpulsehq.com/api/v1/disruptions?port=USLAX&type=earthquake";
$apiKey = getenv("FREIGHTPULSE_KEY");
$headers = [
"Accept: application/json",
$apiKey ? "X-API-Key: " . $apiKey : null
];
$headers = array_values(array_filter($headers));

$ch = curl_init($endpoint);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_TIMEOUT => 20
]);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curlErr = curl_error($ch);
curl_close($ch);

if ($response === false) {
// Transport error; surface curl error and stop
http_response_code(502);
echo json_encode(["error" => "Transport error", "detail" => $curlErr, "status" => $httpCode], JSON_PRETTY_PRINT);
exit;
}

$decoded = json_decode($response, true);

// Validate envelope
if (!is_array($decoded) || !array_key_exists("success", $decoded)) {
http_response_code(500);
echo json_encode(["error" => "Unexpected response structure", "raw" => $response], JSON_PRETTY_PRINT);
exit;
}

if ($decoded["success"] !== true) {
// Graceful handling if API signals a logical error
$meta = isset($decoded["meta"]) ? $decoded["meta"] : null;
echo json_encode(["ok" => false, "meta" => $meta], JSON_PRETTY_PRINT);
exit;
}

// At this point, "data" exists per envelope contract.
// Since field-level schema is not specified here, handle defensively.
$data = isset($decoded["data"]) ? $decoded["data"] : [];

$timestamp = isset($data["timestamp"]) ? $data["timestamp"] : null;

// Basic projection for downstream systems: forward the envelope and a few
// commonly present metadata fields without assuming hazard-specific keys.
$out = [
"ok" => true,
"timestamp" => $timestamp,
"data" => $data
];

header("Content-Type: application/json");
echo json_encode($out, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);

Notes for production hardening:

Python: Minimal verification client for the same lookup

Use this to smoke-test connectivity and log the top-level envelope. It calls the same Weather disruptions endpoint for earthquakes.

import os
import sys
import json
import requests

endpoint = "https://freightpulsehq.com/api/v1/disruptions"
params = {"port": "USLAX", "type": "earthquake"}
api_key = os.getenv("FREIGHTPULSE_KEY") # export FREIGHTPULSE_KEY=YOUR_API_KEY

headers = {"Accept": "application/json"}
if api_key:
headers["X-API-Key"] = api_key

try:
r = requests.get(endpoint, params=params, headers=headers, timeout=20)
r.raise_for_status()
except requests.RequestException as e:
print(json.dumps({"error": "transport", "detail": str(e)}))
sys.exit(2)

try:
payload = r.json()
except ValueError:
print(json.dumps({"error": "invalid_json", "raw": r.text[:800]}))
sys.exit(3)

if not isinstance(payload, dict) or "success" not in payload:
print(json.dumps({"error": "bad_envelope", "raw": payload}))
sys.exit(4)

if payload.get("success") is not True:
print(json.dumps({"ok": False, "meta": payload.get("meta")}))
sys.exit(1)

data = payload.get("data", {})
print(json.dumps({
"ok": True,
"timestamp": data.get("timestamp"),
"meta": payload.get("meta"),
"keys_in_data": list(data.keys()) if isinstance(data, dict) else None
}, indent=2))

Request composition and reliability patterns

Authentication and quotas

Send the header X-API-Key: YOUR_API_KEY on each request. If you test without a key, the service allows guest access with a cap of 100 requests per day per IP. Build your client to degrade gracefully when you approach the guest cap, or add your key to unlock your production throughput.

Envelope-first parsing

FreightPulse wraps all responses with success and data. Your first two lines of parsing logic should verify success === true and that data exists and is an object. This makes your integration resilient across Weather lookups as schemas evolve.

Handling timestamps and timezones

Timestamps are ISO 8601 with timezone offsets (e.g., 2026-10-09T00:00:25+00:00). Normalize to UTC in your storage layer and keep the raw string for audit logs. For cache invalidation and scheduling pipelines, key off data.timestamp rather than client clock time.

Error handling and observability

Operational context: Earthquakes and port congestion

This Weather lookup focuses on natural hazard signals from GDACS/USGS/NOAA. Use it to flag potential operational risk at a port such as USLAX. If you combine it with congestion context from FreightPulse, remember that port congestion is IMF PortWatch-derived, lagged roughly 6–7 days, reported as a 7-day average versus a 90-day baseline. It is not live AIS wait times, so avoid building alerting that interprets it as same-day queue length.

Because the endpoint is hazards-focused, do not attach or imply a real-time freight rate in USD as “today’s price.” Keep rate quoting logic separate and ensure your UI labels earthquake-derived risk appropriately.

Testing strategy without overfitting to fields

Without assuming any field that isn’t explicitly documented here, you can still create robust tests:

Deployment checklist

Where to go next

If you need endpoint-by-endpoint field definitions or additional Weather lookups, read the official docs and keep your integration envelope-driven to minimize breakage on field adds:

FAQ

Q: Can I use the disruptions endpoint without an API key?
A: Yes. Guest requests are allowed up to 100 requests per day per IP. For production, set X-API-Key: YOUR_API_KEY to avoid throttling.

Q: Is the port congestion signal live?
A: No. FreightPulse port congestion references IMF PortWatch and is lagged ~6–7 days, reported as a 7-day average versus a 90-day baseline, not live AIS wait times.

Q: What sources back the earthquake data?
A: Natural hazards only from GDACS/USGS/NOAA. The disruptions lookup does not include strikes, canals, or other non-weather categories.

Q: Can I attach a USD freight rate to the earthquake response as today’s price?
A: No. Do not quote a freight-rates USD fare as today’s price from this Weather disruptions endpoint.

Q: How should I parse the response safely if the event fields change?
A: Always check the envelope first—success and data—then gate optional logic behind existence checks. Use data.timestamp for staleness and meta.request_id for log correlation.

Ready to integrate the Earthquake Disruptions lookup with proper authentication and envelope parsing? Create your API key and start testing today: Register.