Webhooks
Table of Contents
Super Dispatch uses webhooks to update an API client when various events (or actions) happen on the platform. An API client should subscribe to an action to receive updates and unsubscribe to stop it. All webhook requests are POST requests with a JSON payload.
You can see the diagram that explains when a webhook event is triggered in the document Flows.
Managing webhook subscriptions
The list of available webhook actions can be retrieved using the specific API endpoint. Deprecated webhook actions aren't returned.
The API client can subscribe to a webhook action by providing a callback URL:
curl -X "POST" "https://api.shipper.superdispatch.com/v1/public/webhooks/<webhook_action>/subscribe" \
-H 'Authorization: Bearer <access_token>' \
-H 'Content-Type: application/json; charset=utf-8' \
-d $'{
"callback_url": "<callback_url>"
}'
The response is a confirmation of the subscription:
{
"status": "success",
"data": {
"object": {
"is_active": true,
"created_at": "2019-11-19T21:44:57.979+0000",
"changed_at": "2019-11-19T21:44:57.979+0000",
"action": "<webhook_action>",
"verification_token": "87be7a34-238d-4378-bda9-4d93ffe50982",
"callback_url": "<callback_url>",
"guid": "9ea8edaf-874b-4dee-8be7-29ab169a21ea"
}
}
}
After a successful subscription, Super Dispatch starts sending POST requests to the provided callback URL when the webhook action happened (like order.picked_up or order.archived). For example, if the API client is subscribed to the order.created webhook action, the API server sends a request whenever a new order is created on Shipper TMS: via the API or manually on the user interface.
The verification_token field is utilized to confirm that webhook notifications received by API clients are sent by Super Dispatch.
You can unsubscribe from a webhook action:
curl -X "POST" "https://api.shipper.superdispatch.com/v1/public/webhooks/<webhook_action>/unsubscribe" \
-H 'Authorization: Bearer <access_token>'
The list of current webhook subscriptions can be retrieved:
curl -X "GET" "https://api.shipper.superdispatch.com/v1/public/webhooks" \
-H 'Authorization: Bearer <access_token>'
Payload
The payload (request body) always contains these default fields:
| Field | Type | Description |
|---|---|---|
action | string | The action name like order.created. See the list below. |
action_date | string | The date and time when the action happened. |
error_message | string | The error message (is sent when a previous action is failed). |
The payload also contains the target object guid like order_guid or offer_guid.
Retry policy
The webhook request timeout is 10 seconds. The API client that is subscribed to a webhook action should return a 2xx response in 60 seconds. Otherwise, the webhook request fails with a timeout. Furthermore, HTTP response codes like 3xx, 4xx, and 5xx fail the webhook request.
The retry policy is linear:
- interval: 60 seconds
- retry count: 5.
This means when the API received a failed response from the callback URL, it'll send 5 requests with 60 seconds of interval until it gets a successful response. It stops sending a request after 5th try.
Testing webhooks
We suggest using webhook.site during the implementation process to test the delivery and payload of webhook requests.
Actions
The actions supported by the Shipper API are below.
Ignored actions
We also send .ignored webhook actions when a carrier updates the order which status is already delivered on the Shipper TMS. These updates are ignored by default, but the corresponding events are sent to API clients to inform them that the carrier actually changed the order status.
Here's a quick explanation:
- A load offer is sent to a carrier (
offer.sentis sent) - The load offer is accepted by the carrier (
offer.acceptedis sent) - The corresponding order is manually marked as picked up on Shipper TMS (
order.manually_marked_as_picked_upis sent) - The order is manually marked as delivered on Shipper TMS (
order.manually_marked_as_deliveredis sent) - Then the order is marked as picked up on Carrier TMS (
order.picked_up.ignoredis sent, only works for shipper->carrier flow)
It is done to avoid confusion and inconsistencies in order statuses. For instance, if order with an active offer is manually marked as picked up and then as delivered prior to the carrier making any actions, an API client receives order.manually_marked_as_picked_up and order.manually_marked_as_delivered. If we sent order.picked_up after carrier picks up the order, it would confuse an API client to be informed about their delivered order being picked up again.
Order related actions
| Action | Is sent when... |
|---|---|
order.created | Order is created |
order.cancel | Order is canceled by shipper |
order.submitted_by_customer | Order is submitted to shipper by customer |
order.picked_up | Order is picked up |
order.picked_up.ignored | Order with active offer is manually marked as delivered, then it is picked up by the carrier |
order.delivered | Order is delivered |
order.delivered.ignored | Order with active offer is manually marked as delivered, then it is delivered by the carrier |
order.picked_up_bol | Triggered when pickup BOL becomes available |
order.delivered_bol | Triggered when delivery BOL becomes available |
order.paid | Shipper marks order paid to carrier |
order.unmark_as_paid | Shipper unmarks order as paid to carrier |
order.customer_paid | Order is marked as paid by customer |
order.invoiced | Order is invoiced by the carrier |
order.customer_invoiced | Order is invoiced to the customer |
order.archived | Order is archived |
order.marked_as_on_hold | Order is marked as on hold by shipper |
order.unmarked_as_on_hold | Order is unmarked as on hold by shipper |
order.unarchived | Order is unarchived |
order.posted_to_slb | Order is posted to Super Loadboard (SLB) |
order.removed_from_slb | Order is removed (unposted) from SLB |
order.booked | Order is booked by a preferred carrier via SLB |
order.manually_marked_as_new | Order is manually marked as new |
order.manually_marked_as_pending | Order is manually marked as pending |
order.manually_marked_as_accepted | Shipper manually marks order as accepted |
order.manually_marked_as_invoiced | Shipper manually marks order as invoiced by carrier |
order.manually_unmarked_as_invoiced | Shipper manually unmarks order as invoiced by carrier |
order.manually_marked_as_picked_up | Order is manually marked as picked up |
order.manually_marked_as_delivered | Order is manually marked as delivered |
order.rolled_back_manual_status_change | Order status is manually rolled back |
order.removed | Order is removed |
order.restored | Order is restored |
The order payload has only one additional field:
| Field name | Type | Description |
|---|---|---|
order_guid | guid | GUID of the related order |
Samples:
order.created is triggered when order is created.
{
"action": "order.created",
"action_date": "2019-10-31T05:23:15.835+0000",
"order_guid": "cd04ce94-5c35-442d-b9e6-183a900b8848"
}
order.picked_up_bol webhook event is triggered only when pdf_bol_url and online_bol_url become available, which indicates that the pickup inspection synchronization is finished.
{
"action": "order.picked_up_bol",
"order_guid": "d2be393a-c3a0-4680-bbb9-d6fa84aa2d4c",
"action_date": "2021-02-24T09:49:37.051+0000",
"pdf_bol_url": "https://carrier.superdispatch.com/orders/pdf-bol/Kkryz1y8QYpmdeR1q7bde/",
"online_bol_url": "https://bol.superdispatch.com/KRyz1y8QYpmdeqm73WR1q7bde"
}
order.delivered_bol webhook event is triggered only when pdf_bol_url, online_bol_url and pdf_delivery_receipt_url become available, which indicates that the delivery inspection synchronization is finished.
{
"action": "order.delivered_bol",
"order_guid": "d2be393a-c3a0-4680-bbb9-d6fa84aa2d4c",
"action_date": "2021-02-24T09:58:33.544+0000",
"pdf_bol_url": "https://carrier.superdispatch.com/orders/pdf-bol/KRyz1y8QYpmdeqm73WR1q7bde/",
"online_bol_url": "https://bol.superdispatch.com/KRyz1y8QYpmdeqm73WR1q7bde",
"pdf_delivery_receipt_url": "https://carrier.superdispatch.com/orders/Kkryz1y8QYpmdeR1q7bde/delivery-receipt/pdf/"
}
order.submitted_by_customer webhook event is triggered when customer submits order from the customer portal or via shipper-to-broker flow. This event has customer_counterparty_guid that indicates which customer submitted the order:
{
"action": "order.submitted_by_customer",
"order_guid": "d2be393a-c3a0-4680-bbb9-d6fa84aa2d4c",
"action_date": "2021-02-24T09:58:33.544+0000",
"customer_counterparty_guid": "4f797316-63a8-432a-a4ef-2986b8occ89d"
}
Webhooks for order and vehicle revisions
General Info
Webhooks for order and vehicle revisions allow getting notifications when an order or its vehicles are updated. Using these webhook events API users are able to fully synchronize data in their system with Shipper TMS. These events allow subscribing to any subset of field changes. For example, if you are interested only in price changes you can subscribe to the price field changes and get notified only when the order price is changed.
To subscribe order or vehicle changes use the following list of events:
order.created- order is createdorder.modified- order is updatedvehicle.created- vehicle is createdvehicle.modified- vehicle is updatedvehicle.deleted- vehicle is deleted
The payload for subscribing to these events accepts audit_field_set field. This field should contain the list of order or vehicle fields which values will be added to the webhook payload when it's triggered.
The triggered webhook payload has the following shape:
{
"action": "<webhook_action>",
"order_guid": "cd04ce94-5c35-442d-b9e6-183a900b8848",
"vehicle_guid": "rt04cey4-5c35-442d-b9e6-183a900b5672",
"revision_guid": "t50r2ey4-5c35-442d-b9e6-183a43eb5621",
"action_date": "2020-11-24T11:43:37.480+0000",
"user_guid": "42a630e3-a55f-4374-8f1a-bb16d272393d",
"data": "<the payload with data diffs>"
}
The nested data field's shape is similar to the order's (or vehicle's) shape except instead of primitive value leaf fields contain old and new values like "field": { "old_value": <old price value>, "new_value": <new price value>}. For order.created and vehicle.created events old_value is always null. For vehicle.deleted event new_value is always null.
order.modifiedandvehicle.modifiedevents are triggered only when one ofaudit_field_setfields are changed.order.created,vehicle.createdandvehicle.deletedevents are triggered even if theaudit_field_setis empty.
Subscription example for order revisions
Here is the example of how to subscribe to order's number, price, and pickup.venue.name field changes:
curl -X "POST" "https://api.shipper.superdispatch.com/v1/public/webhooks/order.modified/subscribe" \
-H 'Authorization: Bearer <access_token>' \
-H 'Content-Type: application/json; charset=utf-8' \
-d $'{
"callback_url": "<callback_url>",
"audit_field_set": ["number", "price", "pickup.venue.name"]
}'
When these fields are changed the following payload will be sent:
{
"action": "order.modified",
"order_guid": "55dd0a13-7986-4bdf-97f2-9ee1ecc0f99c",
"revision_guid": "ed92b963-161d-40eb-9311-25424acc0a00",
"action_date": "2020-11-24T11:43:37.480+0000",
"user_guid": "42a630e3-a55f-4374-8f1a-bb16d272393d",
"data": {
"number": {
"old_value": "order #123",
"new_value": "#456"
},
"price": {
"old_value": 500.55,
"new_value": 700.99
},
"pickup": {
"venue": {
"name": {
"old_value": "terminal #123",
"new_value": "terminal #456"
}
}
}
}
}
Other fields that also may have been changed with this update aren't included in the payload.
Some order fields could be changed by a carrier. In such cases, the webhook payload will contain the carrier information who made these changes. For example:
{
"action": "order.modified",
"order_guid": "4bb162cb-ce49-4dbb-aba4-2738b925434e",
"revision_guid": "0c79d8b0-ee36-4d56-a71d-c20c99da8268",
"action_date": "2020-11-24T13:52:24.780+0000",
"carrier_phone": "+1234567890",
"carrier_name": "Charon the Ferryman",
"carrier_contact_name": "Charon",
"carrier_guid": "7bec305c-13c1-4c00-a59f-06af456c8c0e",
"carrier_email": "charon@gmail.com",
"data": {
"pickup": {
"scheduled_at_by_carrier": {
"old_value": null,
"new_value": "2020-11-27T15:00:00.000+0000"
}
},
"delivery": {
"scheduled_at_by_carrier": {
"old_value": null,
"new_value": "2020-11-28T15:00:00.000+0000"
},
"notes": {
"old_value": "Meet John",
"new_value": "Met Boris"
}
}
}
}
Subscription example for vehicle revisions
Similarly, to subscribe to vehicle's make, model, and vin fields changes you can use the following command:
curl -X "POST" "https://api.shipper.superdispatch.com/v1/public/webhooks/vehicle.modified/subscribe" \
-H 'Authorization: Bearer <access_token>' \
-H 'Content-Type: application/json; charset=utf-8' \
-d $'{
"callback_url": "<callback_url>",
"audit_field_set": ["vehicles.make", "vehicles.model", "vehicles.vin"]
}'
When these fields are changed the following payload will be sent:
{
"action": "vehicle.modified",
"order_guid": "55dd0a13-7986-4bdf-97f2-9ee1ecc0f99c",
"vehicle_guid": "55dd0a13-7986-4bdf-97f2-9ee1ecc0f99c",
"revision_guid": "ed92b963-161d-40eb-9311-25424acc0a00",
"action_date": "2020-11-24T11:43:37.480+0000",
"user_guid": "42a630e3-a55f-4374-8f1a-bb16d272393d",
"data": {
"make": {
"old_value": "GMC",
"new_value": "Nissan"
},
"model": {
"old_value": "Sierra",
"new_value": "Altima"
},
"vin": {
"old_value": "1G6DC5EY7B0157681",
"new_value": "1N4AL3AP6FC197729"
}
}
}
The full list of order fields to which you can subscribe
numberpurchase_order_numberpricetransport_typeinspection_typebroker_feeorder_instructionsloadboard_instructionsdispatcher_namesales_representativecustomer.namecustomer.business_typecustomer.addresscustomer.citycustomer.statecustomer.zipcustomer.phonecustomer.emailcustomer.contact_namecustomer.contact_titlecustomer.contact_emailcustomer.contact_phonecustomer.contact_mobile_phonepayment.termspayment.methodpayment.notespayment.amountpayment.reference_numbercustomer_payment.termscustomer_payment.methodcustomer_payment.notescustomer_payment.amountcustomer_payment.tariffcustomer_payment.depositcustomer_payment.reference_numberpickup.first_available_pickup_datepickup.date_typepickup.schedule_at_by_customerpickup.schedule_ends_at_by_customerpickup.scheduled_atpickup.schedule_ends_atpickup.schedule_at_by_carrierpickup.adjusted_datepickup.notespickup.venue.namepickup.venue.business_typepickup.venue.addresspickup.venue.citypickup.venue.statepickup.venue.zippickup.venue.contact_namepickup.venue.contact_titlepickup.venue.contact_emailpickup.venue.contact_phonepickup.venue.contact_mobile_phonedelivery.date_typedelivery.schedule_at_by_customerdelivery.schedule_ends_at_by_customerdelivery.scheduled_atdelivery.schedule_ends_atdelivery.schedule_at_by_carrierdelivery.adjusted_datedelivery.notesdelivery.venue.namedelivery.venue.business_typedelivery.venue.addressdelivery.venue.citydelivery.venue.statedelivery.venue.zipdelivery.venue.contact_namedelivery.venue.contact_titledelivery.venue.contact_emaildelivery.venue.contact_phonedelivery.venue.contact_mobile_phone
The full list of vehicle fields to which you can subscribe
vehicles.makevehicles.modelvehicles.typevehicles.yearvehicles.colorvehicles.vinvehicles.pricevehicles.tariffvehicles.lot_number
Offer related actions
| Action | Is sent when... |
|---|---|
offer.sent | Load offer is sent |
offer.sent.failed | Sending a load offer is failed |
offer.accepted | Load offer is accepted by carrier |
offer.accepted.ignored | The carrier accepts the load offer after it was manually marked as picked up or delivered by the shipper |
offer.updated_to_accepted | The carrier has reverted the order status from picked_up to new |
offer.updated_to_accepted.ignored | The carrier has reverted the order status from delivered to new, or from delivered to picked_up to new |
offer.declined | Load offer is declined |
offer.declined.ignored | The carrier declines the load offer after it was manually marked as delivered by the shipper |
offer.canceled | Load offer is canceled by shipper |
offer.canceled_by_carrier | Load offer is canceled by carrier |
offer.canceled_by_carrier.ignored | Load offer is canceled by carrier after it was delivered |
The offer payload has these additional fields:
| Field name | Type | Description |
|---|---|---|
offer_guid | guid | GUID of the load offer |
order_guid | guid | GUID of the related order |
carrier_guid | guid | GUID of the carrier which the load offer was sent to |
status | string | The order status. |
id | bigint | Unique identifier (primary key) of the load offer. This is deprecated. |
order_id | bigint | Unique identifier (primary key) of the related order. This is deprecated. |
Sample payload:
{
"action": "offer.sent",
"action_date": "2019-10-31T05:23:15.835+0000",
"offer_guid": "ca252a6f-dee1-4741-bbe6-4a904fee4a1e",
"order_guid": "cd04ce94-5c35-442d-b9e6-183a900b8848",
"carrier_guid": "ebbfa8f0-38e2-49e4-9c72-0476f6fa878f",
"status": "new"
}
Load Requests related actions
| Action | Is sent when... |
|---|---|
load_request.created | Carrier sends a load request to shipper |
load_request.updated | Carrier updates their own request (e.g. price, pickup or delivery dates, etc.) |
load_request.canceled_by_carrier | Carrier cancels their own request |
load_request.declined_by_shipper | Shipper declines carrier's load request |
The load request payload has these additional fields:
| Field name | Type | Description |
|---|---|---|
order_guid | guid | GUID of the related order |
data.guid | guid | GUID of the load request |
data.requested_price | number | The carrier suggested price |
data.pickup_date | date-time | The carrier suggested pickup date |
data.delivery_date | date-time | The carrier suggested delivery date |
data.carrier_guid | guid | GUID of the carrier who sent the load request |
data.carrier_email | string | Carrier's email |
data.carrier_phone | string | Carrier's phone number |
data.carrier_name | string | Carrier's business name |
data.carrier_contact_name | string | Carrier's contact person's name |
data.carrier_address | string | Carrier's address |
data.carrier_city | string | Carrier's city |
data.carrier_state | string | Carrier's state |
data.carrier_zip | string | Carrier's ZIP |
data.carrier_usdot | string | Carrier's USDOT |
Sample payload:
{
"action": "load_request.created",
"order_guid": "823b7436-40d6-4039-bfe6-c7d90bd8c14d",
"action_date": "2020-01-20T09:33:21.266+0000",
"data": {
"guid": "u789102t-f59k-j893-bfe6-c7d90bd8790f",
"carrier_guid": "9b9fd584-800c-445d-81cb-c951daaeebcf",
"carrier_email": "lyubov@mysuperdispatch.com",
"carrier_phone": "+99890909099",
"carrier_name": "TEST Carrier Inc",
"carrier_contact_name": "Lyubov Korovina",
"carrier_address": "111 Texas Avenue\r\nAustin, TX 48034",
"carrier_city": "Austin",
"carrier_state": "TX",
"carrier_zip": "48034",
"carrier_usdot": "3942812",
"requested_price": "12",
"pickup_date": "2020-11-20T10:33:29.112+0000",
"delivery_date": "2020-11-20T10:33:29.112+0000"
}
}
The payload above is similar for load request actions such as load_request.declined_by_shipper, load_request.canceled_by_carrier, load_request.created or load_request.updated.
Vehicle Location Actions
| Action | Is sent when... |
|---|---|
vehicle.pickup_eta_updated_by_driver | The driver updates the pickup ETA for a vehicle |
vehicle.delivery_eta_updated_by_driver | The driver updates the delivery ETA for a vehicle |
vehicle.driver_location_updated | The driver's GPS location is updated for picked-up vehicles |
vehicle.gps_activated | GPS tracking becomes active for picked-up vehicles |
vehicle.gps_deactivated | GPS tracking is deactivated after going stale |
ETA Updated By Driver
The payload for vehicle.pickup_eta_updated_by_driver and vehicle.delivery_eta_updated_by_driver has these additional fields:
| Field name | Type | Description |
|---|---|---|
order_guid | guid | GUID of the related order |
vehicle_guids | array of guid | GUIDs of the vehicles for which the ETA was updated |
notes | string | null | Optional notes provided by the driver with the ETA update |
date_from | date-time | Start of the ETA time window provided by the driver |
date_until | date-time | End of the ETA time window provided by the driver |
Sample payload:
{
"action": "vehicle.pickup_eta_updated_by_driver",
"action_date": "2026-04-15T14:30:00.000+0000",
"order_guid": "cd04ce94-5c35-442d-b9e6-183a900b8848",
"vehicle_guids": [
"55dd0a13-7986-4bdf-97f2-9ee1ecc0f99c"
],
"notes": "Stuck in traffic, running a bit late",
"date_from": "2026-04-16T09:00:00.000+0000",
"date_until": "2026-04-16T11:00:00.000+0000"
}
Driver Location Updated
This webhook is triggered when the system receives a significant location change from the driver during transport. Location updates are throttled — only sent when the driver has moved a meaningful distance from the last reported position.
The payload for vehicle.driver_location_updated has these additional fields:
| Field name | Type | Description |
|---|---|---|
vehicle_guids | array of guid | GUIDs of the vehicles whose location was updated |
latitude | number | Driver's current latitude |
longitude | number | Driver's current longitude |
address | string | Driver's current address (reverse geocoded) |
Sample payload:
{
"action": "vehicle.driver_location_updated",
"action_date": "2026-04-15T14:30:00.000+0000",
"vehicle_guids": [
"55dd0a13-7986-4bdf-97f2-9ee1ecc0f99c",
"a1b2c3d4-e5f6-7890-abcd-ef1234567890"
],
"latitude": 41.8781,
"longitude": -87.6298,
"address": "Chicago, IL 60601"
}
GPS Status Changed
These webhooks notify you when GPS tracking turns on or off for a vehicle that is in transit, so you can reflect whether live location updates are currently expected.
| Action | Is sent when... |
|---|---|
vehicle.gps_activated | The first GPS location is received for picked-up vehicles, switching GPS tracking on |
vehicle.gps_deactivated | No GPS location has been received for more than one hour, so GPS tracking is switched off |
vehicle.gps_activated is sent only on the transition from inactive to active — it is not sent again for subsequent location updates while tracking remains on. vehicle.gps_deactivated is sent by a scheduled job that deactivates stale GPS status when the last location update is older than one hour.
Events are grouped per shipper, so vehicle_guids contains every vehicle whose GPS status changed together in the same batch.
The payload for vehicle.gps_activated and vehicle.gps_deactivated has these additional fields:
| Field name | Type | Description |
|---|---|---|
vehicle_guids | array of guid | GUIDs of the vehicles whose GPS status changed |
gps_active | boolean | Whether GPS tracking is now active (true for activated, false for deactivated) |
Sample payload:
{
"action": "vehicle.gps_activated",
"action_date": "2026-06-10T14:30:00.000+0000",
"vehicle_guids": [
"55dd0a13-7986-4bdf-97f2-9ee1ecc0f99c"
],
"gps_active": true
}
{
"action": "vehicle.gps_deactivated",
"action_date": "2026-06-10T15:45:00.000+0000",
"vehicle_guids": [
"55dd0a13-7986-4bdf-97f2-9ee1ecc0f99c",
"a1b2c3d4-e5f6-7890-abcd-ef1234567890"
],
"gps_active": false
}
Shipper to broker flow related actions
| Action | Receiver | Is sent when... |
|---|---|---|
| escalation.submitted | Shipper | Broker submits escalation |
| escalation.resolved | Shipper, Broker | Shipper resolves escalation |
| order.cancelled_by_customer | Broker | Shipper cancels order |
Sample payload:
{
"action": "escalation.resolved",
"action_date": "2025-05-12T14:30:00Z",
"order_guid": "123e4567-e89b-12d3-a456-426614174000",
"resolver_guid": "987e6543-e21b-45d3-b456-426614174111",
"escalation_guid": "456e1234-e78b-53d3-a456-426614174222",
"resolve_reasons": {
"CHARGES_DUE": "Charges are due",
"VEHICLE_IS_NOT_AT_LOCATION": "Vehicle is not at location"
}
}