Order properties

Orders in RouteQ are locations that are visited by one or more vehicles in the optimal sequence meeting the restrictions.

The locations field in the request is used to define orders. The principle of "order = location" is valid in most situations of delivery from the depot. However, for the route planning service location generally is a point where you need to perform a certain action.

The locations field will contain more points than you have orders, if:

Order ID

Each order must have a unique numeric or string ID in the id field. The ID must be unique within a single request. For the export of planning results to Track & Trace, the order ID should be unique within your company.

If the id field is empty, then when you upload the data from Excel and send the task for routing, it's filled in as 1, 2, 3… If id is filled in for the order, we recommend also specifying the depot's id (or avoid 0 in the order's id, since this value is reserved for the depot).

In addition to the order number, you can specify other order attributes from your accounting system:

  • ref: Additional order number. In some cases, the fields are used as follows: id is populated with the internal identifier from the accounting system (unique for the entire sheet), and ref is populated with the document number users know and may not be unique.

  • title: Recipient's name.

  • description: Delivery location description (such as the address).

  • comments: Order comments. The information from this field is uploaded to the fields of the order card in Track & Trace and the Yandex Courier app. In addition to the text description, you can add a link to the comments, and the courier can open it from the app.

Alert

The ref, title, description, and comments fields are solely for informational purposes and aren't used when optimizing routes.

Order coordinates

You can specify the order delivery point in the WGS84 system. The coordinates must correspond to the parking spot or stop point used for the order handover. If the order location in your system is specified by the address, geocode it (convert an address in open format to geographical coordinates).

To determine the coordinates of the order, use the point.lat and point.lon fields. Make sure that latitude and longitude are not swapped and no pairs of coordinates are too different from the others (this usually indicates geocoding errors: routing will find out that such an address is rather distant from the others, and the order can't be included into any routes).

To determine the coordinates of the order, use the location.point field.

Correct coordinates are key for good routing results. The geocoder may inaccurately recognize addresses that are entered with errors or contain information not related to the address. That's why we recommend paying close attention to how addresses are created and stored in your system:

  • If customers enter addresses in a form on your site, we recommend that you enable address validation.

  • If addresses are entered by your company employees, streamline the input process. The address is usually entered as an unstructured string, which includes comments and delivery time window information in the same field. To avoid errors and unrecognized addresses during geocoding, try to at least separate the address from the other data.

Alert

The coordinates 0,0 will not be processed correctly and will result in an error when you send a request to RouteQ.

Order type

The order type is specified in the type field. Possible values:

Order weight

For each order delivered, you can define the weight. It's not mandatory to enter weight, but it's recommended to avoid vehicle overload.

To determine the order weight, use the shipment_size field (you may specify one of the following attributes):

  • shipment_size.weight_kg: Weight in kilograms or bulk weight.

  • shipment_size.volume_cbm: Order volume in cubic meters. If the volume_cbm field is undefined, the order volume is calculated as the product of the dimensions of the order:

    • shipment_size.volume.width_m: Order width in meters.

    • shipment_size.volume.depth_m: Order length in meters.

    • shipment_size.volume.height_m: Order height in meters.

  • shipment_size.units: Number of units (pallets, boxs, kegs).

For more information about determining weight, see Weight and volume.

When specifying the weight of orders, make sure to specify the load capacity of the vehicles.

We recommend that you set the gross weight and volume of the order, especially if the information about the tare weight can significantly affect the routing results. If the information on gross weight isn't explicitly known at planning, we recommend that you calculate it based on the specifics of the goods being transported. Let's say the average weight of a pallet with cargo is 800 kg, the pallet's weight is 20 kg, the net weight in the order is 500 kg, and it's unknown at the time of planning how the cargo will be collected at the depot. In this case, when you pass an order to RouteQ, you can specify: the weight as 500 kg + 20 kg * (500/800)= 512.5 kg, and the number of cargo units as the ratio of the expected gross weight to the average weight of the pallet: 512.5/800 = 0.64 pallets. This is only one of the possible approaches to approximating this calculation.

If an order consists of several different products, each with its own dimensions, you need to specify the final characteristics of the order: total weight, total volume, total number of units. In the order dimensions, you can transfer the maximum dimensions (if this is important for planning).

Learn more

For example, let's say one order consists of three different products, each with its own dimensions and weight:

Item No.

Number of units

Dimensions, m

Weight of each unit, kg

1

50

0.1x0.1x0.1

2

2

10

0.2x0.2x0.2

3

3

1

1x0.5x0.1

50

Final characteristics by order:

  • Total weight: 50 * 2 + 10 * 3 + 50 = 180
  • Total volume: 50*(0.1*0.1*0.1) + 10*(0.2*0.2*0.2) + 1*(1*0.5*0.1) = 0.18.
  • Number of units: 50+10+1 = 61
  • Order dimensions: max(0.1; 0.2; 1)*max(0.1; 0.2; 0.5)*max(0.1; 0.2; 0.1) = 1*0.5*0.2.

Alert

If the weight, volume, or number of units in the order exceed the maximum vehicle capacity, Planning moves the order to unassigned orders, because orders are indivisible for RouteQ (except for cases with specially configured splitting settings, see Splitting orders into parts for more). If there are big orders in your accounting system, split them into several smaller orders when uploading to RouteQ.

Example

A courier in a vehicle with a carrying capacity of 10 cubic meters (capacity.volume.width_m = 2, capacity.volume.depth_m = 2.5, and capacity.volume.height_m = 2) delivers two orders. For the first order, the volume is defined shipment_size.volume_cbm = 5. For the second order, the volume is undefined, which is why it's calculated from the dimensions shipment_size.volume.width_m = 2, shipment_size.volume.depth_m = 2, and shipment_size.volume.height_m = 1. Both orders are placed in the vehicle.

API request (JSON)API responseView on map

Custom units

Besides the specified units of weight, volume (calculated from dimensions), and number of cargo units, in RouteQ you can specify custom measurement units for an order and limit the vehicle carrying capacity using custom measurement units.

You might need this if, besides the units you use (weight, volume, number of cargo units), you need to:

  • Set the order cost and limit the total cost of orders transported by the courier. That's needed to ensure that each courier carries goods in the amount of no more than N monetary units.

  • Limit the number of orders carried by each courier. In this case, you can specify a custom unit of measurement = 1 for each order, and on each vehicle set the limit of this number of orders.

  • Implement any other logic aimed at limiting the number of specific orders per courier. Let's say you have VIP customers that you absolutely can't be late to. For them, you can set a rule that each courier can take no more than 2 VIP orders. This reduces the risk of non-delivery for such orders because of contingencies.

The custom unit of measurement is set by two parameters:

  • shipment_size.custom.<sequential number>.name: Name of the custom unit.

  • shipment_size.custom.<sequential number>.size: Order size in custom units.

By default, shipment_size.custom.<sequential number>.size is 0.

You can set multiple custom units and assign any names to them.

Alert

The name of the custom unit assigned to the vehicle must be the same as for the order.

Example of filling in Excel file sheets for a custom price parameter (order cost):

Order cost

shipment_size.custom.0.name

shipment_size.custom.0.size

price

100

Total order cost

capacity.custom.0.name

capacity.custom.0.size

price

1000

Example 1

This example shows the weight, volume, and number of cargo units. You can also set the order cost and the limit on the total order cost per vehicle using the location.shipment_size.custom.0 and vehicle.capacity.custom.0 parameters, respectively.

You can see that there are 2 vehicles transporting 1 order each. However, their weight, volume and number of units is small, because their order cost is close to the vehicle's limit.

API request (JSON)API responseView on map

Example 2

The same as example 1, but the maximum number of orders that the courier can transport is also specified. The restriction is described using the location.shipment_size.custom.1 and vehicle.capacity.custom.1 parameters. Each vehicle can now carry no more than 5 orders.

You can see that the number of orders in three cars has changed. Now one vehicle carries one order, and orders cannot be added due to the total cost limit. For the rest, maximum utilization by total cost in each vehicle was achieved, and it was possible to maintain the limit on the number of orders.

API request (JSON)API responseView on map

Order dimensions

When you create an order, you might need to account for its dimensions, besides weight and volume. For example, a vehicle with a cargo compartment of 1x1x1 meter can't accommodate a box that is 2x0.5x0.5 meter, even though it has a smaller volume.

If an order consists of several different products, each with its own dimensions, you need to specify the final characteristics of the order: total weight, total volume, total number of units. In the order dimensions, you can transfer the maximum dimensions (if this is important for planning).

Learn more

For example, let's say one order consists of three different products, each with its own dimensions and weight:

Item No.

Number of units

Dimensions, m

Weight of each unit, kg

1

50

0.1x0.1x0.1

2

2

10

0.2x0.2x0.2

3

3

1

1x0.5x0.1

50

Final characteristics by order:

  • Total weight: 50 * 2 + 10 * 3 + 50 = 180
  • Total volume: 50*(0.1*0.1*0.1) + 10*(0.2*0.2*0.2) + 1*(1*0.5*0.1) = 0.18
  • Number of units: 50+10+1 = 61
  • Order dimensions: max(0.1; 0.2; 1)*max(0.1; 0.2; 0.5)*max(0.1; 0.2; 0.1) = 1*0.5*0.2

RouteQ has the location.shipment_size.volume.type parameter to set the type of cargo transported. Possible values:

  • bulk: Loose. When you create an order, you don't need to account for dimensions of this cargo. Used by default.

  • rigid: Rigid. When you create an order, you need to account for the dimensions, but the cargo can be oriented arbitrarily (in other words, any of its sides can face the floor of the vehicle body).

  • fixed_bottom: Fixed-bottom orientation. When assembling an order, you can't turn over the cargo (the height dimension is fixed), but you can rotate it around its vertical axis (the cargo must be oriented with a specific side facing the floor of the vehicle body).

Alert

You can check the order dimensions for each order individually. Multiple orders that fit by volume but not by dimensions can be assigned to a same vehicle. For example, 2 orders with the dimensions 0.6x0.6x0.6 can be placed in a 1x1x1 vehicle body.

Example 1

A vehicle with the cargo compartment dimensions of 1x1x1 meters delivers an order with the dimensions of 2x0.5x0.5 meters. Since the dimensions are not accounted for by default, the order is assigned to the vehicle.

API request (JSON)API responseView on map

Example 2

The same as example 1, but the order is considered rigid and does not fit in the vehicle. As a result, it is not delivered.

API request (JSON)API responseView on map

Order orientation in the vehicle

To determine the orientation of orders with the rigid or fixed_bottom type relative to the axis of the vehicle, the location.shipment_size.volume.align field is used.

The default value is align = all_axes. Orders must be placed strictly parallel to the axis of the vehicle. Sometimes it is more convenient to load the cargo in the vehicle at an angle. To support such a scenario, align = height is used.

The orientation of the order depends on the combination of the type and align values. Possible options are listed below:

align/type

rigid

fixed_bottom

all_axes

The order can be rotated 900 around any axis, but it should always be placed strictly parallel to the axes of the vehicle body.

The order can be rotated 900, provided that its bottom** is always on the floor of the vehicle body.

height

The order may be rotated however you like, provided that any one of its sides is on the floor of the vehicle body. It means that the order height* must be parallel to the height of the cargo compartment.

The order may be rotated however you like, provided that its bottom** is constantly aligned along the floor of the vehicle body.

* shipment_size.volume.height_m: Order height in meters.

** Side defined as width x depth, expressed in the parameters:

  • shipment_size.volume.width_m: Order width in meters.

  • shipment_size.volume.depth_m: Order length in meters.

Example 1

In the planning task, there is an order with the dimensions 0.4x3.2x1 m and a vehicle with a carrying capacity of 2x3x1.5 m. The parameter location.shipment_size.volume.type = fixed_bottom is given, meaning the order cannot be turned over. The orientation location.shipment_size.volume.align is not specified, so the load must be placed parallel to the axis of the vehicle.

As a result, the order does not fit in the vehicle, because the length of the order is longer than the length of the body.

API request (JSON)API responseView on map

Example 2

The same as example 1, but location.shipment_size.volume.align = height, the cargo can be rotated at any angle.

As a result of solving the algorithm, the cargo is placed diagonally in the body and the order will be delivered.

API request (JSON)API responseView on map

Order time window

Every order must have a time window: the time interval when the vehicle or courier must arrive at the order address.

To define a time window, use the field time_window.

The time window can be defined inone of the following formats:

  • 07:00:00–23:00:00: The time window starts at 7:00 and ends at 23:00 on the current day.

  • 2019-10-10T07:00:00+03:00/2019-10-10T23:00:00+03:00: The time window for a specific date and time zone (read as YYYY-MM-DDThh:mm:ss±hh:mm).

Depending on the type of the time window, the courier arrives at the order location strictly at the specified interval (hard window) or may violate the window with an additional penalty (soft window). For more information, see Hard and soft time windows.

To manage hard time windows, use the hard_window field:

  • If true, a hard time window is used.

  • If false, a soft time window is used.

With a soft time window, additional penalties can be set for its violation. This functionality is described in more detail in Penalties for the depot's time window violation.

To limit permissible violations of the main window, you can set a hard time window around a soft one.

In the case of delivery by a specific time, we don't recommend entering a time window with the same upper and lower boundaries, especially if it's a hard time window.

For example, if the order delivery time is exactly 9:00, the algorithm will process the value 9:00:00 - 9:00:00 without errors, but in practice, the driver will arrive for such an order in advance. Therefore, we recommend that you specify a more realistic time window range, for example, 8:30:00–9:00:00. The narrower your order time windows (all other things being equal), the more vehicles you need to complete the orders within your preset time windows. So, make sure that your time window reflects the real possibility of arriving at a given point as much as possible.

Alert

Handling time is not used to determine the fact of meeting the time window. For example, if you specify the 10:00–16:00 window and the handling time is 30 minutes, arrival at the order at 15:59 is considered on time.

Multiple time windows in the order

If necessary, you can enter multiple time windows for a depot in RouteQ. This is useful in the following situations:

  • There's a break in delivery location availability (for example, you must make a delivery from 9:00 to 12:00 or from 15:00 to 18:00).

  • You have a multi-day route and need to make a delivery at the specified time (for example, from 9:00 to 18:00), but on one of the days appointed for delivery.

In the time_windows field, an array of time_window elements is specified. Orders are delivered during one of the available windows. The information about which time window has been used is contained in the used_time_window field of the API response.

You can set a hard external window hard_time_window for each time window.

Alert

Windows set in time_window must not overlap. For example, you can't specify windows between 9:00–12:00 and 11:00–14:00 at the same time.

Example 1

There are two orders to deliver with two time windows: time_windows.0.time_window is 9:00–12:00 and time_windows.1.time_window is 15:00–18:00 (description format for Excel). Orders are delivered within the first time window.

API request (JSON)API responseView on map

Example 2

There are 20 orders to deliver in two days between 8:00 and 15:00. Order windows are specified in relative format: for the first day — 08:00:00–15:00:00, for the second day — 1.08:00:00–1.15:00:00. Note that in this case, the depot time window is also written in relative format and includes both dates. Vehicle work shifts need to be specified for each day.

API request (JSON)API responseView on map

Handover time

When planning your routes, you can specify the handover time for each order.

The following parameters are available (set in seconds):

  • service_duration_s: Time to hand over an order to the recipient.

  • shared_service_duration_s: Time for exchanging documents or parking.

If multiple orders are delivered to the same address, they can be combined into a multi-order. The handling time for them is calculated as Total{service_duration_s} + Maximum{shared_service_duration_s} for all orders in a multi-order. To exclude an order from a multi-order and take into account its handling time shared_service_duration_s separately, disable the option location.can_be_merged = false. For more information, see Multi-orders.

For some scenarios, additional parameters are taken into account when calculating handover time. They are described in the section Possible logistics scenarios (for example, the time to reload orders for cross-docking). Additionally, when calculating the handover time, time adjustment can be set.

By default, the handover time is not included in the order time window. There may be a situation when a courier arrives at a point at 17:59, even though the order window ends at 18:00. To avoid such cases, use the options.penalize_late_service option. This option determines whether the lateness penalty applies before the handover time starts (false, the default value) or ends (true). It means that if true, the algorithm tries to complete the handling time within the time window.

In the source data, specify a realistic handover time. If too much time is provided for, the algorithm will schedule more couriers than is actually required. If too little time is provided, then the solution will be too optimistic, and there will be delays in order deliveries.

Alert

With a large number of orders, even a small time difference per order can eventually lead to a difference in the number of couriers. For example, for 200 orders, a difference in handover time of 2 minutes is almost a full day of work for a courier: 200 x 2 min = 400 min = nearly 7 hours.

Make sure that you use the average time in the calculations. For example, a courier spends 10 minutes on 9 out of 10 orders, and 30 minutes on 1 order. The average handover time is: (9 * 10 min + 1 * 30 min) / 10 = 12 min.

To select the value of the handover time:

  • Calculate the value:

    <Average shift length> − <Average actual number of points per shift> * <Average handover time>
    

    As a result, there should be a reasonable amount of time left for the courier to move between points.

  • Create a list of different handover times if they change based on the delivery addresses. For example, if you need different times to receive an order in stores of the same retail chain. The list is created outside of RouteQ.

  • Implement a formula for calculating handover time if the volume and weight characteristics of orders vary greatly. For example, 1 minute for every 100 kg, but no less than 5 minutes. The values must be explicitly specified, so the formula must be implemented outside of RouteQ.

To check the handover time, make a real trip along the routes and use the courier performance report in Track & Trace.

Example

The example defines the handover time for each order.

API request (JSON)API responseView on map

Order loading or unloading time at the depot

In addition to the total handling time at the depot, in Route Q you can specify the time needed to load a specific order into a vehicle or unload a pickup order at the depot. To determine the time needed to load or unload an order, use the location.depot_duration_s request field.

If the depot has a single common handling time, it's added to the total order loading time for each vehicle. For more information, see Handling time at depot.

When using cross-docking, the order reloading time is taken into account as location.crossdock_service_duration_s. For planning examples, see Cross-docking.

Example

The depot handling time for each of the three orders is 5 minutes, and the total depot handling time is 10 minutes. In total, the vehicle will need 25 minutes to load.

API request (JSON)API responseView on map

Time when the order is ready at the depot

By default, when planning for delivery of orders from the depot, it's assumed that the orders are ready for shipment. However, that's not totally true (for example, if orders are prepared during a day). In such cases, account for the time needed to prepare orders. Often couriers make several runs from the depot, picking up orders as they become available (for this model, enable multiple runs per courier).

The order ready time is defined in the depot_ready_time field on the Orders sheet. Use it only for the orders with the delivery type with no related pickup orders (meaning only for deliveries from the depot). The depot_ready_time parameter sets a hard restriction — if it's violated, the order goes to unassigned. To set a soft restriction, use the soft_depot_ready_time parameter (only supported in the API). The following penalties are imposed if the soft restriction is violated:

  • penalty.depot_ready_time.fixed: For the violation of the order ready time.
  • penalty.depot_ready_time.minute: For every minute of violating the order ready time.

Specify the date and time in depot_ready_time and soft_depot_ready_time in the same format as when setting time windows.

Sample values:

  • 10:15

  • 2020-09-06T13:15:00+03:00 (September 6, 2020 at 13:15 GMT+3)

  • 2020-09-06T10:15:00Z (September 6, 2020 at 10:15 UTC)

If the depot_ready_time is in the past during route planning (for example, when the order is ready to be sent for delivery the night before), the depot_ready_time value in the API response will be negative.

Example of calculating a negative depot_ready_time value

Routes are planned for March 19. For one of the orders, depot_ready_time = 2024-03-18T20:15:00+03:00. The API response for this order will have depot_ready_time = -03:45.

If the courier should start loading as soon as orders get ready, use the Loading when ready option.

Example 1

In the example, there are 10 orders to be delivered, and each has its own ready time (9:00, 10:00, 12:00, or 14:00). As a result, runs in the courier routes are built using depot_ready_time.

API request (JSON)API responseView on map

Example 2

The same as in example 1 but with smaller time windows specified for orders. Every order has a soft restriction (soft_depot_ready_time = 9:00, 10:00, 12:00, 14:00, or 15:00) and a penalty for every minute of violating this restriction (penalty.depot_ready_time.minute = 10).

As a result of planning, the algorithm violates the order ready time of 10 to ensure that the order is delivered on time.

API request (JSON)API responseView on map

Deadline for picking up an order from the depot

Generally, you can pick up orders from the depot at any time within the depot's time windows. If an order has to be picked up before a certain time, use the depot_expiring_time parameter on the Orders sheet. The depot_expiring_time parameter sets a hard restriction — if it's violated, the order goes to unassigned. To set a soft restriction, use the soft_depot_expiring_time parameter (only supported in the API). When you define soft restrictions, the following penalties apply:

  • penalty.depot_expiring_time.fixed: For the violation of the order pickup deadline.
  • penalty.depot_expiring_time.minute: For every minute of violating the order pickup deadline.

Specify the date and time in depot_expiring_time and soft_depot_expiring_time in the same format as when setting time windows.

Sample values:

  • 10:15

  • 2020-09-06T13:15:00+03:00 (September 6, 2020 at 13:15 GMT+3)

  • 2020-09-06T10:15:00Z (September 6, 2020 at 10:15 UTC)

After the order has been picked up, it may take some time for it to be loaded into the vehicle: depot_duration_s. The total handling time at the depot depot.load_service_duration_s is also added.

Example 1

In the example, there 4 orders to be delivered. Orders 1 and 2 are fragile, so they need to be packed a specific way. Before loading the order, the packaging is checked by an employee whose shift ends at 13:00. Orders 3 and 4 are only ready for shipment at 14:00. As a result, runs in the courier routes are built using depot_expiring_time and depot_ready_time.

API request (JSON)API responseView on map

Example 2

You need to deliver 10 perishable orders. Each order has a soft restriction for the depot pickup deadline: 8:30, 9:00, 9:30, and 10:00. The courier starts work at 9:00, so they can't pick up the order on time. A penalty is imposed for violating the restriction.

API request (JSON)API responseView on map

Pickup and delivery

In general, orders are loaded onto vehicles at the depot and delivered to the recipient addresses.

If an order needs to be picked up at the customer's address and then delivered to another address (pickup & delivery), define the order type.

To do this, use the location.type field with the following values:

  • pickup: Picking up an order at a certain address.

  • delivery: Delivering an order to a certain address (default).

Orders with the pickup type can be delivered:

  • At the specified address: Specify the ID of the order with the delivery type in the location.delivery_to field.

  • At one of the specified addresses: List the order IDs with the drop_off type in the location.delivery_to_any field. See Delivery to one of multiple locations.

  • To one of the specified depots: List the depot IDs in the location.depot_id field. See Assigning an order to a depot. The order will be delivered in the current route.

  • To any depot: In this case, leave the location.depot_id field blank. The order will be delivered to the depot in the current route if at least one of the following conditions is met:

    • location.pickup_must_reach_depot is true. See Pickup order delivery to the depot.
    • The delivery deadline location.delivery_deadline is set. See Time of order delivery to the depot.
    • The courier with the pickup order must return to the depot at the end of the route (vehicle.return_to_depot = true). If none of the above conditions are met, the courier keeps the pickup order and delivers it to the depot in the next route.

If a delivery can be made to one of multiple locations, you can find out exactly where the order was delivered from the API response. For a drop_off order or depot, the IDs of delivered orders are listed in the delivered_orders field.

Example

The first courier must return to the depot at the end of the shift. For them, vehicle.return_to_depot = true. This courier takes all pickup orders. The second courier with vehicle.return_to_depot = false works with remote orders and completes the shift at a point that's convenient for them.

API request (JSON)API responseView on map

Alert

If pickup orders must always return to the depot, and the vehicles with vehicle.return_to_depot = false and vehicle.return_to_depot = true are used in planning, you need to explicitly fill out the location.delivery_to field. Otherwise, the order may remain in the courier's vehicle.

To take into account the order of reception and delivery, use the location.in_lifo_order parameter.

RouteQ also supports mixed pickup and delivery. In this case, both regular delivery orders and pickup/delivery orders are present in the request.

There may be other locations between the order pickup and its delivery to another address if the vehicle's load capacity is sufficient and if this route is more profitable.

If you need to deliver the order immediately after pickup, use order grouping with options.location_groups.solid option set to true.

Please note that if there are multiple orders for pickup cargo at the same address, in rare cases, the pickup can be performed by more than one vehicle or courier. This might be justified in terms of reducing the total cost of delivery.

Returning the container

If a courier needs to grab a pickup order in a container at one location, deliver it to an address, and then return the container to the initial or another location, you can use the "pickup-delivery-return" scheme. To do this:

  1. Add an order with the type pickup and use the field location.delivery_to to specify the ID of the order with the delivery — where the order needs to be delivered in a container.
  2. Add an order with the type return — the address of the location where you need to return the container after delivery.
  3. For the order with the type delivery, in the field location.return_to specify the ID of the order with the return type — the location where the container will be returned.

Example

The courier's route comprises 7 orders. Order 1 with the pickup type is packed in a container. As a result of planning, the courier delivers order 1 to location 3, then returns the container to the initial location. This doesn't affect the delivery of other orders.

API request (JSON)API responseView on map

Order of reception and delivery

Use the location.in_lifo_order parameter to create routes based on the order of receiving and delivering cargo. The abbreviation "lifo" stands for "last in, first out". This parameter can be used for pickup/delivery order pairs when the sequence of loading and unloading is important. By default, location.in_lifo_order = false.

For example, one vehicle transports a chair, armchair, and bed from three addresses to three other addresses. If you load and unload furniture in the same order, to unload a chair, you need to unload the bed first, then the armchair, and finally the chair. Then you have to load the armchair and bed back into the vehicle to go to the next address. Obviously, additional loading and unloading cycles require more time and effort. To avoid unnecessary costs, plan the loading and unloading queue in advance:

  1. Load the bed.
  2. Load the armchair.
  3. Load the chair.
  4. Unload the chair.
  5. Unload the armchair.
  6. Unload the bed.

This procedure follows the "last in, first out" principle. To comply with it, specify location.in_lifo_order = true for all orders where the sequence of reception and delivery is important.

Alert

In pickup/delivery order pairs, the location.in_lifo_order field value should be the same.

Example 1

This example has 6 delivery points. You need to transport an order from point 1 to point 4, from 2 to 5, and from 3 to 6. The sequence is not important, so the route connects the points sequentially: 1 → 2 → 3 → 4 → 5 → 6.

API request (JSON)API responseView on map

Example 2

The same as example 1, but location.in_lifo_order = true is specified for all points, so the route connects the points according to the "lifo" principle: 1 → 2 → 3 → 6 → 5 → 4.

API request (JSON)API responseView on map

Delivery to one of multiple locations

Sometimes, you need to deliver an order to any one of several addresses. For example, if you need to deliver an order to any third-party logistics company's terminal and include a preferred delivery address in the route.

In this case, the pickup order type is used. To learn more about it, see Pickup and delivery. The delivery_to_any field contains a comma-separated list of order IDs with the drop_off type or depots you can deliver the cargo to. You don't need to specify weight and volume for drop_off orders. You can find out exactly where the order was delivered from the API response. For a drop_off order or depot, the IDs of delivered orders are listed in the delivered_orders field.

Note

You can specify delivery_to_any for pickup orders only.

You can only specify depot IDs in the delivery_to_any field when planning via the API.

You can specify handling time for drop_off orders. For a pickup order, if you need to set a specific loading time in drop_off, use the pickup order's depot_duration_s field.

As a result of route optimization, you can deliver multiple pickup orders to one drop_off.

Example 1

In the example below, there are 2 pickup orders and 2 drop_off orders. For each pickup, both drop_off orders are listed in the delivery_to_any field.

Please note that the drop_off orders' handling time is 3 minutes. At the same time, the depot_duration_s value for one of the pickup orders is 30 minutes. The total unloading time in the drop_off orders is 33 minutes.

API request (JSON)API responseView on map

Example 2

In the example below, there are 3 pickup orders, 1 drop_off order, and 2 depots. Orders pickup_1 and pickup_2 can be taken to any depot, while pickup_3 can only be taken to the drop_off order. As a result of planning, the courier delivers pickup_3 to drop_off, and pickup_1 and pickup_2 to Depot 1.

API request (JSON)API responseView on map

Receiving cargo at one of the possible locations

Sometimes cargo for delivery can be picked up from any number of points. For example, if the product that needs to be delivered is available at several depots. In this case, the pickup_from_any property is used for the delivery order.

Multiple pickup orders must be linked with the delivery order in which pickup_from_any is set to true. The link is set in the pickup order, in the delivery_to field. When planning a route, any of these pickup orders can be selected, and others are ignored. The choice of a pickup order is based on the optimal route cost.

Please note that all pickup orders and the linked delivery order must be the same weight.

By default, the pickup_from_any parameter is false.

Example

In this example, there are 2 delivery orders with pickup_from_any set to true. 2 pickup orders are associated with each of these orders.

API request (JSON)API responseView on map

Assigning an order to a depot

Assign the order to a depot if:

  • The delivery order type is only available in certain depots.
  • You need to deliver a pickup order to one of the specified depots.

To do this, specify one or more depot ids where the order is available in the depot_id field. If the order is available in any depot, leave it empty. The same applies to orders with the pickup type.

Assigning orders to a depot is not required in the following cases:

To see which depot is selected for receiving or delivering cargo, you can check the route parameters in the API response:

  • The IDs of the orders delivered to the depot are specified in the delivered_orders field for this depot.
  • The IDs of the orders received at the depot are specified in the picked_orders field for this depot.

Example

Three depots, three orders, and three vehicles are given. Each vehicle starts from its own depot. Orders are assigned to depots using location.depot_id:

  • Order 1 is not assigned to a depot. It can be delivered from any depot.

  • Order 2 is assigned to depots 1 and 2. This order can be delivered from one of the two specified depots.

  • Order 3 is assigned to depot 3. It is located in a specific depot.

As a result, the algorithm built two routes:

  1. One courier delivers orders 1 and 2 from depot 2.
  2. Another courier delivers order 3 from depot 3.

API request (JSON)API responseView on map

Pickup order delivery to the depot

If a pickup order needs to be brought to the depot, it can be delivered both in the current route (if the courier returns to the depot at the end of the working day) and at the start of the next route (when the courier heads off from the depot in the morning). For more information, see Cargo collection to the depot.

If an order is to be delivered to the depot in the current route, set pickup_must_reach_depot = true (it's set to false by default).

Please note the following restrictions for the pickup_must_reach_depot field:

  • pickup_must_reach_depot can only be set to true for pickup orders.
  • pickup_must_reach_depot can only be set to false if the depot_id field is blank, meaning the order can be delivered to any depot.

If one or more depots is given in the depot_id field, the pickup order will be delivered to one of these depots in the current route, regardless of the pickup_must_reach_depot value.

If the task contains pickup orders to be delivered to the depot (location.pickup_must_reach_depot = true), but there are no couriers visiting depots (couriers who head off from the depot, return to the depot at the end of the route, or stop at the depot in the middle of the route), the planning task can't be solved, and you'll see an error message.

Example 1

The courier delivers 15 orders, including 3 pickup orders, which must be delivered to the depot. The courier starts the route at the depot but doesn't have to return to the depot at the end of the day (return_to_depot = false). So, they take pickup orders and keep them to deliver these orders to the depot the next morning.

API request (JSON)API responseView on map

Example 2

The same as in example 1, but pickup_must_reach_depot = true for pickup orders. So, at the end of the route, the courier brings these orders to the depot.

API request (JSON)API responseView on map

Time of order delivery to the depot

In some cases, pickup orders need to be collected at the depot by a particular time. This might be relevant for the courier and logistic companies that send orders by other means of transportation (for example, to the airport or by truck to another city). It means that to meet certain shared delivery timeframes, all orders might have to be picked up before a certain time, otherwise they will all be sent the next day.

To determine the time when the pickup order is delivered to the depot, use the delivery_deadline parameter. The option sets soft restrictions: a penalty.delivery_deadline.fixed or penalty.delivery_deadline.fixed penalty is applied in the event of a violation. The parameter changes the behavior only for orders with the pickup type. To learn more about working with such orders, see Pickup and delivery.

Alert

By default, a courier makes only one run per day, returning to the depot to deliver goods there at the end of the run. To let a courier return to the depot and continue delivery, specify the parameter max_runs with a value greater than 1. For more information about setting up the number of runs, see Multiple vehicle runs per day.

Example

In the example below, one courier delivers all orders and gets back to the depot in the middle of the day to return the order before the specified delivery_deadline.

API request (JSON)API responseView on map

Limitation of the time the order can be in the vehicle

When planning routes, it may be necessary to limit the time an order is in the vehicle (for example, when delivering frozen food or medical tests). To do this, use the location.transit_time object, which consists of two fields:

  • limit_s: A soft restriction, in seconds.
  • hard_limit_s: A hard restriction, in seconds.

You can set one time restrictions or both at the same time for an order.

If a soft restriction limit_s is set, at least one of the following penalties must be specified for it:

  • location.penalty.transit_time.fixed: A fixed penalty for exceeding the time when an order can be in a vehicle.
  • location.penalty.transit_time.minute: A penalty for each minute over the limit.

There aren't any default values for penalties.

If a hard limit hard_limit_s is set, the order will be excluded from all routes if one of the following conditions is met:

  • An order can't be executed without a violation.
  • Delivering the order is more expensive than the penalty for not delivering it.

The restriction covers the following scenarios:

Note

The restriction can't be used in scenarios with anchor locations and cross-docking.

Example

In the example below, 8 orders are set with the values transit_time.limit_s = 3600 and transit_time.hard_limit_s = 5600. As a result, 2 orders violate the soft time restriction that specifies the time the order can be in a vehicle. Another order can't be delivered without violating the hard restriction, so it is unassigned.

API request (JSON)API responseView on map

Multi-orders

When you plan routes, there might be cases when multiple orders need to be delivered to the same address, such as to the same apartment building or business center. These orders can automatically be combined into one or more multi-orders.

The proximity of the combined orders is determined by the options.multiorder_radius_m parameter (the default is 1 m). See Multi-orders for more information. When creating multi-orders, coordinates, order time windows, and connections between orders (the grouping and pickup&delivery pairs) are all taken into account.

Combining orders into a multi-order occurs only if it improves the solution metrics and if other restrictions aren't violated: the carrying capacity of a vehicle or a courier and order compatibility by tags. You can prohibit combining an order with other orders by setting location.can_be_merged = false (this parameter is set to true by default).

Note

If you want to make sure that all orders located at the same address are combined into one multi-order, set the options options.merge_multiorders = true and options.force_merge_multiorders = true. In some cases, this requirement may worsen the planning results. We recommend using these options only if the orders delivered to the same address are significantly smaller than a vehicle's capacity and you are sure that they can be delivered by one vehicle (subject to other restrictions).

When combining orders, the time for delivering documents or parking is counted once for the group by default if they're delivered as a multi-order.

If a customer has several orders in one multi-order, the handover time may be shared.

The following parameters are used to determine the handover time for a multi-order:

  • location.shared_service_duration_s: Time for handing over documents or parking. To calculate it, the maximum value is taken for all orders combined into the multi-order.

  • location.service_duration_s: Time for handing over orders.

  • location.client_service_duration_s: Handover time for one client in a multi-order. To calculate it, the maximum value of this parameter is taken for all orders for one client. The location.client_id parameter is used to identify the client. The algorithm combines orders with the same client_id in one multi-order as long as it doesn't worsen the solution. For example, combining two orders with different time windows and the same client_id may worsen the solution.

For regular orders located at different addresses, the location.shared_service_duration_s parking time and the location.client_service_duration_s client handling time are counted separately for each one.

For multi-orders, the location.shared_service_duration_s parking time is only counted once. The location.client_service_duration_s client handling time for orders with the same client_id is the maximum value for orders in the multi-order. For orders with different client_id, the values are totaled.

For orders with can_be_merged = false, the shared_service_duration_s time for document handover or parking is accounted for separately. To take this time into account separately for each order in a multi-order, disable the waiting option (options.wait_in_multiorders = false). For more information, see Routing options.

Example 1

In the example, 3 orders with the same time windows and different handover times are set. The option to combine multi-orders is activated.

API request (JSON)API responseView on map

Example 2

In the example, there are 4 orders combined into one multi-order. Orders 1 and 3 belong to the first customer, while orders 2 and 4 belong to the second one. The multi-order processing time (total_service_duration_s parameter in the API response) consists of the following values:

  • shared_service_duration_s: 100 seconds, the total time for all orders.
  • service_duration_s: 600 seconds, handover time for all orders.
  • client_service_duration_s for the first customer: 300 seconds (the maximum value for orders 1 and 3).
  • client_service_duration_s for the second client: 400 seconds (the maximum value for orders 2 and 4).

As a result, the processing time of the multi-order is 100 + 4*600 + 300 + 400 = 3200 seconds.

API request (JSON)API responseView on map

Example 3

The same as in example 2, but can_be_merged = false for order 1. Then for order 1, the handling time is 100 + 600 + 100 = 800 seconds, and for a multi-order which combines orders 2, 3, and 4, the handling time is 100 + 3*600 + 300 + 400 = 2600 seconds. The total handling time total_service_duration_s is 3400 seconds.

API request (JSON)API responseView on map

Splitting orders into parts

When you plan routes, there might be cases when an order needs to be divided into several parts, which are then transported by different vehicles. This can be bulk (loose) cargo or cargo on pallets.

To split an order into parts, specify the following parameters in the locations object:

  • can_be_split: The order can be split into parts (only for delivery and pickup orders). The default is false.

  • max_split_parts: The maximum number of parts the order can be split into. The default value is 10.

  • quant: The minimum size of a single part, which is set with these formats:

    • "quant": 0.25: Corresponds to the specified order proportion. In this example, the smallest part is equal to a quarter of the order.
    • "quant": {"weight_kg": 2.5}: Sets the size of the minimum part in weight_kg, units, or volume_cbm. In this example, the minimum part is 2.5 kg.

When a leftover part remains after splitting, it may be smaller than the quant.

To split remove the part that fills the entire vehicle in the current run from the order, use locations.split_parts_must_fill_whole_vehicle = true (the default is false). This may also result in a leftover part.

You can transport several leftover parts from different orders in one run.

Note

If split_parts_must_fill_whole_vehicle = true, you cannot specify the minimum size of a split part (quant).

When working with a resulting solution or on the map, you can check which orders were split: the split orders have the order's part number in the Order number field. The split_orders_percentage metric shows the percentage of split orders.

Alert

For solutions with split orders, manual adjustments in the routing workspace are unavailable.

You can limit the time between the arrivals of different parts of the order. To do this, specify the maximum allowed time in seconds for the locations.max_time_between_visits_s parameter. This parameter sets a soft restriction with the following penalties:

  • locations.penalty.time_between_visits.fixed: Fixed penalty for exceeding the established limit.
  • locations.penalty.time_between_visits.minute: A penalty for each minute over the limit.

To limit the maximum percentage of orders that can be split, use the options.max_split_orders_percentage parameter. It sets a soft restriction with the following penalties:

  • options.penalty.split_orders_percentage.fixed: Fixed penalty for exceeding the established limit.
  • options.penalty.split_orders_percentage.per_percent: Penalty for each percentage above the established limit.

Example 1

You need to deliver 6 orders 1000 kg each using 4 vehicles with a carrying capacity of 1500 kg. You can divide orders in half and deliver them in parts, but this can only apply to 50% of all the orders. A fixed penalty is applied for violating the restriction. As a result of planning, 2 orders are split in half and delivered on different vehicles. Penalty: max_split_orders_percentage_penalty = 0.

API request (JSON)API responseView on map

Example 2

You need to deliver 1 order with a volume of 50 cubic meters from the depot to a construction site. There are 3 vehicles whose carrying capacities are 5, 7.5, and 10 cubic meters, so the order will have to be delivered in parts. The minimum size of each part is 5 cubic meters. Each vehicle can make 3 runs. As a result of planning, the order will be split into 7 parts.

API request (JSON)API responseView on map

Example 3

You need to deliver an order of 20 pallets from the depot to a store. You have 1 vehicle with a carrying capacity of 19 pallets, and it can only make one run. As a result of planning, part of the order (19 pallets) was delivered, while 1 pallet was unassigned.

API request (JSON)API responseView on map

Example 4

You need to deliver 2 orders weighing 1500 kg and 2200 kg using a vehicle with a load capacity of 1000 kg. The parameter split_parts_must_fill_whole_vehicle is true, so the orders are split into 1000 kg parts with a remainder. As a result of planning, the remainder from the orders will be delivered as part of one run.

API request (JSON)API responseView on map

Penalty for non-delivery of an order part

When an order is split into parts, one or several parts may remain unassigned. To have the non-delivery penalty (penalty.drop) calculated based on the size of the order part that remains undelivered, you can set fixed and scaled parts of the penalty: penalty.drop.fixed and penalty.drop.scaled.

The penalty is calculated using the following formula: penalty.drop.fixed + order_ratio * penalty.drop.scaled, where order_ratio is the part (percentage) of the order that was not delivered.

You can specify only a fixed or scaled part of the penalty, not both at the same time.

Example

You need to deliver an order weighing 2000 kg. The order can be split into 250 kg parts. You have 1 vehicle with a carrying capacity of 1500 kg, and it can perform 1 run only. The penalty for non-delivery of an order part is made up of a fixed part of 1,000,000 units and a scaled part of 200,000 units.

As a result of planning, a part of the order equal to 500 kg (1/4 of the order) is not delivered. Penalty: 1,000,000 + (200,000 * 0.25) = 1,050,000 units.

API request (JSON)API responseView on map

Handling time for split orders

You can set the handling time for split orders in one of the following ways:

  • As a fixed time for each part of the order regardless of its size.
  • Depending on the size (percentage) of the delivered part of the order. In this case, the service_duration_s, shared_service_duration_s, client_service_duration_s, depot_duration_s, and crossdock_service_duration_s parameters are set as structures with the fixed and scaled fields.

Note

The parking_service_duration_s parameter cannot be set as a structure with the fixed and scaled fields and is always set as a fixed number.

The parameters for calculating the handling time for split orders can be combined into the service_durations structure with the following elements:

  • location: Corresponds to the service_duration_s parameter.
  • stop: Corresponds to the shared_service_duration_s parameter.
  • client: Corresponds to the client_service_duration_s parameter.
  • depot: Corresponds to the depot_duration_s parameter.
  • crossdock: Corresponds to the crossdock_service_duration_s parameter.
  • parking: Corresponds to the parking_service_duration_s parameter.

Each of these elements (except parking) can be set either as a number or as a structure with the fixed field. They can also be set with the scaled fields, in which case the handling time is calculated using the following formula: fixed + order_ratio * scaled, where order_ratio is the delivered part (percentage) of the order.

Note

When you use the service_durations structure, the respective service_duration_s, shared_service_duration_s, client_service_duration_s, depot_duration_s, crossdock_service_duration_s, and parking_service_duration_s parameters cannot be separately specified for the order.

In the API response, the contents of the service_durations structure remain unchanged: the fields that were set as fixed and scaled parts are output as structures, and those that were set as a number are output as a number.

If the handling times are set without the service_durations structure, then the crossdock_service_duration_s and depot_duration_s parameters in the API response remain the same as in the request. The remaining parameters are output as a number corresponding to the actual handling time for this order in the resulting solution. The final value may also be affected by other parameters, such as combining into a multi-order or multiplier (service_duration_multiplier).

Example 1

A vehicle with a carrying capacity of 600 kg has to deliver an order weighing 2100 kg. The order can be split into parts weighing no less than 300 kg. As a result, the vehicle makes 4 runs: three runs with the cargo weighing 600 kg (2/7 of the order) and one run with the cargo weighing 300 kg (1/7 of the order).

The following parameters are set for the order:

  • Order handling time (service_duration_s), with a fixed part of 600 seconds and a scaled part of 70 seconds (10 seconds for every 300 kg).
  • Loading time at the depot (depot_duration_s), also with a fixed part of 300 seconds and a scaled part of 140 seconds (20 seconds for every 300 kg).

The total handling time is (600 + 20 + 300 + 40) * 3 + (600 + 10 + 300 + 20) = 3810 seconds.

API request (JSON)API responseView on map

Example 2

The same as example 1, but the handling time is set as the service_durations structure.

API request (JSON)API responseView on map

Penalties for order time window violation

This penalty is added to the total cost of the route if the order is planned for delivery, but the delivery occurs earlier or later than the specified time window.

Note

This is only possible if you set a soft time window. If a hard time window is violated, the order is automatically marked as undelivered and excluded from all routes.

A penalty for late delivery makes it more likely that the most important orders are delivered on time, at the expense of less important orders.

To control the timeliness of deliveries, you can use the following objects in RouteQ:

  • location.penalty.early: Sets a penalty for delivery earlier than the time window.

  • location.penalty.late: Sets a penalty for delivery later than the time window.

  • location.penalty.out_of_time: Sets same penalties for delivery both earlier and later than the time window.

If location.penalty.early and location.penalty.late are not set, the values of location.penalty.out_of_time are used (that is, early and late override the out_of_time parameter).

Each object consists of two fields:

  • fixed: A fixed penalty for one-time late delivery.

  • minute: A penalty for each minute of late delivery.

If only one value (fixed or minute) is set for location.penalty.early or location.penalty.late then the second is taken from location.penalty.out_of_time. For example, only location.penalty.late.fixed can be set. In this case, location.penalty.out_of_time.minute will be used as a per-minute penalty for lateness.

Note

The above fields have default values. We recommend using them as the starting values for defining custom priorities for order delivery. When in doubt, contact RouteQ analysts to determine the correct coefficients.

Example

The example below contains a request with different penalties for early and late order delivery. Please note that for all orders location.hard_window = false.

API request (JSON)API responseView on map

Penalties for not delivering an order

For each order in the request to RouteQ, you can define a penalty for non-delivery. If there are not enough vehicles or couriers, individual orders may be excluded from all the routes.

For example, if an order located far from the other orders causes the other orders to be delivered late by several hours, this order may be excluded from the routes as a non-delivered order.

Note

In the RouteQ response, non-delivered orders will be placed in a separate field: dropped_locations.

This penalty is added to the total cost of the route, if the order can't be assigned to any of the specified vehicles.

There are many reasons why an order can't be included into any route, for example:

  • The order weight exceeds the load capacity of any of the specified vehicles.

  • The total weight of the orders exceeds the total load capacity of the vehicles, so the orders can't be delivered even by additional runs. This means you have unassigned orders anyway.

  • This order is not compatible with any of the specified vehicles, or the load capacity of the vehicles compatible with a certain set of orders is too small to accommodate all such orders.

  • It's not possible to deliver the order within the demanded hard time window.

  • It's not possible to deliver the orders under the strict restrictions on driver shifts.

  • You have set hard and narrow values for the depot time window and the return parameters of the vehicles. As a result, the system plans for vehicle return to the depot, but doesn't have enough time to deliver all the orders.

  • The order doesn't have the right coordinates, making it geographically far from the other orders. As a result, the system can't find a way to complete this order.

  • You plan a complex task in low mode.

Usually, if one order has a penalty of 50 units and another order has a penalty of 5 units, the order with a penalty of 50 units is considered more important and is more likely to be included in the planned routes.

To define the non-delivery penalty in RouteQ, use the location.penalty.drop field.

Note

Note the default value for this field (1,000,000). You only need to change this field for use cases where you expect unassigned orders. To manage priorities, we recommend using the value of a similar or higher order, and don't use 0.

If you're ever unsure, contact RouteQ analysts to determine the correct coefficients.

Order-vehicle compatibility

When you define an order in the request to RouteQ, you can assign a list of requirements for the vehicle completing the order.

To define the order tags (required vehicle characteristics), use the field location.required_tags.

The order is considered compatible with the vehicle if any of the vehicle and order compatibility rules are met. Compatibility rules are set when you define the vehicles.

For more information about compatibility rules, see Vehicle tags.

If an order has optional but preferred vehicle or courier requirements (for example, the recommended skill level of a courier or the customer's preference for a certain courier to deliver), they are indicated in the location.optional_tags field. For more information, see Optional tags.

Example

In example 4, orders require temperature-controlled transportation: the Refrigerator tag is set in location.required_tags. Two of them require a vehicle equipped with a tail lift, so there are two tags in the location.required_tags field: Refrigerator and Tail lift. These orders match vehicle 1, which has the necessary values in the vehicle.tags field: Refrigerator and Tail lift.

API request (JSON)API responseView on map

Order incompatibility

If you need to deliver order types that can't be carried by a vehicle at the same time, RouteQ allows you to identify one or more incompatible types. RouteQ has no predefined order types.

Here are the incompatible order types supported:

  • Incompatible goods that can't be transported in a same vehicle and same run for objective reasons.

  • Incompatibility of different recipients with each other. For example: separation of competitive goods across different vehicles, division by certain types of customers.

Use the location.load_types field to define the order type. If necessary, you can specify more than one type for each order. To define incompatible orders, use the incompatible_load_types field, which is set in Excel on the Incompatible_order_types sheet. Use this field to specify the list of incompatible order types. At the planning step, the orders are allocated to different vehicles, if they have at least one incompatible type.

To set order incompatibility for a separate vehicle, use the vehicle.incompatible_load_types parameter, which will allow you to take the vehicle's features into account.

Note

Order incompatibility is a strict restriction. It means that it can't be violated at automatic routing. For example, if multiple orders are planned for the same point, but they are incompatible, the algorithm will assign them to different vehicles. When you use the order incompatibility types, you may get sub-optimal routes. Therefore, make sure that you introduce really important restrictions that are mandatory in practice.

Example 1

If you employ the same vehicle fleet to deliver household chemicals, food, and flowers, use the location.load_types field to specify the cargo types chemicals, food, flowers for the applicable orders.

To ensure that household chemicals are never loaded in the same vehicle with food or flowers, but still flowers and food can be transported together, set the following incompatibility rules:

type

incompatible_load_types

chemicals

food, flowers

In this example, we set 3 orders and assigned each order one of the 3 types. The algorithm planned 2 routes.

API request (JSON)API responseView on map

Example 2

In this example, 4 orders are entered, and incompatibility of cargo types and geographical zones is specified.

As a result, all orders are incompatible with each other, and the algorithm plans 4 routes even though 2 orders are sent to the same point.

API request (JSON)API responseView on map

Enable or disable grouping options

The location.use_in_proximity option selectively disables options.proximity_factor and options.global_proximity_factor that are responsible for grouping routes.

By default, location.use_in_proximity = true, meaning the grouping options apply to all orders. For more information, see Grouped routes.

Sequence order

If some orders on the route need to be completed earlier than the others, you can set their completion sequence using the sequence_order parameter. For example, if sequence_order = 1 for Order 1 and sequence_order = 2 for Order 2, it means that Order 1 must be completed earlier than Order 2.

Alert

The sequence is set end-to-end within one route for all of the vehicle's runs. As part of overall planning, there may be a situation when an order with a greater sequence_order parameter value in one route will be delivered earlier than an order with a lower parameter value in another route.

Examples of situations where sequence order is important:

  • First you need to pick up documents, sign them at another point, and then bring them back.

  • The vehicle is not equipped with a refrigerator, so first you need to deliver products with special temperature requirements.

  • You first need to fulfill orders at distant points or VIP customer orders, then the rest.

The sequence_order parameter value can be a positive integer.

Orders are completed in ascending order of the sequence_order. Accordingly, the sequence_order value for each subsequent run should be higher than the previous one. Orders with identical sequence order values are completed out of sequence. Orders without a set sequence_order value can be placed in any order and anywhere on the route.

Example

In the example, there are three orders: Order 1 with sequence_order = 1, Order 2 with sequence_order = 2, and Order 3 without a set sequence order value. It means that on this route, Order 1 is to be completed first, followed by Order 2. Order 3 can be completed at any time. This adds flexibility to planning and allows different sequence combinations:

  • Order 1 → Order 2 → Order 3

  • Order 1 → Order 3 → Order 2

  • Order 3 → Order 1 → Order 2

API request (JSON)API responseView on map

Sequence order in planned routes

If the sequence of orders in a planned route doesn't match the sequence set with the sequence_order parameter, then the orders will be ordered by sequence_order.

Exception: if the vehicles.fixed_planned_route parameter is true and the planned route doesn't need to be optimized. In this case, if the solution violates the order set by the sequence_order parameter, it will be considered impossible (UNFEASIBLE).

Example

In the example there are 4 orders and 1 courier. In vehicles.planned_route, orders are set in the direct order: 1 → 2 → 3 → 4. In sequence_order orders are set in reverse order: 4 → 3 → 2 → 1. The planned route is not fixed, vehicles.fixed_planned_route = false.

As a result, orders are arranged by the sequence_order values.

API request (JSON)API responseView on map

Sequence order in fixed routes

If a fixed part of a route violates the sequence set with sequence_order, then the solution will be considered impossible (UNFEASIBLE). Otherwise, orders that need to be completed after a fixed part of the route should have a sequence_order value equal to at least the maximum sequence_order value of orders in a fixed route.

Example

In the example there are 4 orders and 1 courier. In vehicles.visited_locations, orders are listed: 2, 4, 3. For Orders 2 and 4, sequence_order = 1, while for Orders 1 and 3 sequence_order = 2. As a result, orders from a fixed part of the route are executed first: 2 → 4 → 3 → 1.

API request (JSON)API responseView on map

Sequence order in multi-orders

The options.merge_multiorders option combines orders to the same address in a multi-order only if the orders have the same sequence_order value. In this case, no sequence_order is considered a separate value. If multiple orders to the same address have different sequence order values, these orders will not necessarily be combined into a multi-order (but they can be if such a solution is more optimal and possible taking into account the applicable restrictions).

Examples

In these examples, there are 2 couriers with a carrying capacity of 8 orders each. The option to combine orders into multi-orders is enabled. Total 12 orders:

  • The first group consists of 4 orders with the same sequence_order values and addresses.

  • The second group consists of 4 orders to the same address: 2 of them have the same sequence_order values, while the other 2 don't have a set sequence value.

  • The third group consists of 4 orders with different sequence_order values, of which only 2 are to the same address.

Example 1

In the third group, orders 3-A and 3-D have the same addresses. As a result, only orders in the first and second groups are combined.

API request (JSON)API responseView on map

Example 2

In the third group, orders 3-A and 3-B have the same addresses. As a result, orders 3-A and 3-B are also combined into one multi-order.

API request (JSON)API responseView on map

Additional order parameters for route optimization

To optimize a route, sometimes you need to take into account some specific order parameter. For example, the courier's earnings for completing a specific order or the value of an order in terms of business processes. To take such parameters into account, an additional numeric field custom_value is used.

Various custom_value are summed up and added to a variable accessible by the total_custom_value keyword when using advanced cost settings.

Example

When delivering food, couriers are paid only for delivering the order to a customer, not for picking up orders at a restaurant. It's profitable for a company to have a courier who delivers at least 12 orders per shift.

To implement this scenario, the same value custom_value = 1 is assigned to orders with the delivery type, while for orders with the pickup type, the value of this field is 0. The cost of using a vehicle is calculated using the formula: 1000 + 100 * duration_h + 100 * max(0, 12 – total_custom_value). If a courier delivers less than 12 orders, it will increase the vehicle cost by 100 units for each undelivered order. For a company, high costs mean non-optimal use of a vehicle.

In the example, courier 1 delivers only 4 orders in 1.74 hours, so the cost of their route solution total_custom_cost is 1000 + 174 + 800 = 1974 units. Courier 2 delivers 12 orders in 4.16 hours. The cost of their route solution is 1000 + 416 = 1416 units.

API request (JSON)API responseView on map

Contact support