How BtSh sends freight status back to your ERP.
A webhook is BtSh calling your system when something important changes. It removes the need for logistics teams to keep refreshing dashboards or for ERPs to poll continuously.
Webhooks in one sentence
Instead of your ERP asking BtSh “has anything changed?” every few minutes, BtSh sends an HTTPS
POST to an endpoint your company registers, the moment a load or trip changes state.
Your integration reads the event and updates the matching shipment row in SAP, Oracle, Microsoft
Dynamics or your TMS.
Which events BtSh sends
Events cover the commercial life of a load, the physical trip and the paperwork that follows. Typical subscriptions for an enterprise shipper:
load.created load.matched load.escrow_funded load.pickup_confirmed load.in_transit load.delivered load.completed load.cancelled load.exception trip.arrived_pickup trip.departed_pickup trip.near_delivery trip.arrived_destination trip.delay_detected trip.route_deviation document.pod_available payment.received payment.failed
Most ERPs only need a handful: load.matched to show a truck is assigned, load.in_transit and trip.near_delivery for the warehouse, and load.delivered plus document.pod_available to close the shipment and trigger invoicing.
What each delivery looks like
Every delivery is a JSON body with headers that tell your system exactly what it received:
POST https://erp.yourcompany.com/btsh/webhooks Content-Type: application/json User-Agent: BtSh-Connect/1.0 X-BTSH-Event: load.delivered X-BTSH-Event-Id: ... X-BTSH-Delivery-Id: ... X-BTSH-Timestamp: 1767225600 X-BTSH-Signature: sha256=...
How to trust it: verify the signature
Each endpoint has its own signing secret. BtSh computes an HMAC-SHA256 over the timestamp, a full stop
and the raw request body, and sends it as X-BTSH-Signature. Your integration repeats the
same calculation with its copy of the secret and rejects anything that does not match — so a
forged “delivered” event can never close a shipment in your ERP.
expected = "sha256=" + HMAC_SHA256(secret, timestamp + "." + raw_body) accept only if expected == X-BTSH-Signature
Verify the signature against the exact bytes received, before parsing or re-serialising the JSON. Also reject timestamps that are too old, so a captured request cannot be replayed later.
What happens if your system is down
A delivery counts as successful only when your endpoint answers with a 2xx status. If it times out or returns an error, BtSh retries on a widening schedule — after about 1 minute, 5 minutes, 15 minutes, 1 hour, 6 hours and 24 hours. After the final attempt the delivery is parked as dead-letter, visible to your integration team, rather than silently lost.
Make your handler idempotent
Because of retries, the same event can arrive more than once. Store the
X-BTSH-Event-Id you have processed and ignore repeats. Reply with 2xx quickly and do
heavy ERP work in the background, so slow processing is never mistaken for a failed delivery.
Webhooks plus the Loads API
Webhooks are the return path. Loads go in through the BtSh Loads API (one authenticated request per shipment, with an idempotency key), and status comes back through webhooks — so the ERP stays the system of record while BtSh executes the freight. Read how your ERP can send freight directly to BtSh for the first half of the integration.
Planning an enterprise freight integration?
BtSh corporate workspaces and production API access are provisioned through our enterprise onboarding team.
Explore BtSh Enterprise Shipping