<br />

> [!WARNING]
> This product or feature is in Preview (pre-GA). Pre-GA products and features might have limited support, and changes to pre-GA products and features might not be compatible with other pre-GA versions. Pre-GA Offerings are covered by the [Google
> Maps Platform Service Specific Terms](https://cloud.google.com/maps-platform/terms/maps-service-terms). For more information, see the [launch stage
> descriptions](https://developers.google.com/maps/launch-stages).

<br />

You can use the `ComputeRouteMatrix` method an HTTP request and response
or with any language that supports gRPC, including Java and Go.

## HTTP examples

The following example shows a `ComputeRouteMatrix` HTTP request and response.

### Request:

    curl -X POST -d '{
    "origins": [
    {
    "waypoint": { "location": { "latLng": {
    "latitude": 37.420761,
    "longitude": -122.081356,
    }}},
    "routeModifiers": { "avoidFerries": true}
    },
    {
    "waypoint": { "location": { "latLng": {
    "latitude": 37.403184,
    "longitude": -122.097371,
    }}},
    "routeModifiers": { "avoidFerries": true}
    }
    ],
    "destinations": [
    {
    "waypoint": { "location": { "latLng": {
    "latitude": 37.420999,
    "longitude": -122.086894,
    }}}
    },
    {
    "waypoint": { "location": { "latLng": {
    "latitude": 37.383047,
    "longitude": -122.044651,
    }}}
    }
    ],
    "travelMode": "DRIVE",
    "routingPreference": "TRAFFIC_AWARE"
    }' -H 'Content-Type: application/json' -H 'X-Goog-Api-Key: <YOUR_API_KEY>' -H 'X-Goog-FieldMask: originIndex,destinationIndex,duration,distanceMeters,status' 'https://routespreferred.googleapis.com/v1alpha:computeRouteMatrix'

### Response:

    [{
      "status": {},
      "distanceMeters": 827,
      "duration": "139s"
    }
    ,
    {
      "originIndex": 1,
      "destinationIndex": 1,
      "status": {},
      "distanceMeters": 5597,
      "duration": "383s"
    }
    ,
    {
      "originIndex": 1,
      "status": {},
      "distanceMeters": 2926,
      "duration": "316s"
    }
    ,
    {
      "destinationIndex": 1,
      "status": {},
      "distanceMeters": 8602,
      "duration": "613s"
    }
    ]

The following example shows a `ComputeRouteMatrix` HTTP request and response
for computing an estimated toll price.

### Request:

    curl -X POST -d '{
    "origins": [
    {
    "waypoint": { "location": { "latLng": {
            "latitude":47.7020056,
            "longitude":-122.3479236,
    }}},
    "routeModifiers": {
    "vehicleInfo":{
          "emissionType": "GASOLINE"
        },
        "tollPasses": [
          "US_MA_EZPASSMA",
          "US_WA_GOOD_TO_GO"
        ]
    }
    }],
    "destinations": [
    {
    "waypoint": { "location": { "latLng": {
            "latitude":47.6192234,
            "longitude": -122.1676792
    }}}
    }],
    "travelMode": "DRIVE",
    "routingPreference": "TRAFFIC_AWARE"
    }' -H 'Content-Type: application/json' -H 'X-Goog-Api-Key: <YOUR_API_KEY>' -H 'X-Goog-FieldMask: originIndex,destinationIndex,travelAdvisory,duration,distanceMeters,status' 'https://routespreferred.googleapis.com/v1alpha:computeRouteMatrix'

### Response:

    [{
      "status": {},
      "distanceMeters": 22498,
      "duration": "1251s",
      "travelAdvisory": {
        "tollInfo": {
          "estimatedPrice": [
            {
              "currencyCode": "USD",
              "units": "2",
              "nanos": 700000000
            }
          ]
        }
      }
    }
    ]

## Java and Go examples

The following examples show how to call the `ComputeRouteMatrix` method with Java
or Go. See the corresponding
[Java](https://github.com/googlemaps/java-routespreferred-samples) and
[Go](https://github.com/googlemaps/go-routespreferred-samples) Github
repositories for build instructions.

### Java

```java
package com.example;

import com.google.maps.routes.v1.*;
import com.google.type.LatLng;
import io.grpc.CallOptions;
import io.grpc.Channel;
import io.grpc.ClientCall;
import io.grpc.ClientInterceptor;
import io.grpc.ClientInterceptors;
import io.grpc.ForwardingClientCall;
import io.grpc.Metadata;
import io.grpc.MethodDescriptor;
import io.grpc.StatusRuntimeException;
import io.grpc.netty.NettyChannelBuilder;
import java.util.Iterator;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;

public class RoutesPreferredClient {
    // For more detail on inserting API keys, see:
    // https://cloud.google.com/endpoints/docs/grpc/restricting-api-access-with-api-keys#java
    // For more detail on system parameters (such as FieldMask), see:
    // https://cloud.google.com/apis/docs/system-parameters
    private static final class RoutesPreferredInterceptor implements ClientInterceptor {
        private final String apiKey;
        private static final Logger logger = Logger.getLogger(RoutesPreferredInterceptor.class.getName());
        private static Metadata.Key<String> API_KEY_HEADER = Metadata.Key.of("x-goog-api-key",
                Metadata.ASCII_STRING_MARSHALLER);
        private static Metadata.Key<String> FIELD_MASK_HEADER = Metadata.Key.of("x-goog-fieldmask",
                Metadata.ASCII_STRING_MARSHALLER);

        public RoutesPreferredInterceptor(String apiKey) {
            this.apiKey = apiKey;
        }

        @Override
        public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> method,
                CallOptions callOptions, Channel next) {
            logger.info("Intercepted " + method.getFullMethodName());
            ClientCall<ReqT, RespT> call = next.newCall(method, callOptions);
            call = new ForwardingClientCall.SimpleForwardingClientCall<ReqT, RespT>(call) {
                @Override
                public void start(Listener<RespT> responseListener, Metadata headers) {
                    headers.put(API_KEY_HEADER, apiKey);
                    // Note that setting the field mask to * is OK for testing, but discouraged in
                    // production.
                    // For example, for ComputeRoutes, set the field mask to
                    // "routes.distanceMeters,routes.duration,routes.polyline.encodedPolyline"
                    // in order to get the route distances, durations, and encoded polylines.
                    headers.put(FIELD_MASK_HEADER, "*");
                    super.start(responseListener, headers);
                }
            };
            return call;
        }
    }

    private static final Logger logger = Logger.getLogger(RoutesPreferredClient.class.getName());
    private final RoutesPreferredGrpc.RoutesPreferredBlockingStub blockingStub;

    public RoutesPreferredClient(Channel channel) {
        blockingStub = RoutesPreferredGrpc.newBlockingStub(channel);
    }

    public static Waypoint createWaypointForLatLng(double lat, double lng) {
        return Waypoint.newBuilder()
                .setLocation(Location.newBuilder().setLatLng(LatLng.newBuilder().setLatitude(lat).setLongitude(lng)))
                .build();
    }

    public void computeRoutes() {
        ComputeRoutesRequest request = ComputeRoutesRequest.newBuilder()
                .setOrigin(createWaypointForLatLng(37.420761, -122.081356))
                .setDestination(createWaypointForLatLng(37.420999, -122.086894)).setTravelMode(RouteTravelMode.DRIVE)
                .setRoutingPreference(RoutingPreference.TRAFFIC_AWARE).setComputeAlternativeRoutes(true)
                .setUnits(Units.METRIC).setLanguageCode("en-us")
                .setRouteModifiers(
                        RouteModifiers.newBuilder().setAvoidTolls(false).setAvoidHighways(true).setAvoidFerries(true))
                .setPolylineQuality(PolylineQuality.OVERVIEW).build();
        ComputeRoutesResponse response;
        try {
            logger.info("About to send request: " + request.toString());
            response = blockingStub.withDeadlineAfter(2000, TimeUnit.MILLISECONDS).computeRoutes(request);
        } catch (StatusRuntimeException e) {
            logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
            return;
        }
        logger.info("Response: " + response.toString());
    }

    public void computeRouteMatrix() {
        ComputeRouteMatrixRequest request = ComputeRouteMatrixRequest.newBuilder()
                .addOrigins(RouteMatrixOrigin.newBuilder().setWaypoint(createWaypointForLatLng(37.420761, -122.081356))
                        .setRouteModifiers(RouteModifiers.newBuilder().setAvoidTolls(false).setAvoidHighways(true)
                                .setAvoidFerries(true)))
                .addOrigins(RouteMatrixOrigin.newBuilder().setWaypoint(createWaypointForLatLng(37.403184, -122.097371)))
                .addDestinations(RouteMatrixDestination.newBuilder()
                        .setWaypoint(createWaypointForLatLng(37.420999, -122.086894)))
                .addDestinations(RouteMatrixDestination.newBuilder()
                        .setWaypoint(createWaypointForLatLng(37.383047, -122.044651)))
                .setTravelMode(RouteTravelMode.DRIVE).setRoutingPreference(RoutingPreference.TRAFFIC_AWARE).build();
        Iterator<RouteMatrixElement> elements;
        try {
            logger.info("About to send request: " + request.toString());
            elements = blockingStub.withDeadlineAfter(2000, TimeUnit.MILLISECONDS).computeRouteMatrix(request);
        } catch (StatusRuntimeException e) {
            logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
            return;
        }

        while (elements.hasNext()) {
            logger.info("Element response: " + elements.next().toString());
        }
    }

    public static void main(String[] args) throws Exception {
        String apiKey = System.getenv("GOOGLE_MAPS_API_KEY");

        // The standard TLS port is 443
        Channel channel = NettyChannelBuilder.forAddress("routespreferred.googleapis.com", 443).build();
        channel = ClientInterceptors.intercept(channel, new RoutesPreferredInterceptor(apiKey));

        RoutesPreferredClient client = new RoutesPreferredClient(channel);
        client.computeRoutes();
        client.computeRouteMatrix();
    }
}
  
```

### Go

```go
package main

import (
	"context"
	"crypto/tls"
	"io"
	"log"
	"os"
	"time"

	"github.com/golang/protobuf/proto"
	v1 "google.golang.org/genproto/googleapis/maps/routes/v1"
	"google.golang.org/genproto/googleapis/type/latlng"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
	"google.golang.org/grpc/metadata"
)

const (
	serverAddr = "routespreferred.googleapis.com:443"
	// Note that setting the field mask to * is OK for testing, but discouraged in
	// production.
	// For example, for ComputeRoutes, set the field mask to
	// "routes.distanceMeters,routes.duration,routes.polyline.encodedPolyline"
	// in order to get the route distances, durations, and encoded polylines.
	fieldMask = "*"
)

func createWaypoint(lat float64, lng float64) *v1.Waypoint {
	return &v1.Waypoint{LocationType: &v1.Waypoint_Location{
		Location: &v1.Location{
			LatLng: &latlng.LatLng{Latitude: lat, Longitude: lng},
		},
	}}
}

func callComputeRoutes(client v1.RoutesPreferredClient, ctx *context.Context) {
	request := v1.ComputeRoutesRequest{
		Origin:                   createWaypoint(37.420761, -122.081356),
		Destination:              createWaypoint(37.420999, -122.086894),
		TravelMode:               v1.RouteTravelMode_DRIVE,
		RoutingPreference:        v1.RoutingPreference_TRAFFIC_AWARE,
		ComputeAlternativeRoutes: true,
		Units:                    v1.Units_METRIC,
		LanguageCode:             "en-us",
		RouteModifiers: &v1.RouteModifiers{
			AvoidTolls:    false,
			AvoidHighways: true,
			AvoidFerries:  true,
		},
		PolylineQuality: v1.PolylineQuality_OVERVIEW,
	}
	marshaler := proto.TextMarshaler{}
	log.Printf("Sending request: \n%s", marshaler.Text(&request))
	result, err := client.ComputeRoutes(*ctx, &request)

	if err != nil {
		log.Fatalf("Failed to call ComputeRoutes: %v", err)
	}
	log.Printf("Result: %s", marshaler.Text(result))
}

func callComputeRouteMatrix(client v1.RoutesPreferredClient, ctx *context.Context) {
	request := v1.ComputeRouteMatrixRequest{
		Origins: []*v1.RouteMatrixOrigin{
			{Waypoint: createWaypoint(37.420761, -122.081356), RouteModifiers: &v1.RouteModifiers{
				AvoidTolls:    false,
				AvoidHighways: true,
				AvoidFerries:  true,
			}},
			{Waypoint: createWaypoint(37.403184, -122.097371)},
		},
		Destinations: []*v1.RouteMatrixDestination{
			{Waypoint: createWaypoint(37.420999, -122.086894)},
			{Waypoint: createWaypoint(37.383047, -122.044651)},
		},
		TravelMode:        v1.RouteTravelMode_DRIVE,
		RoutingPreference: v1.RoutingPreference_TRAFFIC_AWARE,
	}
	marshaler := proto.TextMarshaler{}
	log.Printf("Sending request: \n%s", marshaler.Text(&request))
	stream, err := client.ComputeRouteMatrix(*ctx, &request)

	if err != nil {
		log.Fatalf("Failed to call ComputeRouteMatrix: %v", err)
	}
	for {
		element, err := stream.Recv()
		if err == io.EOF {
			break
		}
		if err != nil {
			log.Fatalf("Received error in ComputeRouteMatrix stream: %v", err)
		}
		log.Printf("Element: %s\n", marshaler.Text(element))
	}
}

func main() {
	config := tls.Config{}
	conn, err := grpc.Dial(serverAddr,
		grpc.WithTransportCredentials(credentials.NewTLS(&config)))
	if err != nil {
		log.Fatalf("Failed to connect: %v", err)
	}
	defer conn.Close()
	client := v1.NewRoutesPreferredClient(conn)
	ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
	ctx = metadata.AppendToOutgoingContext(ctx, "X-Goog-Api-Key", os.Getenv("GOOGLE_MAPS_API_KEY"))
	ctx = metadata.AppendToOutgoingContext(ctx, "X-Goog-Fieldmask", fieldMask)
	defer cancel()

	callComputeRoutes(client, &ctx)
	callComputeRouteMatrix(client, &ctx)
}
  
```

## Calculating toll fees example

The following example uses the
[`computeRouteMatrix`](https://developers.google.com/maps/documentation/routes_preferred/reference/rest/v1alpha/TopLevel/computeRouteMatrix.md.txt)
method to return toll information on a route with an estimated
price when a toll pass is used.

This feature is enabled with the `routes.travelAdvisory.tollInfo` field mask
specified in the request. The toll pass is specified in the `route_modifiers`
field. The toll price returned is based on the pricing used by the
specified pass. If more than one pass is specified, the least expensive
pricing is returned.

### Request:

    curl -X POST -d '{
    "origins": [
    {
    "waypoint": { "location": { "latLng": {
            "latitude":47.7020056,
            "longitude":-122.3479236,
    }}},
    "routeModifiers": {
    "vehicleInfo":{
          "emissionType": "GASOLINE"
        },
        "tollPasses": [
          "US_MA_EZPASSMA",
          "US_WA_GOOD_TO_GO"
        ]
    }
    }],
    "destinations": [
    {
    "waypoint": { "location": { "latLng": {
            "latitude":47.6192234,
            "longitude": -122.1676792
    }}}
    }],
    "travelMode": "DRIVE",
    "routingPreference": "TRAFFIC_AWARE"
    }' \
    -H 'Content-Type: application/json'  \
    -H 'X-Goog-Api-Key: <YOUR_API_KEY>'  \
    -H 'X-Goog-FieldMask: originIndex,destinationIndex,travelAdvisory,duration,distanceMeters,status' 'https://routespreferred.googleapis.com/v1alpha:computeRouteMatrix'

### Response:

> [!NOTE]
> **Note** : The Routes Preferred API provides an `estimatedPrice` that applies to non-commercial vehicles.
>
> - Toll prices may be different for commercial vehicles.
> - The `units` and `nanos` are omitted when their value is zero.

    [{
      "status": {},
      "distanceMeters": 22495,
      "duration": "1446s",
      "travelAdvisory": {
        "tollInfo": {
          "estimatedPrice": [
            {
              "currencyCode": "USD",
              "units": "4",
              "nanos": 300000000
            }
          ]
        }
      }
    }]