2. Defining shipments

Our service optimizes the routes by assigning shipments (deliveries or pickups) to vehicles considering constraints like territory, time window, capacity and special attributes. Shipments hold the information required to plan the routes:

  1. Location as discussed in Geo-coding addresses
  2. Time windows
  3. Shipment type - delivery or pickup
  4. Load dimensions like pallet places, weight & height, volume, loading meter
  5. Required attributes of a vehicle like tail lift or ADR

You can find a a short description of all the properties in our delivery schema in the API reference, for a quick overview of the more important ones take a look at our Basic API Data Structures page.

The shipment_type sets the type of a shipment as delivery or pickup. We also support directs - freight that is picked up on tour and delivered on tour, so there is no depot loading or unloading. Deliveries that have such a pickup on tour reference those using the pickup_ref_id.

In the most basic case, all you need to create a shipment is a supplierlocation_id for the pickup and the deliverylocation_id for the delivery location. A delivery starts from the depot and has a delivery address. A pickup has a pickup address and is delivered to the depot. If you want to pickup goods 'on tour' you define two addresses that are not the depot.
You also need a time window defined by pdt_to and pdt_from in the ISO datetime format. 'pdt' describes the 'planned delivery time', i.e. the time window in which the goods are expected to arrive at its destination. If you don't provide a time window, we default to the earliest time to leave the depot and the latest time to return to the depot.

curl --request POST \
     --url 'https://<your company name>.prd.smartlane.io/api/delivery' \
     --header 'Content-Type: application/json' \
     --header 'Authorization: JWT your.Long_Randomfghxlcnebem.Secure_AccessToken' \
     --data '{"deliverylocation_id": 2}'
import requests
from datetime import datetime, timedelta

auth_header = {"Authorization": "JWT your.Long_Randomfghxlcnebem.Secure_AccessToken"}
api_url = "https://https://<your company name>.prd.smartlane.io/api"

url = api_url + "/delivery"

data = {"supplierlocation_id": 2,
        "deliverylocation_id": 3,
        "pdt_to": (datetime.now() + timedelta(days=1)).isoformat(),
        "pdt_from": datetime.now().isoformat()}

response = requests.post(url, headers=auth_header, json=data)

Posting this call will return this response:

{
  "adr_needed": false,
  "als_seconds": null,
  "ata": null,
  "atd": null,
  "code": null,
  "creationtime": null,
  "custom_id": "8138bb82-1acd-11ec-85dc-fa3fa3455b94",
  "custom_tour": null,
  "ddt_from": null,
  "ddt_to": null,
  "deliverprio": null,
  "delivery_address": {
    "additional": null,
    "addresstype": null,
    "city": "KIRCHLENGERN",
    "code": null,
    "contactcompany": "Empf\u00e4nger 2",
    "contactfirstname": null,
    "contactlastname": null,
    "country": "DE",
    "customernr": null,
    "default_pdt_from": null,
    "default_pdt_to": null,
    "distances": null,
    "district": "Kirchlengern",
    "email": null,
    "housenumber": "137 - 143",
    "id": 3,
    "location": {
      "coordinates": [
        8.63893,
        52.20686
      ],
      "type": "Point"
    },
    "phonenr": null,
    "postalcode": "32278",
    "search_vector": "'2':2 'empf\u00e4nger':1",
    "street": "luebbecker str."
  },
  "delivery_items": [],
  "deliveryissuename": null,
  "deliverylocation_id": 3,
  "deliverytype_id": null,
  "distances": null,
  "drivernotes": null,
  "effective_loads": null,
  "els_seconds": 300,
  "eta": null,
  "eta_from": null,
  "eta_to": null,
  "final": null,
  "fixed_els_seconds": 300,
  "height": null,
  "id": 67163,
  "length": null,
  "liftgate_needed": false,
  "load": null,
  "load_2": null,
  "load_3": null,
  "load_class_ids": null,
  "load_text": null,
  "notes": null,
  "notify_customer_email": false,
  "notify_customer_sms": false,
  "order_in_tour": 0,
  "orderindex": 67163,
  "overload_ref": null,
  "packets": null,
  "pdt_break_ends": null,
  "pdt_break_starts": null,
  "pdt_from": "2021-09-22T13:17:27.662363+00:00",
  "pdt_to": "2021-09-22T14:17:27.662337+00:00",
  "pickup_id": null,
  "pickup_ref_id": null,
  "possible_vehicles": null,
  "ppt_from": null,
  "ppt_to": null,
  "process_id": null,
  "recipientname": null,
  "recipienttype": null,
  "return_time": null,
  "route_id": null,
  "same_stop_unit": null,
  "scancode": null,
  "shipment_type: null,
  "status": 0,
  "supplier_address": {
    "additional": "",
    "addresstype": "depot",
    "city": "M\u00fcnchen",
    "code": null,
    "contactcompany": "Smartlane GmbH",
    "contactfirstname": "Micha",
    "contactlastname": "Trieba",
    "country": "DE",
    "customernr": null,
    "default_pdt_from": null,
    "default_pdt_to": null,
    "distances": null,
    "district": null,
    "email": "[email protected]",
    "housenumber": "45",
    "id": 1,
    "location": {
      "coordinates": [
        8.74001,
        51.6855
      ],
      "type": "Point"
    },
    "phonenr": "00491634793733",
    "postalcode": "80687",
    "search_vector": "'gmbh':2 'micha':3 'smartlane':1 'trieba':4",
    "street": "Elsenheimerstra\u00dfe 45"
  },
  "supplierlocation_id": 1,
  "tdt_from": null,
  "tdt_to": null,
  "territory": null,
  "tfp": null,
  "tfp_seconds": null,
  "trailer_needed": false,
  "unit": null,
  "update_notes": null,
  "variable_els_seconds_per_load": null,
  "vehicletype_name": null,
  "waiting_time": null,
  "waiting_time_seconds": 0,
  "width": null
}

As you can see, each address can have a default time window for delivery too. This would be a fallback, if you don't provide pdt_from and pdt_to with the shipment data. As mentioned above we default to the settings of the global settings: DEFAULT_DAY_END and DEFAULT_DAY_END if no pdt is specified.

Expected length of stay

We consider the length of a stay for arriving, loading and unloading and leaving the yard for the planning in order to get an accurate planning. It is composed of two values:

  1. The fixed els: The fixed part of the arrival/departure and loading/unloading time (related to the vehicle)
  2. The variable els: The time each shipment will take for loading/unloading (related to the shipments)

So the total els will be calculated as fixed_els + n * variable_els, where n is the number of shipments to load/unload

Again we follow a hierarchy of settings in order to fetch the best value possible:

  1. els definition per shipment (fixed_els_seconds and variable_els_seconds_per_load)
  2. els definition in the config (VARIABLE_ELS_PER_LOAD, MAX_ELS_SECONDS_PER_LOAD, DEFAULT_ELS )

els values are set in seconds.

Time Attributes

We can group the time attributes of a delivery into two categories.

  1. The times that are used as input for the routing algorithm, which need to be known before planning a tour, e.g. the pdt_from, pdt_to and els settings
  2. The times that are calculated by the routing algorithm. These are e.g. the "target delivery time - tdt"or the "expected time of arrival - ETA".

Inputs - planned times

We can also plan with multiple time windows. They can be set by using arrays of pdt_from and pdt_to:

      "pdt_from": ["2020-07-03T10:30:00+00:00",
                  "2020-07-03T12:30:00+00:00"],
      "pdt_to": ["2020-07-03T11:30:00+00:00",
              "2020-07-03T13:30:00+00:00"]

So in this example we have two time windows: The first from "10:30" to "11:30", the second from "12:30" to "13:30".

📘

ISO Time

Make sure that all dates and times are formatted according to the ISO 8601 standard. Be aware that the time zone designator is mandatory, unless you're in UTC±0.

Time spans are often specified in minutes for convenience.

But you may have already noticed that there's many more properties, having _from and _to in their names, and all of them describe time spans, calculated by our algorithm. So let's explain them one by one.

Outputs - calculated times

The first is the target delivery time, abbreviated to tdt_from and tdt_to. It defines the time span, that when met by the driver, allows that the next delivery tdt can also be met. This time span is always within the planned delivery time span.

The next time span estimated time of arrival eta is derived from the target delivery time tdt. It serves some important functionality. First of all, the tdts can be very wide when the planned delivery time windows (pdts) are very large. So it narrows them down to a more definite interval. This is also the time that is communicated to the end customer.

The last of this bunch of time spans is the driver delivery time ddt. It is the time span, that is supposed to be communicated to the driver to tell him at what time it would be best to arrive. It is very similar to the eta, but usually a little earlier.

One more time is missing: the planned pickup time ppt. We fully support pickup and delivery services, but at this point is beyond the scope of this tutorial.

All time related settings overview:

Abbrevation

Name

Description

PDT

planned delivery time

Manual input based on customer wishes.

TDT

target delivery time

Calculated possible time span of delivery, based on pre-defined time constraints and traffic forecasts.

DDT

driver delivery time

Time span of delivery to be communicated to the driver based on TDT.

ETA

estimated time of arrival

Time span of delivery to be communicated to the end customer based on TDT.
Used for customer notification.

PPT

planned pickup time

Manual input based on customer wishes.

ELS

estimated length of stay (seconds)

TFP

driving time from preceding delivery