Home → Blog

Carrier churn hurts twice: once when a high-performing carrier quietly reduces tender acceptance on your lanes and again when your ops team scrambles to rebook at higher spot rates. For freight forwarders and 3PLs, the fix isn’t just better relationship management—it’s earlier signal capture. If you can see deterioration patterns weeks before they materialize in service failures, you can intervene with incentives, backup carriers, and adjusted ETAs that keep customers satisfied.

This post shows how to detect early churn signals using FreightPulse event patterns and unified logistics intelligence. FreightPulse consolidates operational signals—live US FTL quotes, port activity trends, regulatory carrier lookups, global disruption alerts, and fuel price trajectories—behind a single REST API. Instead of piecing together multiple providers, you can build a churn early-warning pipeline with one consistent JSON schema and predictable semantics.

We’ll start by defining practical churn indicators (missed tenders, rising spot deltas vs contract, congestion exposure, and regulatory risk), then wire them to FreightPulse endpoints. You’ll see how to stitch event patterns across /carriers, /freight-rates, /port-congestion, /disruptions, /fuel-prices, and /historical to score churn risk per carrier-lane-week—and take action before it becomes a service failure.

Introduction

Carrier churn rarely announces itself. It lurks in soft signals: an uptick in spot quotes relative to your historical baseline, a cluster of cyclone alerts near a lane-critical port, or a safety-rating change that tightens a carrier’s capacity. By the time acceptance rates fall, your lead time to replace capacity has shrunk, spot premiums rise, and on-time performance dips. The cost is not just linehaul—it’s escalations, manual rework, and customer credits.

The challenge for developers and operations teams is that these signals are scattered across agencies and providers. You might parse EIA spreadsheets for fuel trends, poll a freight marketplace for live quotes, query FMCSA/FMC directories for compliance changes, keep a separate AIS port feed, and cobble together disaster alerts from multiple dashboards. This fragmentation makes it hard to unify time series and compute a coherent churn risk score per carrier-lane-week.

FreightPulse addresses this by normalizing cross-domain logistics data behind a single REST API. You query the same base URL for FTL quotes, port activity (via IMF PortWatch), fuel price levels, FMCSA/FMC lookups, and global natural-disruption alerts. This unification is the missing fabric to detect churn early—because churn is rarely one signal; it’s an event pattern.

Why FreightPulse

What sets FreightPulse apart for churn detection workflows isn’t just breadth of data—it’s the way it reduces developer friction and operational time-to-insight. Four differentiators matter most when building carrier retention analytics and alerting:

In practical terms, this consolidation replaces half a dozen low-level integrations. You build normalized features—“spot_delta_7d,” “port_ratio_vs_baseline,” “diesel_trend_30d,” “carrier_status_active”—that combine into a churn risk signal. Then you can notify carrier managers, adjust tender strategies, and reprice proactively where needed.

Quick Start

Base URL:

https://freightpulsehq.com/api/v1

Authentication is sent in a header. Below is a first request to retrieve national fuel prices. You can run it as-is with your own environment configuration for the header.

curl -H "X-API-Key: YOUR_API_KEY" \
"https://freightpulsehq.com/api/v1/fuel-prices"

Example JSON response:

{
"success": true,
"data": {
"timestamp": "2026-07-30T12:00:00Z",
"source": "EIA (U.S. Energy Information Administration)",
"currency": "USD",
"unit": "gallon",
"data": {
"diesel": {
"national_average": 3.847,
"change_week": -0.023,
"change_percent": -0.6,
"regions": {
"east_coast": 3.912,
"midwest": 3.756,
"gulf_coast": 3.623,
"rocky_mountain": 3.891,
"west_coast": 4.456,
"california": 4.892
},
"historical": {
"30d_avg": 3.82,
"90d_avg": 3.75,
"yoy_change_percent": -8.2
}
},
"gasoline": {
"national_average": 3.156,
"historical": {
"30d_avg": 3.1,
"90d_avg": 3.05,
"yoy_change_percent": 1.1
}
}
}
}
}

Key fields you’ll reuse for churn analytics:

Core Endpoints

1) Carrier Ground Truth: GET /carriers

Use this endpoint to verify a trucking carrier (FMCSA) or ocean NVOCC/OTI (FMC) by ID or name. For churn prediction, look for status changes, safety ratings, and rough size indicators (drivers) that may affect capacity or risk tolerance on your lanes.

Endpoint:

GET /carriers

Key params:

cURL:

curl -H "X-API-Key: YOUR_API_KEY" \
"https://freightpulsehq.com/api/v1/carriers?q=54283"

Example response:

{
"success": true,
"data": {
"type": "trucking",
"query": "54283",
"results": [
{
"dot_number": 54283,
"legal_name": "SWIFT TRANSPORTATION COMPANY OF ARIZONA LLC",
"status": "active",
"safety_rating": "S",
"drivers": 12883,
"address": {
"city": "Phoenix",
"state": "AZ",
"country": "US"
}
}
]
}
}

How to use:

Error handling:

2) Live Rate Pressure: GET /freight-rates

You can query live FTL quotes for US lanes. A rising spread between live spot quotes and your contracted rates is one of the earliest churn signals. If your contracted carrier consistently sees a widening spot premium, their opportunity cost of accepting your tenders grows—churn pressure rises.

Endpoint:

GET /freight-rates

Key params:

cURL:

curl -H "X-API-Key: YOUR_API_KEY" \
"https://freightpulsehq.com/api/v1/freight-rates?mode=trucking&origin_zip=10001&destination_zip=90210"

Example response:

{
"success": true,
"data": {
"mode": "trucking",
"service": "FTL (53' dry van)",
"source": "Warp",
"price_usd": 7207.92,
"transit_days": 4,
"pickup_date": "2026-08-24",
"delivery_date": "2026-08-28"
}
}

How to use:

3) Structural Friction Ahead: GET /port-congestion

Port congestion is a macro friction that ripples into inland trucking velocity and equipment availability. FreightPulse approximates congestion using IMF PortWatch AIS-derived activity: a 7-day average of port calls compared to a 90-day baseline. Important: this is not real-time AIS; data typically lags by ~6–7 days and is meant for trend analysis, not live vessel ETAs.

Endpoint:

GET /port-congestion

Key params:

cURL:

curl -H "X-API-Key: YOUR_API_KEY" \
"https://freightpulsehq.com/api/v1/port-congestion?port=USLAX"

Example response:

{
"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 use:

4) Exogenous Shock Radar: GET /disruptions

Severe weather and natural hazards disrupt capacity and routing decisions—often lowering tender acceptance or causing higher spot quotes. The /disruptions endpoint aggregates events from GDACS, USGS, and NOAA/NWS and lets you filter by hazard type, severity, and port proximity.

Endpoint:

GET /disruptions

Key params:

cURL:

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

Example response:

{
"success": true,
"data": {
"results": [
{
"id": "gdacs:TC:1001305",
"type": "cyclone",
"severity": "moderate",
"title": "Tropical Cyclone SAUDEL-26",
"country": "Japan",
"starts_at": "2026-08-18T12:00:00+00:00",
"source": "GDACS"
}
]
}
}

How to use:

5) Macro Cost Driver Time Series: GET /historical and GET /fuel-prices

Fuel prices underpin carrier margins and tender decisions. Small week-over-week changes can alter acceptance behavior on marginal lanes. Use /fuel-prices for the current level and weekly change; use /historical for time series you can blend into trend features or dashboards.

Endpoints:

GET /fuel-prices
GET /historical

Key params for /historical:

cURL (diesel national 30-day series):

curl -H "X-API-Key: YOUR_API_KEY" \
"https://freightpulsehq.com/api/v1/historical?metric=fuel_price_diesel_national&period=30d"

Example response:

{
"success": true,
"data": {
"metric": "fuel_price_diesel_national",
"period": "30d",
"series": [
{ "date": "2026-07-27", "value": 5.257 },
{ "date": "2026-08-03", "value": 5.343 }
]
}
}

How to use:

Putting It Together: A Churn Early-Warning Pattern

An effective churn signal blends price pressure, structural friction, exogenous shocks, and carrier ground truth. Here’s a framework to compute a weekly score per carrier and lane:

If the composite score breaches a threshold, create a task: notify the carrier rep, adjust tender allocations to include secondary carriers, and hedge with spot capacity. If the trigger is fuel-only, update surcharge calculators; if it’s congestion- or disruption-led, communicate extended ETAs and pre-position backups in adjacent markets.

Implementation: Code Patterns and Observability

Below are practical examples for fetching signals and instrumenting reliability. Use standardized envelopes, retries with exponential backoff, and circuit breakers per endpoint. Log success=false responses with error strings for triage; align polling cadence to signal semantics (spot prices hourly or daily, port congestion daily, disruptions near-real-time polling, carriers weekly).

JavaScript (Node.js) example: Fetch live FTL quote and compute a delta

import fetch from "node-fetch";

async function getSpotQuote(originZip, destZip) {
const url = `https://freightpulsehq.com/api/v1/freight-rates?mode=trucking&origin_zip=${originZip}&destination_zip=${destZip}`;
const res = await fetch(url, {
headers: { "X-API-Key": process.env.FP_KEY }
});
const json = await res.json();
if (!json.success || !json.data || typeof json.data.price_usd !== "number") {
throw new Error("Quote unavailable or malformed response");
}
return json.data;
}

(async () => {
const contractRate = 6200; // example, from your TMS
const quote = await getSpotQuote("10001", "90210");
const delta = quote.price_usd - contractRate;
console.log({ lane: "10001->90210", spot: quote.price_usd, delta });
})();

Python example: Blend diesel momentum with port congestion

import os
import requests
from datetime import datetime

BASE = "https://freightpulsehq.com/api/v1"
HEADERS = {"X-API-Key": os.getenv("FP_KEY")}

def get_diesel_series(period="90d"):
r = requests.get(f"{BASE}/historical", headers=HEADERS,
params={"metric": "fuel_price_diesel_national", "period": period})
j = r.json()
assert j.get("success"), j
return j["data"]["series"]

def slope(series):
# simple linear slope: (last - first) / count
if len(series) < 2:
return 0.0
return (series[-1]["value"] - series[0]["value"]) / len(series)

def get_port_congestion(locode="USLAX"):
r = requests.get(f"{BASE}/port-congestion", headers=HEADERS, params={"port": locode})
j = r.json()
assert j.get("success"), j
return j["data"]["results"][0]

diesel = get_diesel_series("30d")
diesel_slope = slope(diesel)

congestion = get_port_congestion("USLAX")
ratio = congestion["metrics"]["ratio_vs_baseline"]
as_of = congestion["as_of"]

print({
"diesel_slope_30d": round(diesel_slope, 4),
"lax_ratio_vs_baseline": ratio,
"as_of": as_of
})

Reliability tips:

Interpreting Sample Responses in Your Churn Model

Let’s walk through a combined sample showing how the same week can light up multiple signals.

Sample pack: fuel, rates, congestion, disruptions

{
"fuel": {
"success": true,
"data": {
"timestamp": "2026-07-30T12:00:00Z",
"data": {
"diesel": {
"national_average": 3.847,
"change_week": 0.041,
"historical": { "30d_avg": 3.82, "90d_avg": 3.75, "yoy_change_percent": -6.9 }
}
}
}
},
"rate": {
"success": true,
"data": {
"mode": "trucking",
"price_usd": 3550.25,
"transit_days": 2,
"pickup_date": "2026-08-22",
"delivery_date": "2026-08-24"
}
},
"congestion": {
"success": true,
"data": {
"results": [{
"port": "Los Angeles-Long Beach",
"locode": "US LAX",
"country": "United States",
"congestion": "high",
"as_of": "2026-08-15",
"metrics": { "recent_avg_portcalls_per_day": 7.1, "baseline_avg_portcalls_per_day": 10.5, "ratio_vs_baseline": 0.68 }
}]
}
},
"disruptions": {
"success": true,
"data": {
"results": [{
"id": "noaa:wx:storm-95731",
"type": "severe_weather",
"severity": "high",
"title": "Severe thunderstorm watch",
"country": "United States",
"starts_at": "2026-08-19T18:00:00Z",
"source": "NOAA/NWS"
}]
}
}
}

Interpretation:

Real-World Use Cases

1) Carrier retention scorecard in your TMS

Build a weekly score per carrier-lane using /freight-rates (spot deltas), /historical (fuel momentum), /port-congestion (ratio_vs_baseline), /disruptions (hazard count/severity near key ports), and /carriers (status, safety_rating). Display red/yellow/green statuses and generate proactive playbooks: negotiate temporary surcharges, diversify tender allocations, or bring forward backup carriers for lanes flagged red.

2) Port exposure dashboard for routing planners

Use /port-congestion and /historical port_congestion:<portid> series to plot 90-day trends across ~20 curated ports. Layer /disruptions filtered by port to show near-term hazard overlays. When ratio_vs_baseline dips and hazards cluster, planners can redirect flows (e.g., PNW instead of LA/LB) preemptively, preventing last-minute rejections from carriers feeling the squeeze.

3) Fuel-adjusted spot procurement bot

Combine /fuel-prices with /freight-rates to create a normalized “spot minus fuel-expected” score. When spot rates detach from fuel fundamentals, your bot escalates to human review or widens quote sourcing. This avoids overpaying in temporary spikes and reduces the chance that carriers churn because your tenders are lagging market reality.

Expanded Endpoint Deep Dive and Best Practices

/fuel-prices details and strategies

Purpose: Get current national and regional fuel levels plus short/medium-term context. Business value: calibrate surcharge models and anticipate carrier margin pressure on diesel-heavy lanes.

Fields to log:

Performance tips:

/freight-rates details and strategies

Purpose: Probe current market rates for US FTL and select ocean/air corridors. Business value: a fast pressure gauge on carrier opportunity cost.

Key params impact:

Error handling:

/port-congestion details and strategies

Purpose: Track trend-level port activity as an indicator of gate, berth, or yard friction that can propagate inland. Business value: anticipate load imbalances and drayage throughput impacts that influence carrier capacity and appetite.

Data semantics:

Best practice:

/disruptions details and strategies

Purpose: Detect acute hazards that can break your weekly plan—cyclones, quakes, wildfires, severe weather. Business value: preempt service failures and communicate revised ETAs before your customer calls.

Key tactics:

/carriers details and strategies

Purpose: Verify the legal and safety posture of carriers. Business value: reduce surprises due to regulatory shifts or capacity constraints.

Operational loop:

/historical details and strategies

Purpose: Pull time series for diesel/gasoline and select port congestion metrics. Business value: trend analysis and smoothing for robust churn features.

Features:

Error Scenarios and Defensive Engineering

FreightPulse responses share a consistent envelope. Always check success. For application stability:

Observability:

End-to-End Example: Churn Risk Microservice

Here’s a high-level flow for a service that assigns a churn score to each carrier-lane, daily:

  1. Input set: list of lanes with contract rates and primary carriers; mapping from lanes to gateway ports.
  2. Fetch: - For each lane, pull /freight-rates (spot). - For each gateway port, pull /port-congestion and /disruptions. - Pull /fuel-prices and /historical (diesel) once per run. - For each primary carrier, pull /carriers weekly (or daily during audits).
  3. Features: - spot_delta = spot - contract. - fuel_slope_30d from /historical. - port_ratio = ratio_vs_baseline for mapped ports. - hazard_max_severity around those ports in last 72 hours. - carrier_ok = status == active and safety_rating stable.
  4. Score: - risk = w1*norm(spot_delta) + w2*relu(fuel_slope_30d) + w3*(1 - port_ratio) + w4*hazard_severity - w5*carrier_ok_bonus
  5. Actions: - risk > T1: notify carrier rep with context. - risk > T2: split tenders 70/30 with secondary carrier; recalc ETAs. - risk > T3: escalate; request revised pricing or activate contingency capacity.

All lookups, trends, and alerts come from the same API, which simplifies retries, caching, and on-call procedures.

Additional Complete JSON Examples

/carriers ocean lookup by name

{
"success": true,
"data": {
"type": "ocean",
"query": "Example NVOCC",
"results": [
{
"org_number": "OTI-12345",
"legal_name": "EXAMPLE NVOCC LOGISTICS LLC",
"status": "active",
"address": { "city": "Jersey City", "state": "NJ", "country": "US" }
}
]
}
}

/disruptions filtered by type and country

{
"success": true,
"data": {
"results": [
{
"id": "usgs:EQ:2026-08-17-abc123",
"type": "earthquake",
"severity": "moderate",
"title": "M5.1 earthquake",
"country": "United States",
"starts_at": "2026-08-17T04:26:00Z",
"source": "USGS"
},
{
"id": "noaa:wx:heat-2026-0817",
"type": "severe_weather",
"severity": "low",
"title": "Excessive heat advisory",
"country": "United States",
"starts_at": "2026-08-17T12:00:00Z",
"source": "NOAA/NWS"
}
]
}
}

/historical port congestion series (example)

{
"success": true,
"data": {
"metric": "port_congestion:USLAX",
"period": "90d",
"series": [
{ "date": "2026-05-20", "value": 0.96 },
{ "date": "2026-06-20", "value": 0.89 },
{ "date": "2026-07-20", "value": 0.78 },
{ "date": "2026-08-14", "value": 0.70 }
]
}
}

FAQ

How often do FreightPulse fuel prices update?

Fuel price data reflects the latest releases aligned with EIA reporting cadence and includes weekly changes plus historical averages. For most planning and surcharge scenarios, fetching once daily is sufficient, with historical series available for 30/90-day context.

Can I look up ocean carriers as well as trucking carriers?

Yes. The /carriers endpoint supports type=ocean for NVOCC/OTI lookups from the FMC directory and type=trucking for FMCSA SAFER data. You can query by organization number or legal name to verify status and basic identity.

Does the port congestion data reflect real-time vessel wait times?

No. Port congestion uses IMF PortWatch AIS-derived activity and is an approximation designed for trend analysis. It represents a 7-day average of port calls versus a 90-day baseline and typically lags by about 6–7 days, so treat it as a medium-frequency planning signal.

How should I combine disruptions with port congestion to forecast risk?

Use disruptions for acute, near-term hazard scoring and port congestion for structural friction. When both light up simultaneously near a lane’s gateway, increase your churn risk score and activate mitigation steps like backup carriers and revised ETAs.

What if a required parameter is missing on an endpoint like /freight-rates?

Validate inputs upfront and always check the response envelope. For /freight-rates, missing required params may return a successful HTTP status with an unavailable payload; verify the presence and type of expected fields (e.g., price_usd) before using the result.

Conclusion + CTA

Carrier churn is an event pattern, not a single datapoint. If you only watch tender acceptance after it drops, you’re reacting too late. By blending rate pressure, fuel costs, congestion trends, exogenous hazards, and carrier ground truth into a single weekly score, you put your teams in front of the problem—reallocating tenders, communicating proactive ETAs, and retaining high-value partners before relationships fray.

The fastest way to production is to centralize your logistics intelligence. With unified endpoints for rates, fuel prices, port congestion, disruptions, and carrier verification, FreightPulse lets you build a churn early-warning system without stitching together half a dozen feeds or normalizing inconsistent schemas.

Start instrumenting your churn signal today. Explore the API, wire your lanes and carriers, and ship your first alerts in hours—not weeks. Try FreightPulse for free and turn scattered signals into decisive action for your carrier network.