> [!NOTE]
> **Note:** **Before constructing a vehicle request** , read the requirements under [Vehicle requests](https://developers.google.com/maps/documentation/mobility/fleet-engine/essentials/vehicles.md.txt#vehicle_requests) in the Introduction.

|---|---|---|
| This document covers important vehicle fields you can update when creating and managing vehicles. - `type`: The type of this delivery vehicle. This impacts routes generated for this vehicle. - `attributes[]`: An option array of type [`DeliveryVehicleAttribute`](https://developers.google.com/maps/documentation/mobility/fleet-engine/reference/tasks/rpc/maps.fleetengine.delivery.v1.md.txt#maps.fleetengine.delivery.v1.DeliveryVehicleAttribute). Use them to define custom criteria for vehicles in your service to enhance filtering behavior when searching or listing vehicles. |   | For a complete list of vehicle fields, see: - [`DeliveryVehicle message`](https://developers.google.com/maps/documentation/mobility/fleet-engine/reference/tasks/rpc/maps.fleetengine.delivery.v1.md.txt#deliveryvehicle) - [`DeliveryVehicle resource`](https://developers.google.com/maps/documentation/mobility/fleet-engine/reference/tasks/rest/v1/providers.deliveryVehicles.md.txt) |

## Vehicle attributes field

Use the vehicle `attributes` field to create customized criteria to enable your
consumers or fleet operators to find vehicles in your fleet across a wider
variety of search criteria. This enhances the capabilities of your apps to
provide better vehicle matches over what you would from using search criteria
based solely on other vehicle fields. Each vehicle can have at most 100
attributes, and each one must have a unique key. Values can be strings,
booleans, or numbers.

For example, you could declare a custom attribute called *zone* to
differentiate which zone of the city your delivery vehicles operate in. You'd
use string values such as the following to represent different zones: `1B`,
`2C`, and `3A`. You could then use a filter in Fleet Tracking to only show
vehicles working in a specific zone to the operator responsible for that zone.

However, custom attribute values don't have to be mutually exclusive. You might
use criteria such as *available-at-night* and *has-refrigeration* . Each of these
could be a separate custom attribute that uses boolean values. A given vehicle
could be assigned all three of these custom attributes along with the *zone*
custom attribute set to the appropriate string value.

### Update vehicle attributes

Each `attributes` key can only have one value **per vehicle** . You declare
custom vehicle attributes using the `attributes` in the field mask, and then
providing values based on the method below.

This `UpdateDeliveryVehicle` API does not allow updating only a single
attribute. When using this method, any use of the `attributes` field in the
field mask results in the **entire set** of vehicle attributes being re-declared
for the vehicle. This results in an overwrite of any pre-existing attribute not
explicitly included in the field mask. If you use this method to declare a new
custom attribute, you must also re-declare every custom attribute you want the
vehicle to retain. If you exclude the `attributes` in the field mask, then this
method leaves existing custom attributes as previously defined for the vehicle.
If you use `attributes` in the field mask, but without setting values, that is
equivalent to removing all custom attributes from the vehicle.

## Update vehicle fields example

This section shows how to update vehicle fields using
`UpdateDeliveryVehicleRequest`, which includes an `update_mask` to indicate
which fields to update. See the Protocol Buffers documentation on
[field masks](https://developers.google.com/maps/documentation/mobility/fleet-engine/essentials/vehicles/protobuf.dev/reference/cpp/api-docs/google.protobuf.util.field_mask_util) for details.

> [!NOTE]
> **Note:** The `update_mask` field should always be set. Not setting the `update_mask` field defaults to writing all fields. This can result in unintended behavior.

Updates to fields other than `last_location` require *Fleet Engine Delivery
Admin* privileges.

### Example: set custom attribute

This example specifies a new attribute: `zone`. As noted in
[Update vehicle attributes](https://developers.google.com/maps/documentation/mobility/fleet-engine/essentials/vehicles/scheduled-tasks-vehicle-fields.md.txt#update_vehicle_attributes) earlier, updating the `attributes` field using
this approach requires you to indicate all custom attributes you want to retain.
Therefore the example shows a `available-at-night` value written to preserve it
from being overwritten during an update operation that specifies the
`attributes` field.

See the [providers.deliveryVehicles.patch](https://developers.google.com/maps/documentation/mobility/fleet-engine/reference/tasks/rest/v1/providers.deliveryVehicles/patch.md.txt) reference.

### gRPC

```java
  static final String PROJECT_ID = "my-delivery-co-gcp-project";
  static final String VEHICLE_ID = "vehicle-8241890";

  DeliveryServiceBlockingStub deliveryService =
    DeliveryServiceGrpc.newBlockingStub(channel);

  // Vehicle settings
  String vehicleName = "providers/" + PROJECT_ID + "/deliveryVehicles/" + VEHICLE_ID;
  DeliveryVehicle myDeliveryVehicle = DeliveryVehicle.newBuilder()
      .addAllAttributes(ImmutableList.of(
          DeliveryVehicleAttribute.newBuilder().setKey("zone").setValue("1B").build(),
          DeliveryVehicleAttribute.newBuilder().setKey("available-at-night").setValue("true").build()))
      .build();

  // DeliveryVehicle request
  UpdateDeliveryVehicleRequest updateDeliveryVehicleRequest =
    UpdateDeliveryVehicleRequest.newBuilder()  // No need for the header
        .setName(vehicleName)
        .setDeliveryVehicle(myDeliveryVehicle)
        .setUpdateMask(FieldMask.newBuilder()
            .addPaths("attributes"))
        .build();

  try {
    DeliveryVehicle updatedDeliveryVehicle =
        deliveryService.updateDeliveryVehicle(updateDeliveryVehicleRequest);
  } catch (StatusRuntimeException e) {
    Status s = e.getStatus();
    switch (s.getCode()) {
       case NOT_FOUND:
         break;
       case PERMISSION_DENIED:
         break;
    }
    return;
  }
```

### REST

```bash
  # Set JWT, PROJECT_ID, VEHICLE_ID, TASK1_ID, and TASK2_ID in the local
  # environment
  curl -X PATCH "https://fleetengine.googleapis.com/v1/providers/${PROJECT_ID}/deliveryVehicles/${VEHICLE_ID}?updateMask=attributes" \
    -H "Content-type: application/json" \
    -H "Authorization: Bearer ${JWT}" \
    --data-binary @- << EOM
  {
      "attributes": [
        {"key": "zone", "value": "1B"},
        {"key": "available-at-night", "value": "true"}
      ]
  }
  EOM
```

## What's next

- [Update a delivery vehicle location](https://developers.google.com/maps/documentation/mobility/fleet-engine/essentials/vehicles/scheduled-tasks-update-vehicle-location.md.txt)