Gareth Wilson Gareth Wilson

Guide to Flexport Webhooks: Features and Best Practices

Published


Flexport webhooks notify your systems about freight milestones: a shipment is created, a shipment leg departs, a booking updates. If you're building logistics visibility on Flexport, webhooks are how you react to milestones without polling.

This guide covers how Flexport (classic freight) webhooks work, the events you'll handle, how to verify the X-Hub-Signature headers, and the best practices for production.

What are Flexport webhooks?

Flexport freight webhooks are HTTP POSTs delivered to an endpoint you configure, each carrying a Flexport "Event" object. Flexport signs deliveries GitHub/X-Hub style, with two headers keyed on a per-endpoint secret token: X-Hub-Signature (HMAC-SHA1, being deprecated) and X-Hub-Signature-256 (HMAC-SHA256, recommended).

This guide covers the classic freight webhooks. Flexport also has a newer Logistics API with its own webhook endpoints and Order.*/Shipment.* events; if your integration is on that product, its scheme and envelope differ.

Flexport webhook features

FeatureDetails
ConfigurationAccount Settings (UI-created endpoints with a secret token)
Signature headersX-Hub-Signature (SHA1, deprecating), X-Hub-Signature-256 (SHA256, recommended)
Signature schemesha256=<hex> HMAC of the raw body, keyed with the per-endpoint secret token
Event format/object#event (e.g. /shipment#created)
PayloadA Flexport "Event" object
AcknowledgementReturn HTTP 200 (respond fast, process async)
SDKNone

Common events

Flexport milestone identifiers use the /object#event format (not object.event):

EventFires when
/shipment#createdA shipment is created
/shipment_leg#departedA shipment leg departs
/shipment#updatedA shipment updates
/booking#createdA booking is created

Branch on the /object#event identifier. Some milestones are available upon request. Consult Flexport's Milestones reference for the full list.

Setting up Flexport webhooks

Configure endpoints and their secret token in the account Settings section (classic freight uses UI creation rather than a public create-endpoint API). Your endpoint must return HTTP 200; respond fast and process asynchronously, since some milestones can be heavy.

Securing Flexport webhooks

Each delivery carries X-Hub-Signature (SHA1) and X-Hub-Signature-256 (SHA256). Prefer the SHA256 header: it's sha256= followed by a hex HMAC-SHA256 of the raw request body, keyed with your per-endpoint secret token. Verify against the raw bytes and compare in constant time.

const crypto = require("crypto");

const SECRET = process.env.FLEXPORT_WEBHOOK_SECRET; // per-endpoint secret token

function verify(rawBody, signatureHeader) {
  const expected = "sha256=" +
    crypto.createHmac("sha256", SECRET).update(rawBody).digest("hex");
  const a = Buffer.from(expected);
  const b = Buffer.from(signatureHeader || "");
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

app.post("/webhook", express.raw({ type: "application/json" }), (req, res) => {
  if (!verify(req.body, req.headers["x-hub-signature-256"])) {
    return res.sendStatus(401);
  }

  res.sendStatus(200); // acknowledge fast
  processQueue.add(JSON.parse(req.body)); // process asynchronously
});

The same check in Python:

import hashlib
import hmac
import os

SECRET = os.environ["FLEXPORT_WEBHOOK_SECRET"].encode()


def verify(raw_body: bytes, signature_header: str) -> bool:
    expected = "sha256=" + hmac.new(SECRET, raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature_header or "")

Flexport webhook limitations and pain points

SHA1 vs SHA256

The Problem: Flexport sends both X-Hub-Signature (SHA1) and X-Hub-Signature-256 (SHA256). Verifying the deprecated SHA1 header ties you to a weaker, sunsetting scheme.

Why It Happens: Flexport keeps the legacy SHA1 header for compatibility while recommending SHA256.

Workarounds:

  • Verify the X-Hub-Signature-256 header and treat SHA1 as legacy.

How Hookdeck Can Help: Hookdeck verifies the SHA256 signature at the edge, so your app receives pre-verified events without depending on the deprecated header.

The /object#event naming

The Problem: Milestone identifiers use /object#event (e.g. /shipment#created), not the object.event form many integrations assume. Matching the wrong format silently ignores events.

Why It Happens: Flexport's milestone reference uses the /object#event convention.

Workarounds:

  • Branch on the exact /object#event identifier from the payload.

How Hookdeck Can Help: Hookdeck's filters route on the fields you actually receive, so the naming convention is handled in one place.

UI-only endpoint creation

The Problem: Classic freight endpoints and their secret tokens are created in the Settings UI, not via a public API, which complicates programmatic setup and environment parity.

Why It Happens: The classic product manages endpoints through the dashboard.

Workarounds:

  • Document endpoint configuration and secrets as part of your setup runbook.

How Hookdeck Can Help: Hookdeck gives you an API-manageable ingestion URL in front of Flexport, so your side of the configuration is reproducible.

Raw-body handling and duplicates

The Problem: The signature is over the raw body, and deliveries can repeat, so re-serializing the body breaks verification and duplicates can double-process.

Why It Happens: The signed content is the exact bytes; at-least-once delivery brings duplicates.

Workarounds:

  • Verify against the raw body and dedupe on an event id.

How Hookdeck Can Help: Hookdeck verifies against the bytes as received and deduplicates. See our guide to webhook idempotency.

Best practices

Verify X-Hub-Signature-256 over the raw body

Use sha256= + hex HMAC-SHA256 over the raw body with the per-endpoint secret, and compare in constant time. Treat SHA1 as legacy.

Branch on /object#event

Match the exact /object#event identifier, not object.event.

Acknowledge fast, process asynchronously

Return 200 immediately and defer work to a queue. See why to process webhooks asynchronously.

Dedupe

Dedupe on an event id so repeats don't double-process.

Make Flexport webhooks production-ready

Hookdeck verifies X-Hub-Signature-256, deduplicates, and durably queues every freight milestone

Conclusion

Flexport freight webhooks are signed GitHub/X-Hub style, verify the X-Hub-Signature-256 (SHA256) header over the raw body with your per-endpoint secret and treat SHA1 as legacy. Branch on the /object#event milestone identifiers, acknowledge fast, and dedupe.

Hookdeck verifies the signature, deduplicates, and durably queues every event at the edge, so your app only ever processes verified, unique milestones.

Get started with Hookdeck for free and handle Flexport webhooks reliably in minutes.


Gareth Wilson

Gareth Wilson

Product Marketing

Multi-time founding marketer, Gareth is PMM at Hookdeck and author of the newsletter, Community Inc.