Integrations / Webhooks

Webhooks

Webhooks allow you to receive real-time events from FreightConnect without polling the API. Perfect for integrating with your TMS, accounting system, or custom apps.

Overview

Instead of continuously asking "Did anything change?", FreightConnect pushes events to you:

  • Load posted → webhook fires
  • Carrier quoted → webhook fires
  • Quote accepted → webhook fires
  • Shipment delivered → webhook fires
  • Settlement paid → webhook fires

You get the data immediately, enabling real-time workflows.

Setting Up Webhooks

  1. Go to SettingsIntegrationsWebhooks
  2. Click Add Webhook
  3. Enter your URL — where we'll POST events: https://yourdomain.com/freightconnect-webhook
  4. Select events to subscribe to (see list below)
  5. (Optional) Add custom headers for authentication
  6. Click Create

We'll send a test webhook to verify the URL works. If it fails, check that your endpoint is accessible from the internet.

Events

Load Lifecycle

  • load.created — load created but not yet posted
  • load.posted — load posted to carrier network; quotes starting to arrive
  • load.posted_cancelled — load posting cancelled (no carrier accepted yet)

Quote Events

  • quote.received — carrier submitted a quote
  • quote.accepted — you accepted a carrier quote; shipment is now active
  • quote.declined — you rejected a carrier quote
  • quote.auto_accepted — (Enterprise) automated quote acceptance based on your rules

Shipment Events

  • shipment.picked_up — pickup confirmed by carrier
  • shipment.in_transit — shipment en route
  • shipment.out_for_delivery — final leg (truck at destination city)
  • shipment.delivered — delivery confirmed

POD Events

  • pod.received — proof of delivery uploaded
  • pod.verified — POD reviewed and verified
  • pod.disputed — shipper disputed the delivery

Settlement Events

  • settlement.created — invoice generated; awaiting payment
  • settlement.paid — carrier payment received
  • settlement.disputed — carrier disputed the invoice
  • settlement.cancelled — load cancelled; no settlement needed

Webhook Payload Format

Every webhook includes:

{
  "event": "quote.received",
  "timestamp": "2026-04-13T14:30:00Z",
  "webhook_id": "webhook_abc123",
  "data": {
    "load_id": "load_xyz",
    "quote_id": "quote_123",
    "carrier_name": "ABC Trucking",
    "carrier_id": "carr_abc",
    "quoted_rate": 2.15,
    "fsc_score": 82,
    "eta": "2026-04-15T17:00:00Z"
  }
}

The data object contains the full resource details (load, quote, shipment, etc.).

Signature Verification

Every webhook includes an X-FreightConnect-Signature header. Verify it to ensure the request is authentic:

import hmac
import hashlib

def verify_webhook(request):
    signature = request.headers['X-FreightConnect-Signature']
    body = request.body  # raw body bytes, not parsed JSON
    
    # Get your webhook secret (from Settings → Webhooks → Show Secret)
    webhook_secret = 'whsec_...'
    
    expected_signature = hmac.new(
        webhook_secret.encode(),
        body,
        hashlib.sha256
    ).hexdigest()
    
    return hmac.compare_digest(signature, expected_signature)

# In your webhook handler:
if not verify_webhook(request):
    return 400  # Unauthorized
else:
    # Process the webhook
    process_webhook(request)

Retry Logic

We retry failed webhooks:

  1. Initial delivery attempt
  2. Retry after 5 seconds
  3. Retry after 30 seconds
  4. Retry after 1 minute
  5. Retry after 5 minutes
  6. Final retry after 30 minutes

If all 6 attempts fail, we stop retrying and flag it in your webhook logs.

Webhook Logs

View delivery status in SettingsIntegrationsWebhooksLogs:

  • Succeeded — webhook delivered and your endpoint returned 2xx
  • Failed — your endpoint returned an error or timed out
  • Timestamp — when we tried
  • Response — what your endpoint returned

Logs are retained for 30 days.

Testing Webhooks

  1. Go to SettingsWebhooks → select your webhook
  2. Click Send Test Event
  3. Select an event type (e.g., "quote.received")
  4. We send a sample webhook to your endpoint
  5. Check your logs to see if it was received

Perfect for testing your webhook handler before going live.

Best Practices

Always Respond Quickly

Your endpoint should:

  • Return a 2xx status immediately
  • Queue heavy processing (don't block)
  • Use async/background jobs for long tasks
@app.post("/freightconnect-webhook")
async def webhook(request: Request):
    body = await request.body()
    
    # Verify signature
    if not verify_webhook(request, body):
        return 400
    
    # Parse event
    event = json.loads(body)
    
    # Queue processing, return immediately
    queue.add_task(process_webhook, event)
    
    return 200

Idempotency

Webhooks can be delivered more than once (if we retry due to a timeout). Handle this:

def process_webhook(event):
    event_id = event['id']
    
    # Check if already processed
    if db.event_processed(event_id):
        return  # Already handled
    
    # Process the event
    handle_quote_received(event['data'])
    
    # Mark as processed
    db.mark_event_processed(event_id)

Use Webhook Secrets

Create different webhook URLs for different environments:

  • https://prod.yourdomain.com/freightconnect-webhook — production
  • https://staging.yourdomain.com/freightconnect-webhook — staging
  • Register different webhooks for each

Each webhook has its own secret key, so events don't leak between environments.

Monitor Webhook Health

Check your logs regularly:

  • High failure rate? Your endpoint might be down.
  • Delays? Your endpoint might be slow.

Set up alerts if webhook delivery fails for > 5 minutes.

Deleting Webhooks

Go to SettingsWebhooks → select webhook → Delete. No more events will be sent.

Troubleshooting

Webhook not being sent: Check that you've subscribed to the right events. If you only subscribed to "quote.received" but posted a load, you won't get a webhook.

Webhook signature fails: Make sure you're using the correct webhook secret (not your API key). Find it in SettingsWebhooksShow Secret.

Endpoint returns 500: Fix the error on your end. FreightConnect will retry 6 times, but you need to address the issue.

Too many webhook deliveries: If you're getting duplicates, use idempotency keys (see Best Practices above).

Rate Limiting

No rate limits on webhooks. We'll deliver as fast as your endpoint can handle them (as long as you respond quickly).

What's Next

Last updated: April 2026