This example shows how to use [`loadDemands`](https://developers.google.com/maps/documentation/route-optimization/reference/rest/v1/ShipmentModel.md.txt#Shipment.FIELDS.load_demands) and [`loadLimits`](https://developers.google.com/maps/documentation/route-optimization/reference/rest/v1/ShipmentModel.md.txt#Vehicle.FIELDS.load_limits) to manage
vehicle capacity constraints in a Route Optimization API request.

For a complete conceptual overview, see the [**Load demands and limits key
concepts**](https://developers.google.com/maps/documentation/route-optimization/concepts/load-demands-limits)
document.

## Example request

The following example demonstrates a scenario where a single vehicle with a load
limit must deliver three shipments of different weights.

This example request contains the following load-related parameters:

- `shipments[0]` with a load demand [`amount`](https://developers.google.com/maps/documentation/route-optimization/reference/rest/v1/Load.md.txt#FIELDS.amount) of 50 `weightKg`.
- `shipments[1]` with a load demand [`amount`](https://developers.google.com/maps/documentation/route-optimization/reference/rest/v1/Load.md.txt#FIELDS.amount) of 10 `weightKg`.
- `shipments[2]` with a load demand [`amount`](https://developers.google.com/maps/documentation/route-optimization/reference/rest/v1/Load.md.txt#FIELDS.amount) of 80 `weightKg`.
- `vehicles[0]` with a load limit [`maxLoad`](https://developers.google.com/maps/documentation/route-optimization/reference/rest/v1/ShipmentModel.md.txt#LoadLimit.FIELDS.max_load) of 100 `weightKg`.

#### See an example request with load demands and
limits

```json
{
  "populatePolylines": false,
  "populateTransitionPolylines": false,
  "model": {
    "globalStartTime": "2023-01-13T16:00:00Z",
    "globalEndTime": "2023-01-14T16:00:00Z",
    "shipments": [
      {
        "deliveries": [
          {
            "arrivalLocation": {
              "latitude": 37.789456,
              "longitude": -122.390192
            },
            "duration": "250s"
          }
        ],
        "pickups": [
          {
            "arrivalLocation": {
              "latitude": 37.794465,
              "longitude": -122.394839
            },
            "duration": "150s"
          }
        ],
        "penaltyCost": 100.0,
        "loadDemands": {
          "weightKg": {
            "amount": "50"
          }
        }
      },
      {
        "deliveries": [
          {
            "arrivalLocation": {
              "latitude": 37.789116,
              "longitude": -122.395080
            },
            "duration": "250s"
          }
        ],
        "pickups": [
          {
            "arrivalLocation": {
              "latitude": 37.794465,
              "longitude": -122.394839
            },
            "duration": "150s"
          }
        ],
        "penaltyCost": 15.0,
        "loadDemands": {
          "weightKg": {
            "amount": "10"
          }
        }
      },
      {
        "deliveries": [
          {
            "arrivalLocation": {
              "latitude": 37.795242,
              "longitude": -122.399347
            },
            "duration": "250s"
          }
        ],
        "pickups": [
          {
            "arrivalLocation": {
              "latitude": 37.794465,
              "longitude": -122.394839
            },
            "duration": "150s"
          }
        ],
        "penaltyCost": 50.0,
        "loadDemands": {
          "weightKg": {
            "amount": "80"
          }
        }
      }
    ],
    "vehicles": [
      {
        "endLocation": {
          "latitude": 37.794465,
          "longitude": -122.394839
        },
        "startLocation": {
          "latitude": 37.794465,
          "longitude": -122.394839
        },
        "costPerHour": 40.0,
        "costPerKilometer": 10.0,
        "loadLimits": {
          "weightKg": {
            "maxLoad": "100"
          }
        }
      }
    ]
  }
}
    
```

## Example response

The response shows the optimized route for the vehicle. Because the total load
of all shipments exceeds the vehicle's capacity, the optimizer creates a
sequence of pickups and deliveries to ensure the [`loadLimits`](https://developers.google.com/maps/documentation/route-optimization/reference/rest/v1/ShipmentModel.md.txt#Vehicle.FIELDS.load_limits) are not
violated.

#### See a response to the request with load demands and
limits

```json
{
  "routes": [
    {
      "vehicleStartTime": "2023-01-13T16:00:00Z",
      "vehicleEndTime": "2023-01-13T16:43:27Z",
      "visits": [
        {
          "isPickup": true,
          "startTime": "2023-01-13T16:00:00Z",
          "detour": "0s",
          "loadDemands": {
            "weightKg": {
              "amount": "50"
            }
          }
        },
        {
          "shipmentIndex": 1,
          "isPickup": true,
          "startTime": "2023-01-13T16:02:30Z",
          "detour": "150s",
          "loadDemands": {
            "weightKg": {
              "amount": "10"
            }
          }
        },
        {
          "startTime": "2023-01-13T16:08:55Z",
          "detour": "150s",
          "loadDemands": {
            "weightKg": {
              "amount": "-50"
            }
          }
        },
        {
          "shipmentIndex": 1,
          "startTime": "2023-01-13T16:16:37Z",
          "detour": "343s",
          "loadDemands": {
            "weightKg": {
              "amount": "-10"
            }
          }
        },
        {
          "shipmentIndex": 2,
          "isPickup": true,
          "startTime": "2023-01-13T16:27:07Z",
          "detour": "1627s",
          "loadDemands": {
            "weightKg": {
              "amount": "80"
            }
          }
        },
        {
          "shipmentIndex": 2,
          "startTime": "2023-01-13T16:36:26Z",
          "detour": "0s",
          "loadDemands": {
            "weightKg": {
              "amount": "-80"
            }
          }
        }
      ],
      "transitions": [
        {
          "travelDuration": "0s",
          "waitDuration": "0s",
          "totalDuration": "0s",
          "startTime": "2023-01-13T16:00:00Z",
          "vehicleLoads": {
            "weightKg": {}
          }
        },
        {
          "travelDuration": "0s",
          "waitDuration": "0s",
          "totalDuration": "0s",
          "startTime": "2023-01-13T16:02:30Z",
          "vehicleLoads": {
            "weightKg": {
              "amount": "50"
            }
          }
        },
        {
          "travelDuration": "235s",
          "travelDistanceMeters": 795,
          "waitDuration": "0s",
          "totalDuration": "235s",
          "startTime": "2023-01-13T16:05:00Z",
          "vehicleLoads": {
            "weightKg": {
              "amount": "60"
            }
          }
        },
        {
          "travelDuration": "212s",
          "travelDistanceMeters": 791,
          "waitDuration": "0s",
          "totalDuration": "212s",
          "startTime": "2023-01-13T16:13:05Z",
          "vehicleLoads": {
            "weightKg": {
              "amount": "10"
            }
          }
        },
        {
          "travelDuration": "380s",
          "travelDistanceMeters": 1190,
          "waitDuration": "0s",
          "totalDuration": "380s",
          "startTime": "2023-01-13T16:20:47Z",
          "vehicleLoads": {
            "weightKg": {}
          }
        },
        {
          "travelDuration": "409s",
          "travelDistanceMeters": 1371,
          "waitDuration": "0s",
          "totalDuration": "409s",
          "startTime": "2023-01-13T16:29:37Z",
          "vehicleLoads": {
            "weightKg": {
              "amount": "80"
            }
          }
        },
        {
          "travelDuration": "171s",
          "travelDistanceMeters": 665,
          "waitDuration": "0s",
          "totalDuration": "171s",
          "startTime": "2023-01-13T16:40:36Z",
          "vehicleLoads": {
            "weightKg": {}
          }
        }
      ],
      "metrics": {
        "performedShipmentCount": 3,
        "travelDuration": "1407s",
        "waitDuration": "0s",
        "delayDuration": "0s",
        "breakDuration": "0s",
        "visitDuration": "1200s",
        "totalDuration": "2607s",
        "travelDistanceMeters": 4812,
        "maxLoads": {
          "weightKg": {
            "amount": "80"
          }
        }
      },
      "routeCosts": {
        "model.vehicles.cost_per_kilometer": 48.12,
        "model.vehicles.cost_per_hour": 28.966666666666665
      },
      "routeTotalCost": 77.086666666666659
    }
  ],
  "metrics": {
    "aggregatedRouteMetrics": {
      "performedShipmentCount": 3,
      "travelDuration": "1407s",
      "waitDuration": "0s",
      "delayDuration": "0s",
      "breakDuration": "0s",
      "visitDuration": "1200s",
      "totalDuration": "2607s",
      "travelDistanceMeters": 4812,
      "maxLoads": {
        "weightKg": {
          "amount": "80"
        }
      }
    },
    "usedVehicleCount": 1,
    "earliestVehicleStartTime": "2023-01-13T16:00:00Z",
    "latestVehicleEndTime": "2023-01-13T16:43:27Z",
    "totalCost": 77.086666666666659,
    "costs": {
      "model.vehicles.cost_per_hour": 28.966666666666665,
      "model.vehicles.cost_per_kilometer": 48.12
    }
  }
}
    
```

Because the combined [`loadDemands`](https://developers.google.com/maps/documentation/route-optimization/reference/rest/v1/ShipmentRoute.md.txt#Visit.FIELDS.load_demands) of the three shipments (50 + 10 + 80 =
140) exceeds the vehicle's [`loadLimits`](https://developers.google.com/maps/documentation/route-optimization/reference/rest/v1/ShipmentModel.md.txt#Vehicle.FIELDS.load_limits) (100), the vehicle can't pick up
all shipments at once. The optimizer only considers routes where `shipment[0]`
and `shipment[2]` are not in the vehicle at the same time, since these shipments
are the ones that exceed the vehicle's load limit with their combined weights.

The route has the following [`visits`](https://developers.google.com/maps/documentation/route-optimization/reference/rest/v1/ShipmentRoute.md.txt#FIELDS.visits) to not exceed the vehicle's load
limit:

1. `shipment[0]` is picked up
2. `shipment[1]` is picked up
3. `shipment[0]` is delivered
4. `shipment[1]` is delivered
5. `shipment[2]` is picked up
6. `shipment[2]` is delivered

The vehicle's load changes throughout the route, which you can observe in the
[`transitions`](https://developers.google.com/maps/documentation/route-optimization/reference/rest/v1/ShipmentRoute.md.txt#FIELDS.transitions) array. For example, `transitions[2]` shows the vehicle
carrying a load of 60 `weightKg` after picking up the first two shipments (50 +
10).

The [`maxLoads`](https://developers.google.com/maps/documentation/route-optimization/reference/rest/v1/AggregatedMetrics.md.txt#FIELDS.max_loads) property in [`metrics`](https://developers.google.com/maps/documentation/route-optimization/reference/rest/v1/ShipmentRoute.md.txt#FIELDS.metrics) shows that the maximum load
carried at any point in the route was 80 `weightKg`, confirming that the
solution successfully stayed within the vehicle's 100 `weightKg` limit.

## Soft load limits

The following example shows how to use a soft load limit to optimize a route
with multiple vehicles. The solution splits the shipments between the two
vehicles to avoid the cost penalty for exceeding the vehicle's soft load limit.

### Example request

This request now includes three delivery-only shipments and two vehicles with
the same [`loadLimits`](https://developers.google.com/maps/documentation/route-optimization/reference/rest/v1/ShipmentModel.md.txt#Vehicle.FIELDS.load_limits) and [`softMaxLoad`](https://developers.google.com/maps/documentation/route-optimization/reference/rest/v1/ShipmentModel.md.txt#LoadLimit.FIELDS.soft_max_load).

> [!NOTE]
> **Note:** [`softMaxLoad`](https://developers.google.com/maps/documentation/route-optimization/reference/rest/v1/ShipmentModel.md.txt#LoadLimit.FIELDS.soft_max_load) can only be used on routes where vehicle's load changes in one direction only. This means the route must contain either all pickups where the load increases, or all deliveries where the load decreases. This example uses only deliveries to meet this requirement.

The key parameters for this example are:

- The three shipments have a combined [`loadDemands`](https://developers.google.com/maps/documentation/route-optimization/reference/rest/v1/ShipmentModel.md.txt#Shipment.FIELDS.load_demands) of 140 `weightKg` (50
  - 60 + 30).
- There are two vehicles available with a [`softMaxLoad`](https://developers.google.com/maps/documentation/route-optimization/reference/rest/v1/ShipmentModel.md.txt#LoadLimit.FIELDS.soft_max_load) of "100" `weightKg` and a [`costPerUnitAboveSoftMax`](https://developers.google.com/maps/documentation/route-optimization/reference/rest/v1/ShipmentModel.md.txt#LoadLimit.FIELDS.cost_per_unit_above_soft_max) of 5.0.

#### See an example request with a soft load limit

```json
{
  "populatePolylines": false,
  "populateTransitionPolylines": false,
  "model": {
    "globalStartTime": "2023-01-13T16:00:00Z",
    "globalEndTime": "2023-01-14T16:00:00Z",
    "shipments": [
      {
        "deliveries": [
          {
            "arrivalLocation": {
              "latitude": 37.789456,
              "longitude": -122.390192
            },
            "duration": "250s"
          }
        ],
        
        "loadDemands": {
          "weightKg": {
            "amount": "50"
          }
        }
        
      },
      {
        "deliveries": [
          {
            "arrivalLocation": {
              "latitude": 37.789116,
              "longitude": -122.395080
            },
            "duration": "250s"
          }
        ],
        
        "loadDemands": {
          "weightKg": {
            "amount": "60"
          }
        }
        
      },
      {
        "deliveries": [
          {
            "arrivalLocation": {
              "latitude": 37.795242,
              "longitude": -122.399347
            },
            "duration": "250s"
          }
        ],
        
        "loadDemands": {
          "weightKg": {
            "amount": "30"
          }
        }
        
      }
    ],
    "vehicles": [
      {
        "endLocation": {
          "latitude": 37.794465,
          "longitude": -122.394839
        },
        "startLocation": {
          "latitude": 37.794465,
          "longitude": -122.394839
        },
        "costPerHour": 40.0,
        "costPerKilometer": 10.0,
        
        "loadLimits": {
          "weightKg": {
            "maxLoad": "150",
            "softMaxLoad": "100",
            "costPerUnitAboveSoftMax": 5.0
          }
        }
        
      },
      {
        "endLocation": {
          "latitude": 37.794465,
          "longitude": -122.394839
        },
        "startLocation": {
          "latitude": 37.794465,
          "longitude": -122.394839
        },
        "costPerHour": 40.0,
        "costPerKilometer": 10.0,
        
        "loadLimits": {
          "weightKg": {
            "maxLoad": "150",
            "softMaxLoad": "100",
            "costPerUnitAboveSoftMax": 5.0
          }
        }
        
      }
    ]
  }
}
    
```

### Example response

The response now contains two routes, one for each vehicle. The optimizer
determines that using both vehicles is more cost-effective than using one
vehicle and incurring the soft limit penalty.

#### See a response to the request with a soft load limit

```json
{
  "routes": [
    {
      "vehicleStartTime": "2023-01-13T16:00:00Z",
      "vehicleEndTime": "2023-01-13T16:13:31Z",
      "visits": [
        {
          "startTime": "2023-01-13T16:03:53Z",
          "detour": "0s",
          "loadDemands": {
            "weightKg": {
              "amount": "-50"
            }
          }
        }
      ],
      "transitions": [
        {
          "travelDuration": "233s",
          "travelDistanceMeters": 794,
          "waitDuration": "0s",
          "totalDuration": "233s",
          "startTime": "2023-01-13T16:00:00Z",
          "vehicleLoads": {
            "weightKg": {
              "amount": "50"
            }
          }
        },
        {
          "travelDuration": "328s",
          "travelDistanceMeters": 1188,
          "waitDuration": "0s",
          "totalDuration": "328s",
          "startTime": "2023-01-13T16:08:03Z",
          "vehicleLoads": {
            "weightKg": {}
          }
        }
      ],
      "metrics": {
        "performedShipmentCount": 1,
        "travelDuration": "561s",
        "visitDuration": "250s",
        "totalDuration": "811s",
        "travelDistanceMeters": 1982,
        "maxLoads": {
          "weightKg": {
            "amount": "50"
          }
        }
      },
      "routeCosts": {
        "model.vehicles.cost_per_kilometer": 19.82,
        "model.vehicles.cost_per_hour": 9.01
      },
      "routeTotalCost": 28.83
    },
    {
      "vehicleIndex": 1,
      "vehicleStartTime": "2023-01-13T16:00:00Z",
      "vehicleEndTime": "2023-01-13T16:21:43Z",
      "visits": [
        {
          "shipmentIndex": 1,
          "startTime": "2023-01-13T16:05:54Z",
          "detour": "0s",
          "loadDemands": {
            "weightKg": {
              "amount": "-60"
            }
          }
        },
        {
          "shipmentIndex": 2,
          "startTime": "2023-01-13T16:13:52Z",
          "detour": "473s",
          "loadDemands": {
            "weightKg": {
              "amount": "-30"
            }
          }
        }
      ],
      "transitions": [
        {
          "travelDuration": "354s",
          "travelDistanceMeters": 1196,
          "waitDuration": "0s",
          "totalDuration": "354s",
          "startTime": "2023-01-13T16:00:00Z",
          "vehicleLoads": {
            "weightKg": {
              "amount": "90"
            }
          }
        },
        {
          "travelDuration": "228s",
          "travelDistanceMeters": 808,
          "waitDuration": "0s",
          "totalDuration": "228s",
          "startTime": "2023-01-13T16:10:04Z",
          "vehicleLoads": {
            "weightKg": {
              "amount": "30"
            }
          }
        },
        {
          "travelDuration": "221s",
          "travelDistanceMeters": 655,
          "waitDuration": "0s",
          "totalDuration": "221s",
          "startTime": "2023-01-13T16:18:02Z",
          "vehicleLoads": {
            "weightKg": {}
          }
        }
      ],
      "metrics": {
        "performedShipmentCount": 2,
        "travelDuration": "803s",
        "visitDuration": "500s",
        "totalDuration": "1303s",
        "travelDistanceMeters": 2659,
        "maxLoads": {
          "weightKg": {
            "amount": "90"
          }
        }
      },
      "routeCosts": {
        "model.vehicles.cost_per_kilometer": 26.59,
        "model.vehicles.cost_per_hour": 14.48
      },
      "routeTotalCost": 41.07
    }
  ],
  "metrics": {
    "aggregatedRouteMetrics": {
      "performedShipmentCount": 3,
      "travelDuration": "1364s",
      "visitDuration": "750s",
      "totalDuration": "2114s",
      "travelDistanceMeters": 4641,
      "maxLoads": {
        "weightKg": {
          "amount": "90"
        }
      }
    },
    "usedVehicleCount": 2,
    "earliestVehicleStartTime": "2023-01-13T16:00:00Z",
    "latestVehicleEndTime": "2023-01-13T16:21:43Z",
    "totalCost": 69.90,
    "costs": {
      "model.vehicles.cost_per_kilometer": 46.41,
      "model.vehicles.cost_per_hour": 23.49
    }
  }
}
    
```

The following fields show how the optimizer split the shipments across the
two vehicles to keep the loads under its 100 `weightKg` soft limit.

- The first route ([`vehicleIndex`](https://developers.google.com/maps/documentation/route-optimization/reference/rest/v1/ShipmentRoute.md.txt#FIELDS.vehicle_index): 0) handles the 50 `weightKg` shipment. Its [`maxLoads`](https://developers.google.com/maps/documentation/route-optimization/reference/rest/v1/AggregatedMetrics.md.txt#FIELDS.max_loads) is "50", which is below the soft limit.
- The second route (`vehicleIndex`: 1) handles the 60 and 30 `weightKg` shipments. Its [`maxLoads`](https://developers.google.com/maps/documentation/route-optimization/reference/rest/v1/AggregatedMetrics.md.txt#FIELDS.max_loads) is "90", which is also below the soft limit.
- Because neither vehicle violates its soft limit, the [`routeCosts`](https://developers.google.com/maps/documentation/route-optimization/reference/rest/v1/ShipmentRoute.md.txt#FIELDS.route_costs) for both routes show no [`costPerUnitAboveSoftMax`](https://developers.google.com/maps/documentation/route-optimization/reference/rest/v1/ShipmentModel.md.txt#LoadLimit.FIELDS.cost_per_unit_above_soft_max) penalty.