HyperTrackDocs
WebhooksOrdersETA & Delays

Orders At Risk

Webhook payload sent when the risk state of an order changes, how to read the intensity of each risk, and risk_status on GET /orders.

Order at risk Webhook Payload

[
  {
   "created_at":"2021-01-01T14:01:00.000000Z",
   "recorded_at":"2021-01-01T14:00:00.000000Z",
   "device_id":"00112233-4455-6677-8899-AABBCCDDEEFF",
   "worker_handle": "Worker-1",
   "account_id":"6784e919-7168-4f61-b686-2020f547637f",
   "type":"order",
   "data":{
      "value":"risk_updated",
      "order_handle":"DGC127092",
      "route_handle":"4359cc65-90dd-4b2b-875b-26e6d2eba11d",
      "status":"ongoing",
      "share_url":"https://trck.at/vr1RNLq",
      "risks":{
        "deviating_from_expected_route":{
          "intensity_label": "red",
          "intensity_value": 0.85,
          "previous_intensity_label": "yellow"
        },
        "moving_too_slow":{
          "intensity_label": "yellow",
          "intensity_value": 0.45,
          "previous_intensity_label": "green"
        }
      },
      "metadata":{
         "storeId":"123490809808",
         "customerName":"Andrew"
        }
     },
   "version":"3.0.0"
  }
]

The example shows two risk elements to keep it short. A real webhook holds every risk element that we evaluate for the order.

Following are the Risk elements:

  • delayed_from_scheduled_at: risk element that an order is delayed from the scheduled time of delivery.
  • delayed_from_initial_eta : risk element that an order is delayed beyond the initial ETA communicated to the customer
  • is_offline : risk element that an order is at risk because the device is not sending updates.
  • deviating_from_expected_route : risk element that an order will be at risk because the worker is deviating from the expected route.
  • moving_away_from_destination : risk element that an order will be at risk because the worker is moving away from the destination.
  • in_low_battery : risk element that an order is at risk because the device may shut off before order completion.
  • moving_too_slow : risk element that an order will be at risk because the worker is moving too slowly to fulfil the order.
  • in_outage : risk element that an order is at risk because of a user-driven or software-driven action. eg: turn off GPS, background process killed etc.

How to read intensity

Each risk has an intensity_value from 0 to 1 and an intensity_label. Two things go into the value: how strong the signal is (an ETA 20 min past the scheduled time is stronger than 5 min; a device dark for 30 min is stronger than 5 min) and how sure we are about it (a fresh GPS fix and a steady ETA are sure; a stale fix or a jumpy ETA is not). When we are sure, the value is the signal. When we are not sure, the value moves toward the middle (0.5), so a red only appears when the signal is strong and the evidence is good, and a green only appears when the evidence is good too.

intensity_labelintensity_valueMeaning
greenbelow 0.45 (< 0.45)Fine.
yellow0.45 up to, but not including, 0.75 (>= 0.45 and < 0.75)Watch, or we are not sure yet.
red0.75 and above (>= 0.75)Act.

We compare each label with the last risk_updated webhook we sent for the order. We send a new one when a label moves up (the first one when a risk reaches yellow or red), and when a label moves down and its intensity_value changes by more than 0.1. We send at most one per order per minute. Each webhook includes previous_intensity_label, so you can see what moved.

Parameters

NameTypeMandatoryDescription
data.valuestringYesrisk_updated
data.order_handlestringYesUnique handle for the Order
data.route_handlestringYesUnique identifier of the route containing the order
data.statusstringYesStatus of the order - ongoing
data.share_urlstringYesContains tracking url of the order to provide real time visibility of worker on route of this order
data.metadataobjectNoMetadata that you have assigned to this order
data.risksobjectYesOrder at risk state. Holds every risk element we evaluate for the order, not only the ones that changed. Orders on a flexible route, and orders that do not have a route estimate yet, get only is_offline, in_outage, moving_too_slow, and in_low_battery.
data.risks.delayed_from_scheduled_atobjectNoRisk element evaluating if the order is delayed from the scheduled time of delivery. Object with intensity_value, intensity_label (green, yellow, or red), and previous_intensity_label.
data.risks.delayed_from_initial_etaobjectNoRisk element evaluating if the order is delayed beyond the initial ETA communicated to the customer. Object with intensity_value, intensity_label (green, yellow, or red), and previous_intensity_label.
data.risks.is_offlineobjectNoRisk element evaluating the online/offline status of the worker. Object with intensity_value, intensity_label (green, yellow, or red), and previous_intensity_label.
data.risks.deviating_from_expected_routeobjectNoRisk element evaluating the deviation in route taken by the worker against the expected route. Object with intensity_value, intensity_label (green, yellow, or red), and previous_intensity_label.
data.risks.moving_away_from_destinationobjectNoRisk element evaluating the direction of the worker, if the worker is moving away from the destination. Object with intensity_value, intensity_label (green, yellow, or red), and previous_intensity_label.
data.risks.in_low_batteryobjectNoRisk element evaluating the battery status of the worker's device. Object with intensity_value, intensity_label (green, yellow, or red), and previous_intensity_label.
data.risks.moving_too_slowobjectNoRisk element evaluating the speed of the worker. Object with intensity_value, intensity_label (green, yellow, or red), and previous_intensity_label.
data.risks.in_outageobjectNoRisk element evaluating the outage status of the worker. Object with intensity_value, intensity_label (green, yellow, or red), and previous_intensity_label.
data.risks.*.intensity_labelstringYesLabel of the risk element: green (fine), yellow (watch, or not sure yet), or red (act). See How to read intensity.
data.risks.*.intensity_valuenumberYesNumber from 0 to 1. It combines the strength of the signal and how sure we are about it. See How to read intensity.
data.risks.*.previous_intensity_labelstringNoLabel of the risk element in the previous risk_updated webhook for this order. Not present when the element was not in the previous webhook, for example on the first webhook.

risk_status on GET /orders

GET /orders returns risk_status on each order, and accepts risk_status as a query filter. risk_status is a rollup of the risk element labels on this page.

  • Response field: true when at least one risk element of the order has intensity_label yellow or red. false when all risk elements are green, or when the order has no risk elements.
  • Query filter: risk_status=True returns only the orders at risk. risk_status=False returns only the orders that are not at risk. With aggregate=true, only risk_status=True is applied: risk_status=False is ignored and the counts include all orders. The value is case-sensitive: true and false in lowercase are not valid. To get all orders, do not send the parameter.

risk_status does not tell you which risk changed. To see the label of each risk element, use this webhook.