Guide to Flexport Webhooks: Features and Best Practices
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
| Feature | Details |
|---|---|
| Configuration | Account Settings (UI-created endpoints with a secret token) |
| Signature headers | X-Hub-Signature (SHA1, deprecating), X-Hub-Signature-256 (SHA256, recommended) |
| Signature scheme | sha256=<hex> HMAC of the raw body, keyed with the per-endpoint secret token |
| Event format | /object#event (e.g. /shipment#created) |
| Payload | A Flexport "Event" object |
| Acknowledgement | Return HTTP 200 (respond fast, process async) |
| SDK | None |
Common events
Flexport milestone identifiers use the /object#event format (not object.event):
| Event | Fires when |
|---|---|
/shipment#created | A shipment is created |
/shipment_leg#departed | A shipment leg departs |
/shipment#updated | A shipment updates |
/booking#created | A 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-256header 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#eventidentifier 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.