GraphHopper Directions API (1.0.0)

Integrate A-to-B route planning, turn-by-turn navigation, route optimization, isochrone calculations, location clustering and other tools into your application.

Authentication
  1. Sign up for GraphHopper and get a standard package for 2 weeks for free
  2. Create an API key

Authenticate to the API by passing your key as a query parameter in every request.

API Explorer

You can also try all API parts without registration in our API explorer.

Client Libraries

To speed up development and make coding easier, we offer a JavaScript client and a Java client.

Optimize Response Speed
  1. Reuse SSL/TLS sessions

You should utilize the SSL session to speed up responses after the initial response or use a library that does this. E.g. for Java the OkHttp library automatically reuses SSL/TLS sessions and also the browser takes care of this automatically. For python you can use the requests library: first you create a session (session = requests.Session()) and then do requests only with this session instead of directly using "requests".

  1. Bandwidth reduction

If you create your own client, make sure it supports http/2 and gzipped responses for best speed. If you use the Matrix, the Route Optimization API or the and want to solve large problems, we recommend you to reduce bandwidth by compressing your POST request and specifying the header as follows: Content-Encoding: gzip. This will also avoid the HTTP 413 error "Request Entity Too Large".

Download OpenAPI description
Languages
Servers
https://graphhopper.com/api/1/

Map Data and Routing Profiles

The default data source is OpenStreetMap and as an alternative we have also integrated TomTom.

Route Optimization

The Route Optimization API can be used to solve traveling salesman or vehicle routing problems. You can use our API Explorer to explore Route Optimization. If you have successfully solved the first problem, we recommend this tutorial - Getting Started with the Optimization API. It shows and describes the essential elements to model your vehicle routing problem.

Further reading:

Operations

Solve a route optimization problem

Request

Start by reading the introduction to the Route Optimization API.

To solve a new vehicle routing problem, make a HTTP POST to this URL

https://graphhopper.com/api/1/vrp?key=<your_key>

It returns the solution to this problem in the JSON response.

Please note that this URL is very well suited to solve minor problems. Larger vehicle routing problems, which take longer than 10 seconds to solve, cannot be solved. To solve them, please use the batch mode URL instead.

Bodyapplication/jsonrequired

The request that contains the vehicle routing problem to be solved.

vehiclesArray of objects(Vehicle)non-empty

Specifies the available vehicles.

vehicles[].​vehicle_idstringrequired

Specifies the ID of the vehicle. Ids must be unique, i.e. if there are two vehicles with the same ID, an error is returned.

Example: "vehicle-1"
vehicles[].​type_idstring

The type ID assigns a vehicle type to this vehicle. You can specify types in the array of vehicle types. If you omit the type ID, the default type is used. The default type is a car with a capacity of 0.

Default "default-type"
Example: "my-own-type"
vehicles[].​shiftsArray of objects(Shift)

Array of shifts.

vehicles[].​start_addressobject(Address)
vehicles[].​end_addressobject(Address)

If this is omitted AND return_to_depot is true then the vehicle needs to return to its start_address.

vehicles[].​breakTimeWindowBreak (object) or DriveTimeBreak (object)
Any of:
vehicles[].​return_to_depotboolean

If it is false, the algorithm decides where to end the vehicle route. It ends in one of your customers' locations. The end is chosen such that it contributes to the overall objective function, e.g. min transport_time. If it is true, you can either specify a specific end location (which is then regarded as end depot) or you can leave it and the driver returns to its start location.

Default true
vehicles[].​earliest_startinteger(int64)

Earliest start of vehicle in seconds. It is recommended to use the unix timestamp.

Default 0
vehicles[].​latest_endinteger(int64)

Latest end of vehicle in seconds, i.e. the time the vehicle needs to be at its end location at latest.

Default 9223372036854776000
vehicles[].​skillsArray of strings

Array of skills, i.e. array of string (not case sensitive).

Example: ["drilling_maschine","screw_driver"]
vehicles[].​max_distanceinteger(int64)

Specifies the maximum distance (in meters) a vehicle can go.

Example: 400000
vehicles[].​max_driving_timeinteger(int64)

Specifies the maximum drive time (in seconds) a vehicle/driver can go, i.e. the maximum time on the road (service and waiting times are not included here)

Example: 28800
vehicles[].​max_jobsinteger(int32)

Specifies the maximum number of jobs a vehicle can load.

Example: 12
vehicles[].​min_jobsinteger(int32)

Specifies the minimum number of jobs a vehicle should load. This is a soft constraint, i.e. if it is not possible to fulfill “min_jobs”, we will still try to get as close as possible to this constraint.

Example: 12
vehicles[].​max_activitiesinteger(int32)

Specifies the maximum number of activities a vehicle can conduct.

Example: 24
vehicles[].​move_to_end_addressboolean

Indicates whether a vehicle should be moved even though it has not been assigned any jobs.

vehicle_typesArray of objects(VehicleType)

Specifies the available vehicle types. These types can be assigned to vehicles.

vehicle_types[].​type_idstringrequired

Specifies the id of the vehicle type. If a vehicle needs to be of this type, it should refer to this with its type_id attribute.

Example: "my-own-type"
vehicle_types[].​profilestring(VehicleProfileId)

The routing profile. It determines the network, speed and other physical attributes used when computing the route. See the section about routing profiles for more details and valid profile values.

vehicle_types[].​capacityArray of integers(int32)

Specifies an array of capacity dimension values which need to be int values. For example, if there are two dimensions such as volume and weight then it needs to be defined as [ 1000, 300 ] assuming a maximum volume of 1000 and a maximum weight of 300.

Default [0]
Example: [100,500]
vehicle_types[].​speed_factornumber(double)

Specifies a speed factor for this vehicle type. If the vehicle that uses this type needs to be only half as fast as what is actually calculated with our routing engine then set the speed factor to 0.5.

Default 1
vehicle_types[].​service_time_factornumber(double)

Specifies a service time factor for this vehicle type. If the vehicle/driver that uses this type is able to conduct the service as double as fast as it is determined in the corresponding service or shipment then set it to 0.5.

Default 1
vehicle_types[].​cost_per_meternumber(double)

BETA feature! Cost parameter per distance unit, here meter is used

vehicle_types[].​cost_per_secondnumber(double)

BETA feature! Cost parameter per time unit, here second is used

vehicle_types[].​cost_per_activationnumber(double)

BETA feature! Cost parameter vehicle activation, i.e. fixed costs per vehicle

vehicle_types[].​consider_trafficboolean

Specifies whether traffic should be considered. if "tomtom" is used and this is false, free flow travel times from "tomtom" are calculated. If this is true, historical traffic info are used. We do not yet have traffic data for "openstreetmap", thus, setting this true has no effect at all.

Default false
vehicle_types[].​network_data_providerstring

Specifies the network data provider. Either use openstreetmap (default) or tomtom (add-on required).

Default "openstreetmap"
Enum"openstreetmap""tomtom"
servicesArray of objects(Service)

Specifies the orders of the type "service". These are, for example, pick-ups, deliveries or other stops that are to be approached by the specified vehicles. Each of these orders contains only one location.

services[].​idstringrequired

Specifies the id of the service. Ids need to be unique so there must not be two services/shipments with the same id.

Example: "7fe77504-7df8-4497-843c-02d70b6490ce"
services[].​typestring

Specifies type of service. This makes a difference if items are loaded or unloaded, i.e. if one of the size dimensions > 0. If it is specified as service or pickup, items are loaded and will stay in the vehicle for the rest of the route (and thus consumes capacity for the rest of the route). If it is a delivery, items are implicitly loaded at the beginning of the route and will stay in the route until delivery (and thus releases capacity for the rest of the route).

Default "service"
Enum"service""pickup""delivery"
Example: "delivery"
services[].​priorityinteger(int32)

Specifies the priority. Can be 1 = high priority to 10 = low priority. Often there are more services/shipments than the available vehicle fleet can handle. Then you can set priorities to differentiate high priority tasks from those that could be left unassigned. I.e. the lower the priority the earlier these tasks are omitted in the solution.

Default 2
Example: 1
services[].​namestring

Meaningful name for service, e.g. "deliver pizza".

Example: "delivery pizza"
services[].​addressobject(Address)
services[].​durationinteger(int64)[ 0 .. 604800 ]

Specifies the duration of the service in seconds, i.e. how long it takes at the customer site.

Default 0
Example: 1800
services[].​preparation_timeinteger(int64)[ 0 .. 604800 ]

Specifies the preparation time in seconds. It can be used to model parking lot search time since if you have 3 identical locations in a row, it only falls due once.

Default 0
Example: 300
services[].​time_windowsArray of objects(TimeWindow)

Specifies an array of time window objects (see time_window object below). Specify the time either with the recommended Unix time stamp (the number of seconds since 1970-01-01) or you can also count the seconds relative to Monday morning 00:00 and define the whole week in seconds. For example, Monday 9am is then represented by 9hour * 3600sec/hour = 32400. In turn, Wednesday 1pm corresponds to 2day * 24hour/day * 3600sec/hour + 1day * 13hour/day * 3600sec/hour = 219600. See this tutorial for more information.

Example: [{"earliest":32400,"latest":36000},{"earliest":50400,"latest":54000}]
services[].​sizeArray of integers(int32)

Size can have multiple dimensions and should be in line with the capacity dimension array of the vehicle type. For example, if the item that needs to be delivered has two size dimension, volume and weight, then specify it as follow [ 20, 5 ] assuming a volume of 20 and a weight of 5.

Default [0]
Example: [30,5,1]
services[].​required_skillsArray of strings

Specifies an array of required skills, i.e. array of string (not case sensitive). For example, if this service needs to be conducted by a technician having a drilling_machine and a screw_driver then specify the array as follows: ["drilling_machine","screw_driver"]. This means that the service can only be done by a vehicle (technician) that has the skills drilling_machine AND screw_driver in its skill array. Otherwise it remains unassigned.

Example: ["drilling_machine","screw_driver"]
services[].​allowed_vehiclesArray of strings

Specifies an array of allowed vehicles, i.e. array of vehicle ids. For example, if this service can only be conducted EITHER by technician_peter OR technician_stefan specify this as follows: ["technician_peter","technician_stefan"].

Example: ["technician_peter","technician_stefan"]
services[].​disallowed_vehiclesArray of strings

Specifies an array of disallowed vehicles, i.e. array of vehicle ids.

Example: ["driver-A","driver-B"]
services[].​preferred_vehiclesArray of objects(PreferredVehicle)

Specifies an array of preferred vehicles.

services[].​max_time_in_vehicleinteger(int64)

Specifies the maximum time in seconds a delivery can stay in the vehicle. Currently, it only works with services of "type":"delivery".

Default 9223372036854776000
Example: 900
services[].​groupstring

Group this service belongs to. See the group relation and this post on how to utilize this.

Example: "group-A"
shipmentsArray of objects(Shipment)

Specifies the available shipments. Each shipment consists of a pickup and a delivery. For a single shipment, the pickup must always occur before the delivery. However, pickups and deliveries from multiple shipments can be sequenced independently.

shipments[].​idstringrequired

Specifies the id of the shipment. Ids need to be unique so there must not be two services/shipments with the same id.

Example: "7fe77504-7df8-4497-843c-02d70b6490ce"
shipments[].​namestring

Meaningful name for shipment, e.g. "pickup and deliver pizza to Peter".

Example: "pickup and deliver pizza to Peter"
shipments[].​priorityinteger(int32)

Specifies the priority. Can be 1 = high priority to 10 = low priority. Often there are more services/shipments than the available vehicle fleet can handle. Then you can set priorities to differentiate high priority tasks from those that could be left unassigned. I.e. the lower the priority the earlier these tasks are omitted in the solution.

Default 2
Example: 1
shipments[].​pickupobject(Stop)required
shipments[].​deliveryobject(Stop)required
shipments[].​sizeArray of integers(int32)

Size can have multiple dimensions and should be in line with the capacity dimension array of the vehicle type. For example, if the item that needs to be delivered has two size dimension, volume and weight, then specify it as follow [ 20, 5 ] assuming a volume of 20 and a weight of 5.

Default [0]
Example: [3]
shipments[].​required_skillsArray of strings

Specifies an array of required skills, i.e. array of string (not case sensitive). For example, if this shipment needs to be conducted by a technician having a drilling_machine and a screw_driver then specify the array as follows: ["drilling_machine","screw_driver"]. This means that the service can only be done by a vehicle (technician) that has the skills drilling_machine AND screw_driver in its skill array. Otherwise it remains unassigned.

Example: ["drilling_machine","screw_driver"]
shipments[].​allowed_vehiclesArray of strings

Specifies an array of allowed vehicles, i.e. array of vehicle ids. For example, if this shipment can only be conducted EITHER by "technician_peter" OR "technician_stefan" specify this as follows: ["technician_peter","technician_stefan"].

Example: ["technician_peter","technician_stefan"]
shipments[].​disallowed_vehiclesArray of strings

Specifies an array of disallowed vehicles, i.e. array of vehicle ids.

Example: ["driver-A","driver-B"]
shipments[].​preferred_vehiclesArray of objects(PreferredVehicle)

Specifies an array of preferred vehicles.

shipments[].​max_time_in_vehicleinteger(int64)

Specifies the maximum time in seconds a shipment can stay in the vehicle.

Default 9223372036854776000
Example: 1800
relationsArray of JobRelation (object) or GroupRelation (object)

Defines additional relationships between orders.

Any of:
relations[].​typestringrequired

Specifies the type of relation. It must be either of type in_same_route, not_in_same_route, in_sequence, in_direct_sequence or neighbor.

in_same_route: As the name suggest, it enforces the specified services or shipments to be in the same route. It can be specified as follows:

{
   "type": "in_same_route",
   "ids": ["serv_i_id","serv_j_id"]
}

This enforces service i to be in the same route as service j no matter which vehicle will be employed. If a specific vehicle (driver) is required to conduct this, just add a vehicle_id like this:

{
   "type": "in_same_route",
   "ids": ["serv_i_id","serv_j_id"],
   "vehicle_id": "vehicle1"
}

This not only enforce service i and j to be in the same route, but also makes sure that both services are in the route of vehicle1.

Tip: This way initial loads and vehicle routes can be modelled. For example, if your vehicles are already on the road and new orders come in, then vehicles can still be rescheduled subject to the orders that have already been assigned to these vehicles.

not_in_same_route: It ensures that 2 or more orders are not transported by the same vehicle. It can be specified as follows:

{
   "type": "not_in_same_route",
   "ids": ["serv_i_id","serv_j_id"]
}

in_sequence: This relation type enforces n jobs to be in sequence. It can be specified as

{
   "type": "in_sequence",
   "ids": ["serv_i_id","serv_j_id"]
}

which means that service j need to be in the same route as service i AND it needs to occur somewhere after service i. As described above if a specific vehicle needs to conduct this, just add vehicle_id.

in_direct_sequence: This enforces n services or shipments to be in direct sequence. It can be specified as

{
   "type": "in_direct_sequence",
   "ids": ["serv_i_id","serv_j_id","serv_k_id"]
}

yielding service j to occur directly after service i, and service k to occur directly after service j i.e. in strong order. Again, a vehicle can be assigned a priority by adding a vehicle_id to the relation.

neighbor: This specifies a neighbor relationship, i.e., if services i and j are to be neighbors, i must be either immediately before or after j. I can be specified as follows:

{
    "type": "neighbor",
    "ids": ["serv_i_id","serv_j_id"]
}

Special IDs: If you look at the previous example and you want service i to be the first in the route, use the special ID start as follows:

{
   "type": "in_direct_sequence",
   "ids": ["start","serv_i_id","serv_j_id","serv_k_id"]
}

Latter enforces the direct sequence of i, j and k at the beginning of the route. If this sequence should be bound to the end of the route, use the special ID end like this:

{
   "type": "in_direct_sequence",
   "ids": ["serv_i_id","service_j_id","serv_k_id","end"]
}

If you deal with services then you need to use the 'id' of your services in the field 'ids'. To also consider sequences of the pickups and deliveries of your shipments, you need to use a special ID, i.e. use the shipment id plus the keyword _pickup or _delivery. For example, to ensure that the pickup and delivery of the shipment with the id 'my_shipment' are direct neighbors, you need the following specification:

{
   "type": "in_direct_sequence",
   "ids": ["my_ship_pickup","my_ship_delivery"]
}
Example: "in_direct_sequence"
relations[].​idsArray of stringsrequired

Specifies an array of shipment and/or service ids that are in relation. If you deal with services then you need to use the id of your services in ids. To also consider sequences of the pickups and deliveries of your shipments, you need to use a special ID, i.e. use your shipment id plus the keyword _pickup or _delivery. If you want to place a service or shipment activity at the beginning of your route, use the special ID start. In turn, use end to place it at the end of the route.

Example: ["pickup-1","pickup-2"]
relations[].​vehicle_idstring

Id of pre-assigned vehicle, i.e. the vehicle id that is determined to conduct the services and shipments in this relation.

Example: "driver-Peter"
objectivesArray of objects(Objective)

Specifies an objective function. The vehicle routing problem is solved in such a way that this objective function is minimized.

Example: [{"type":"min","value":"vehicles"},{"type":"min","value":"completion_time"}]
objectives[].​typestringrequired

Type of objective function, i.e. min or min-max.

  • min: Minimizes the objective value.
  • min-max: Minimizes the maximum objective value.

For instance, min -> vehicles minimizes the number of employed vehicles. min -> completion_time minimizes the sum of your vehicle routes' completion time.

If you use, for example, min-max -> completion_time, it minimizes the maximum of your vehicle routes' completion time, i.e. it minimizes the overall makespan. This only makes sense if you have more than one vehicle. In case of one vehicle, switching from min to min-max should not have any impact. If you have more than one vehicle, then the algorithm tries to constantly move stops from one vehicle to another such that the completion time of longest vehicle route can be further reduced. For example, if you have one vehicle that takes 8 hours to serve all customers, adding another vehicle (and using min-max) might halve the time to serve all customers to 4 hours. However, this usually comes with higher transport costs.

If you want to minimize vehicles first and, second, completion_time, you can also combine different objectives like this:

"objectives" : [
   {
      "type": "min",
      "value": "vehicles"
   },
   {
      "type": "min",
      "value": "completion_time"
   }
]

If you want to balance activities or the number of stops among all employed drivers, you need to specify it as follows:

"objectives" : [
   {
      "type": "min-max",
      "value": "completion_time"
   },
   {
      "type": "min-max",
      "value": "activities"
   }
]
Default "min"
Enum"min""min-max"
Example: "min"
objectives[].​valuestringrequired

The value of the objective function. The objective value transport_time solely considers the time your drivers spend on the road, i.e. transport time. In contrary to transport_time, completion_time also takes waiting times at customer sites into account. The completion_time of a route is defined as the time from starting to ending the route, i.e. the route's transport time, the sum of waiting times plus the sum of activity durations. The completion_time_last_stop, on the other hand, refers to the completion time of the very last order in a tour or, in other words, the completion time without the last section from the last stop to the end of the tour. This is typically used if the orders are to be processed as quickly as possible. The objective value vehicles can only be used along with min and minimizes vehicles.

Default "transport_time"
Enum"completion_time""completion_time_last_stop""transport_time""vehicles""activities"
Example: "vehicles"
cost_matricesArray of objects(CostMatrix)

Specifies your own tranport time and distance matrices.

cost_matrices[].​typestring

type of cost matrix, currently default or google are supported

Enum"default""google"
cost_matrices[].​location_idsArray of strings
cost_matrices[].​dataobject

JSON data of matrix response

cost_matrices[].​profilestring

vehicle profile or empty if catch all fallback

configurationobject(Configuration)

Specifies general configurations.

configuration.​routingobject(Routing)

This contains all routing specific configurations.

configuration.​optimizationobject(Optimization)

This contains all optimization specific configurations.

algorithmobject(Algorithm)Deprecated

Use objectives instead.

algorithm.​problem_typestring
Enum"min""min-max"
algorithm.​objectivestring
Enum"transport_time""completion_time"
curl -X POST -H "Content-Type: application/json"   "https://graphhopper.com/api/1/vrp?key=api_key"   -d '{
  "vehicles": [
    {
      "vehicle_id": "my_vehicle",
      "start_address": {
        "location_id": "berlin",
        "lon": 13.406,
        "lat": 52.537
      }
    }
  ],
  "services": [
    {
      "id": "hamburg",
      "name": "visit_hamburg",
      "address": {
        "location_id": "hamburg",
        "lon": 9.999,
        "lat": 53.552
      }
    },
    { 
     "id": "munich",
      "name": "visit_munich",
      "address": {
        "location_id": "munich",
        "lon": 11.57,
        "lat": 48.145
      }
    }
  ]}'

Responses

A response containing the solution

Headers
X-RateLimit-Limitinteger

Your current daily credit limit.

X-RateLimit-Remaininginteger

Your remaining credits until the reset.

X-RateLimit-Resetinteger

The number of seconds that you have to wait before a reset of the credit count is done.

X-RateLimit-Creditsinteger

The credit costs for this request. Note it could be a decimal and even negative number, e.g. when an async request failed.

Bodyapplication/json
copyrightsArray of strings
Example: ["GraphHopper","OpenStreetMap contributors"]
statusstring

Indicates the current status of the job

Enum"waiting_in_queue""processing""finished"
Example: "finished"
waiting_time_in_queueinteger(int64)

Waiting time in ms

Example: 300000
processing_timeinteger(int64)

Processing time in ms. If job is still waiting in queue, processing_time is 0

Example: 900000
solutionobject(Solution)

Only available if status field indicates finished.

solution.​distanceinteger(int32)

Overall distance travelled in meter, i.e. the sum of each route's transport distance

Example: 1200
solution.​transport_timeinteger(int64)

Overall time travelled in seconds, i.e. the sum of each route's transport time.

Example: 12000
solution.​max_operation_timeinteger(int64)

Operation time of longest route in seconds.

Example: 4000
solution.​waiting_timeinteger(int64)

Overall waiting time in seconds.

Example: 200
solution.​service_durationinteger(int64)

Overall service time in seconds.

Example: 1200
solution.​preparation_timeinteger(int64)

Overall preparation time in seconds.

solution.​completion_timeinteger(int64)

Overall completion time in seconds, i.e. the sum of each routes/drivers operation time.

Example: 12000
solution.​no_vehiclesinteger(int32)

Number of employed vehicles.

Example: 10
solution.​no_unassignedinteger(int32)

Number of jobs that could not be assigned to final solution.

Example: 1
solution.​routesArray of objects(Route)

An array of routes

solution.​unassignedobject
solution.​costsinteger(int32)Deprecated
solution.​timeinteger(int64)Deprecated

Use transport_time instead.

Response
application/json
{ "copyrights": [ "GraphHopper", "OpenStreetMap contributors" ], "job_id": "d62fcadd-c84a-4298-90b5-28550125bec5", "status": "finished", "waiting_time_in_queue": 0, "processing_time": 459, "solution": { "costs": 438, "distance": 17994, "time": 4094, "transport_time": 4094, "completion_time": 4172, "max_operation_time": 2465, "waiting_time": 78, "service_duration": 0, "preparation_time": 0, "no_vehicles": 2, "no_unassigned": 0, "routes": [ { "vehicle_id": "vehicle-2", "distance": 10618, "transport_time": 2465, "completion_time": 2465, "waiting_time": 0, "service_duration": 0, "preparation_time": 0, "points": [ { "coordinates": [ [ 13.40608, 52.53701 ], [ 13.40643, 52.53631 ], [ 13.40554, 52.53616 ], [ 13.4054, 52.53608 ], [ 13.40445, 52.53513 ], [ 13.40436, 52.53509 ], [ 13.40428, 52.53508 ], [ 13.40463, 52.53419 ], [ 13.40451, 52.53419 ], [ 13.4034, 52.53401 ], [ 13.403, 52.53359 ], [ 13.40291, 52.53354 ], [ 13.40268, 52.53347 ], [ 13.39888, 52.53259 ], [ 13.39839, 52.53253 ], [ 13.39812, 52.53251 ], [ 13.39616, 52.53243 ], [ 13.39579, 52.5324 ], [ 13.38973, 52.53173 ], [ 13.39163, 52.53025 ], [ 13.38797, 52.52935 ], [ 13.38763, 52.52996 ] ], "type": "LineString" }, { "coordinates": [ [ 13.38763, 52.52996 ], [ 13.38739, 52.53039 ], [ 13.38724, 52.53036 ], [ 13.38464, 52.52929 ], [ 13.38538, 52.52871 ], [ 13.38634, 52.52792 ], [ 13.38638, 52.52779 ], [ 13.38657, 52.52763 ], [ 13.38676, 52.52741 ], [ 13.38698, 52.52713 ], [ 13.38704, 52.52701 ], [ 13.38753, 52.524 ], [ 13.3877, 52.52307 ], [ 13.3878, 52.52282 ], [ 13.38788, 52.52252 ], [ 13.38802, 52.52174 ], [ 13.38519, 52.52009 ], [ 13.38539, 52.5191 ], [ 13.38548, 52.51852 ], [ 13.38042, 52.51819 ], [ 13.38071, 52.5167 ], [ 13.38076, 52.51652 ], [ 13.38084, 52.51634 ], [ 13.3821, 52.51396 ], [ 13.38055, 52.51365 ] ], "type": "LineString" }, { "coordinates": [ [ 13.38055, 52.51365 ], [ 13.38229, 52.514 ], [ 13.38363, 52.51429 ], [ 13.3848, 52.51445 ], [ 13.38504, 52.51358 ], [ 13.39124, 52.51397 ], [ 13.3911, 52.51488 ], [ 13.39303, 52.51499 ], [ 13.39317, 52.5141 ], [ 13.39548, 52.51419 ], [ 13.39571, 52.51421 ] ], "type": "LineString" }, { "coordinates": [ [ 13.39571, 52.51421 ], [ 13.39695, 52.51434 ], [ 13.39674, 52.51523 ], [ 13.39742, 52.51531 ], [ 13.39873, 52.51558 ], [ 13.39846, 52.51599 ], [ 13.39825, 52.51729 ], [ 13.39805, 52.51755 ], [ 13.39892, 52.51761 ], [ 13.39917, 52.51764 ], [ 13.39964, 52.51775 ], [ 13.40009, 52.51791 ], [ 13.40034, 52.51797 ], [ 13.4021, 52.51864 ], [ 13.40288, 52.51896 ], [ 13.40375, 52.51936 ], [ 13.40498, 52.52001 ], [ 13.40463, 52.5203 ], [ 13.40311, 52.52144 ], [ 13.40442, 52.52189 ], [ 13.40448, 52.52192 ], [ 13.40451, 52.52195 ], [ 13.40473, 52.52199 ], [ 13.40504, 52.52208 ], [ 13.40572, 52.52235 ], [ 13.40687, 52.52294 ], [ 13.40693, 52.52299 ], [ 13.40706, 52.52319 ], [ 13.40738, 52.52378 ], [ 13.40787, 52.52443 ], [ 13.4079, 52.52453 ], [ 13.40938, 52.52401 ], [ 13.40962, 52.52398 ], [ 13.41001, 52.52395 ], [ 13.41072, 52.52391 ], [ 13.41215, 52.52389 ], [ 13.41233, 52.52386 ], [ 13.4131, 52.5235 ], [ 13.41288, 52.52333 ], [ 13.41475, 52.52247 ], [ 13.41496, 52.52264 ], [ 13.41523, 52.52251 ], [ 13.41633, 52.52338 ], [ 13.41631, 52.52346 ], [ 13.41654, 52.52364 ], [ 13.41684, 52.52351 ] ], "type": "LineString" }, { "coordinates": [ [ 13.41684, 52.52351 ], [ 13.41654, 52.52364 ], [ 13.41631, 52.52346 ], [ 13.4163, 52.52344 ], [ 13.41587, 52.52363 ], [ 13.41572, 52.5235 ], [ 13.41409, 52.5242 ], [ 13.41454, 52.52461 ], [ 13.41454, 52.52466 ], [ 13.41358, 52.52508 ], [ 13.41366, 52.52514 ], [ 13.41344, 52.52525 ], [ 13.4133, 52.52514 ], [ 13.41316, 52.5252 ], [ 13.41107, 52.52585 ], [ 13.41118, 52.52606 ], [ 13.41118, 52.52616 ], [ 13.41095, 52.52664 ], [ 13.41097, 52.52678 ], [ 13.41084, 52.52706 ], [ 13.41057, 52.52747 ], [ 13.41028, 52.52809 ], [ 13.41032, 52.52821 ], [ 13.4102, 52.52847 ], [ 13.40999, 52.52875 ], [ 13.40984, 52.52905 ], [ 13.40982, 52.52914 ], [ 13.40984, 52.52926 ], [ 13.4104, 52.52998 ], [ 13.4105, 52.53001 ], [ 13.41064, 52.53016 ], [ 13.41082, 52.5303 ], [ 13.41198, 52.53107 ], [ 13.4122, 52.53128 ], [ 13.41232, 52.53143 ], [ 13.41247, 52.53192 ], [ 13.41267, 52.53245 ], [ 13.41275, 52.53259 ], [ 13.41215, 52.5327 ], [ 13.40731, 52.53463 ], [ 13.40608, 52.53701 ] ], "type": "LineString" } ], "activities": [ { "type": "start", "location_id": "berlin", "address": { "location_id": "berlin", "lat": 52.537, "lon": 13.406 }, "end_time": 1554804329, "end_date_time": null, "distance": 0, "driving_time": 0, "preparation_time": 0, "waiting_time": 0, "load_after": [ 0 ] }, { "type": "pickupShipment", "id": "7fe77504-7df8-4497-843c-02d70b6490ce", "location_id": "13.387613_52.529961", "address": { "location_id": "13.387613_52.529961", "lat": 52.529961, "lon": 13.387613 }, "arr_time": 1554804789, "arr_date_time": null, "end_time": 1554804789, "end_date_time": null, "waiting_time": 0, "distance": 2012, "driving_time": 460, "preparation_time": 0, "load_before": [ 0 ], "load_after": [ 1 ] }, { "type": "deliverShipment", "id": "7fe77504-7df8-4497-843c-02d70b6490ce", "location_id": "13.380575_52.513614", "address": { "location_id": "13.380575_52.513614", "lat": 52.513614, "lon": 13.380575 }, "arr_time": 1554805344, "arr_date_time": null, "end_time": 1554805344, "end_date_time": null, "waiting_time": 0, "distance": 4560, "driving_time": 1015, "preparation_time": 0, "load_before": [ 1 ], "load_after": [ 0 ] }, { "type": "service", "id": "s-4", "location_id": "13.395767_52.514038", "address": { "location_id": "13.395767_52.514038", "lat": 52.514038, "lon": 13.395767 }, "arr_time": 1554805632, "arr_date_time": null, "end_time": 1554805632, "end_date_time": null, "waiting_time": 0, "distance": 5887, "driving_time": 1303, "preparation_time": 0, "load_before": [ 0 ], "load_after": [ 1 ] }, { "type": "service", "id": "s-3", "location_id": "13.416882_52.523543", "address": { "location_id": "13.416882_52.523543", "lat": 52.523543, "lon": 13.416882 }, "arr_time": 1554806253, "arr_date_time": null, "end_time": 1554806253, "end_date_time": null, "waiting_time": 0, "distance": 8486, "driving_time": 1924, "preparation_time": 0, "load_before": [ 1 ], "load_after": [ 2 ] }, { "type": "end", "location_id": "berlin", "address": { "location_id": "berlin", "lat": 52.537, "lon": 13.406 }, "arr_time": 1554806794, "arr_date_time": null, "distance": 10618, "driving_time": 2465, "preparation_time": 0, "waiting_time": 0, "load_before": [ 2 ] } ] }, { "vehicle_id": "vehicle-1", "distance": 7376, "transport_time": 1629, "completion_time": 1707, "waiting_time": 78, "service_duration": 0, "preparation_time": 0, "points": [ { "coordinates": [ [ 13.40608, 52.53701 ], [ 13.40674, 52.53571 ], [ 13.40433, 52.53313 ], [ 13.40271, 52.53149 ], [ 13.40246, 52.53121 ], [ 13.40148, 52.52999 ], [ 13.40128, 52.52993 ], [ 13.40118, 52.52988 ], [ 13.40133, 52.5296 ], [ 13.40138, 52.52951 ], [ 13.40167, 52.52914 ], [ 13.40188, 52.52895 ], [ 13.398, 52.52885 ], [ 13.39289, 52.52748 ], [ 13.39354, 52.5264 ], [ 13.39358, 52.52628 ], [ 13.39324, 52.52575 ], [ 13.39334, 52.52573 ], [ 13.39339, 52.52584 ] ], "type": "LineString" }, { "coordinates": [ [ 13.39339, 52.52584 ], [ 13.3934, 52.52599 ], [ 13.39358, 52.52628 ], [ 13.39354, 52.5264 ], [ 13.39242, 52.52823 ], [ 13.39381, 52.52852 ], [ 13.38973, 52.53173 ], [ 13.38717, 52.5315 ], [ 13.38678, 52.5315 ], [ 13.38641, 52.53147 ], [ 13.38617, 52.53143 ], [ 13.38607, 52.53155 ], [ 13.38526, 52.53225 ], [ 13.38501, 52.53252 ], [ 13.38316, 52.53418 ], [ 13.38179, 52.5355 ], [ 13.38084, 52.53523 ], [ 13.38081, 52.53531 ], [ 13.3795, 52.53677 ], [ 13.37941, 52.53682 ], [ 13.37935, 52.53683 ], [ 13.37919, 52.53682 ], [ 13.37617, 52.5361 ], [ 13.37502, 52.53698 ], [ 13.37584, 52.53734 ] ], "type": "LineString" }, { "coordinates": [ [ 13.37584, 52.53734 ], [ 13.37566, 52.53726 ], [ 13.37515, 52.53763 ], [ 13.37644, 52.53841 ], [ 13.37807, 52.53935 ], [ 13.37946, 52.5402 ], [ 13.3796, 52.54019 ], [ 13.37984, 52.54021 ], [ 13.37988, 52.54012 ], [ 13.38062, 52.53936 ], [ 13.38169, 52.53832 ], [ 13.38236, 52.5377 ], [ 13.38363, 52.53661 ], [ 13.38492, 52.53555 ], [ 13.38613, 52.53447 ], [ 13.38757, 52.53338 ], [ 13.38791, 52.53354 ], [ 13.38812, 52.53368 ], [ 13.38833, 52.53392 ], [ 13.38977, 52.53518 ], [ 13.39003, 52.53539 ], [ 13.39256, 52.53701 ], [ 13.39316, 52.53739 ], [ 13.39327, 52.53744 ], [ 13.3936, 52.53757 ], [ 13.40155, 52.53982 ], [ 13.40357, 52.53715 ], [ 13.40372, 52.53719 ], [ 13.40465, 52.53727 ], [ 13.4048, 52.53726 ], [ 13.4059, 52.53736 ], [ 13.40608, 52.53701 ] ], "type": "LineString" } ], "activities": [ { "type": "start", "location_id": "berlin", "address": { "location_id": "berlin", "lat": 52.537, "lon": 13.406 }, "end_time": 1554804329, "end_date_time": null, "distance": 0, "driving_time": 0, "preparation_time": 0, "waiting_time": 0, "load_after": [ 0 ] }, { "type": "service", "id": "s-2", "location_id": "13.393364_52.525851", "address": { "location_id": "13.393364_52.525851", "lat": 52.525851, "lon": 13.393364 }, "arr_time": 1554804743, "arr_date_time": null, "end_time": 1554804743, "end_date_time": null, "waiting_time": 0, "distance": 1884, "driving_time": 414, "preparation_time": 0, "load_before": [ 0 ], "load_after": [ 1 ] }, { "type": "service", "id": "s-1", "location_id": "13.375854_52.537338", "address": { "location_id": "13.375854_52.537338", "lat": 52.537338, "lon": 13.375854 }, "arr_time": 1554805251, "arr_date_time": null, "end_time": 1554805329, "end_date_time": null, "waiting_time": 78, "distance": 4205, "driving_time": 922, "preparation_time": 0, "load_before": [ 1 ], "load_after": [ 2 ] }, { "type": "end", "location_id": "berlin", "address": { "location_id": "berlin", "lat": 52.537, "lon": 13.406 }, "arr_time": 1554806036, "arr_date_time": null, "distance": 7376, "driving_time": 1629, "preparation_time": 0, "waiting_time": 0, "load_before": [ 2 ] } ] } ], "unassigned": { "services": [], "shipments": [], "breaks": [], "details": [] } } }

Submit a route optimization job

Request

To solve a vehicle routing problem, perform the following steps:

1.) Make a HTTP POST to this URL

https://graphhopper.com/api/1/vrp/optimize?key=<your_key>

It returns a job id (job_id).

2.) Take the job id and fetch the solution for the vehicle routing problem from this URL:

https://graphhopper.com/api/1/vrp/solution/<job_id>?key=<your_key>

We recommend to query the solution every 500ms until it returns 'status=finished'.

Note: Since the workflow is a bit more cumbersome and since you lose some time in fetching the solution, you should always prefer the synchronous endpoint. You should use the batch mode only for long running problems.

Bodyapplication/jsonrequired

The request that contains the problem to be solved.

vehiclesArray of objects(Vehicle)non-empty

Specifies the available vehicles.

vehicles[].​vehicle_idstringrequired

Specifies the ID of the vehicle. Ids must be unique, i.e. if there are two vehicles with the same ID, an error is returned.

Example: "vehicle-1"
vehicles[].​type_idstring

The type ID assigns a vehicle type to this vehicle. You can specify types in the array of vehicle types. If you omit the type ID, the default type is used. The default type is a car with a capacity of 0.

Default "default-type"
Example: "my-own-type"
vehicles[].​shiftsArray of objects(Shift)

Array of shifts.

vehicles[].​start_addressobject(Address)
vehicles[].​end_addressobject(Address)

If this is omitted AND return_to_depot is true then the vehicle needs to return to its start_address.

vehicles[].​breakTimeWindowBreak (object) or DriveTimeBreak (object)
Any of:
vehicles[].​return_to_depotboolean

If it is false, the algorithm decides where to end the vehicle route. It ends in one of your customers' locations. The end is chosen such that it contributes to the overall objective function, e.g. min transport_time. If it is true, you can either specify a specific end location (which is then regarded as end depot) or you can leave it and the driver returns to its start location.

Default true
vehicles[].​earliest_startinteger(int64)

Earliest start of vehicle in seconds. It is recommended to use the unix timestamp.

Default 0
vehicles[].​latest_endinteger(int64)

Latest end of vehicle in seconds, i.e. the time the vehicle needs to be at its end location at latest.

Default 9223372036854776000
vehicles[].​skillsArray of strings

Array of skills, i.e. array of string (not case sensitive).

Example: ["drilling_maschine","screw_driver"]
vehicles[].​max_distanceinteger(int64)

Specifies the maximum distance (in meters) a vehicle can go.

Example: 400000
vehicles[].​max_driving_timeinteger(int64)

Specifies the maximum drive time (in seconds) a vehicle/driver can go, i.e. the maximum time on the road (service and waiting times are not included here)

Example: 28800
vehicles[].​max_jobsinteger(int32)

Specifies the maximum number of jobs a vehicle can load.

Example: 12
vehicles[].​min_jobsinteger(int32)

Specifies the minimum number of jobs a vehicle should load. This is a soft constraint, i.e. if it is not possible to fulfill “min_jobs”, we will still try to get as close as possible to this constraint.

Example: 12
vehicles[].​max_activitiesinteger(int32)

Specifies the maximum number of activities a vehicle can conduct.

Example: 24
vehicles[].​move_to_end_addressboolean

Indicates whether a vehicle should be moved even though it has not been assigned any jobs.

vehicle_typesArray of objects(VehicleType)

Specifies the available vehicle types. These types can be assigned to vehicles.

vehicle_types[].​type_idstringrequired

Specifies the id of the vehicle type. If a vehicle needs to be of this type, it should refer to this with its type_id attribute.

Example: "my-own-type"
vehicle_types[].​profilestring(VehicleProfileId)

The routing profile. It determines the network, speed and other physical attributes used when computing the route. See the section about routing profiles for more details and valid profile values.

vehicle_types[].​capacityArray of integers(int32)

Specifies an array of capacity dimension values which need to be int values. For example, if there are two dimensions such as volume and weight then it needs to be defined as [ 1000, 300 ] assuming a maximum volume of 1000 and a maximum weight of 300.

Default [0]
Example: [100,500]
vehicle_types[].​speed_factornumber(double)

Specifies a speed factor for this vehicle type. If the vehicle that uses this type needs to be only half as fast as what is actually calculated with our routing engine then set the speed factor to 0.5.

Default 1
vehicle_types[].​service_time_factornumber(double)

Specifies a service time factor for this vehicle type. If the vehicle/driver that uses this type is able to conduct the service as double as fast as it is determined in the corresponding service or shipment then set it to 0.5.

Default 1
vehicle_types[].​cost_per_meternumber(double)

BETA feature! Cost parameter per distance unit, here meter is used

vehicle_types[].​cost_per_secondnumber(double)

BETA feature! Cost parameter per time unit, here second is used

vehicle_types[].​cost_per_activationnumber(double)

BETA feature! Cost parameter vehicle activation, i.e. fixed costs per vehicle

vehicle_types[].​consider_trafficboolean

Specifies whether traffic should be considered. if "tomtom" is used and this is false, free flow travel times from "tomtom" are calculated. If this is true, historical traffic info are used. We do not yet have traffic data for "openstreetmap", thus, setting this true has no effect at all.

Default false
vehicle_types[].​network_data_providerstring

Specifies the network data provider. Either use openstreetmap (default) or tomtom (add-on required).

Default "openstreetmap"
Enum"openstreetmap""tomtom"
servicesArray of objects(Service)

Specifies the orders of the type "service". These are, for example, pick-ups, deliveries or other stops that are to be approached by the specified vehicles. Each of these orders contains only one location.

services[].​idstringrequired

Specifies the id of the service. Ids need to be unique so there must not be two services/shipments with the same id.

Example: "7fe77504-7df8-4497-843c-02d70b6490ce"
services[].​typestring

Specifies type of service. This makes a difference if items are loaded or unloaded, i.e. if one of the size dimensions > 0. If it is specified as service or pickup, items are loaded and will stay in the vehicle for the rest of the route (and thus consumes capacity for the rest of the route). If it is a delivery, items are implicitly loaded at the beginning of the route and will stay in the route until delivery (and thus releases capacity for the rest of the route).

Default "service"
Enum"service""pickup""delivery"
Example: "delivery"
services[].​priorityinteger(int32)

Specifies the priority. Can be 1 = high priority to 10 = low priority. Often there are more services/shipments than the available vehicle fleet can handle. Then you can set priorities to differentiate high priority tasks from those that could be left unassigned. I.e. the lower the priority the earlier these tasks are omitted in the solution.

Default 2
Example: 1
services[].​namestring

Meaningful name for service, e.g. "deliver pizza".

Example: "delivery pizza"
services[].​addressobject(Address)
services[].​durationinteger(int64)[ 0 .. 604800 ]

Specifies the duration of the service in seconds, i.e. how long it takes at the customer site.

Default 0
Example: 1800
services[].​preparation_timeinteger(int64)[ 0 .. 604800 ]

Specifies the preparation time in seconds. It can be used to model parking lot search time since if you have 3 identical locations in a row, it only falls due once.

Default 0
Example: 300
services[].​time_windowsArray of objects(TimeWindow)

Specifies an array of time window objects (see time_window object below). Specify the time either with the recommended Unix time stamp (the number of seconds since 1970-01-01) or you can also count the seconds relative to Monday morning 00:00 and define the whole week in seconds. For example, Monday 9am is then represented by 9hour * 3600sec/hour = 32400. In turn, Wednesday 1pm corresponds to 2day * 24hour/day * 3600sec/hour + 1day * 13hour/day * 3600sec/hour = 219600. See this tutorial for more information.

Example: [{"earliest":32400,"latest":36000},{"earliest":50400,"latest":54000}]
services[].​sizeArray of integers(int32)

Size can have multiple dimensions and should be in line with the capacity dimension array of the vehicle type. For example, if the item that needs to be delivered has two size dimension, volume and weight, then specify it as follow [ 20, 5 ] assuming a volume of 20 and a weight of 5.

Default [0]
Example: [30,5,1]
services[].​required_skillsArray of strings

Specifies an array of required skills, i.e. array of string (not case sensitive). For example, if this service needs to be conducted by a technician having a drilling_machine and a screw_driver then specify the array as follows: ["drilling_machine","screw_driver"]. This means that the service can only be done by a vehicle (technician) that has the skills drilling_machine AND screw_driver in its skill array. Otherwise it remains unassigned.

Example: ["drilling_machine","screw_driver"]
services[].​allowed_vehiclesArray of strings

Specifies an array of allowed vehicles, i.e. array of vehicle ids. For example, if this service can only be conducted EITHER by technician_peter OR technician_stefan specify this as follows: ["technician_peter","technician_stefan"].

Example: ["technician_peter","technician_stefan"]
services[].​disallowed_vehiclesArray of strings

Specifies an array of disallowed vehicles, i.e. array of vehicle ids.

Example: ["driver-A","driver-B"]
services[].​preferred_vehiclesArray of objects(PreferredVehicle)

Specifies an array of preferred vehicles.

services[].​max_time_in_vehicleinteger(int64)

Specifies the maximum time in seconds a delivery can stay in the vehicle. Currently, it only works with services of "type":"delivery".

Default 9223372036854776000
Example: 900
services[].​groupstring

Group this service belongs to. See the group relation and this post on how to utilize this.

Example: "group-A"
shipmentsArray of objects(Shipment)

Specifies the available shipments. Each shipment consists of a pickup and a delivery. For a single shipment, the pickup must always occur before the delivery. However, pickups and deliveries from multiple shipments can be sequenced independently.

shipments[].​idstringrequired

Specifies the id of the shipment. Ids need to be unique so there must not be two services/shipments with the same id.

Example: "7fe77504-7df8-4497-843c-02d70b6490ce"
shipments[].​namestring

Meaningful name for shipment, e.g. "pickup and deliver pizza to Peter".

Example: "pickup and deliver pizza to Peter"
shipments[].​priorityinteger(int32)

Specifies the priority. Can be 1 = high priority to 10 = low priority. Often there are more services/shipments than the available vehicle fleet can handle. Then you can set priorities to differentiate high priority tasks from those that could be left unassigned. I.e. the lower the priority the earlier these tasks are omitted in the solution.

Default 2
Example: 1
shipments[].​pickupobject(Stop)required
shipments[].​deliveryobject(Stop)required
shipments[].​sizeArray of integers(int32)

Size can have multiple dimensions and should be in line with the capacity dimension array of the vehicle type. For example, if the item that needs to be delivered has two size dimension, volume and weight, then specify it as follow [ 20, 5 ] assuming a volume of 20 and a weight of 5.

Default [0]
Example: [3]
shipments[].​required_skillsArray of strings

Specifies an array of required skills, i.e. array of string (not case sensitive). For example, if this shipment needs to be conducted by a technician having a drilling_machine and a screw_driver then specify the array as follows: ["drilling_machine","screw_driver"]. This means that the service can only be done by a vehicle (technician) that has the skills drilling_machine AND screw_driver in its skill array. Otherwise it remains unassigned.

Example: ["drilling_machine","screw_driver"]
shipments[].​allowed_vehiclesArray of strings

Specifies an array of allowed vehicles, i.e. array of vehicle ids. For example, if this shipment can only be conducted EITHER by "technician_peter" OR "technician_stefan" specify this as follows: ["technician_peter","technician_stefan"].

Example: ["technician_peter","technician_stefan"]
shipments[].​disallowed_vehiclesArray of strings

Specifies an array of disallowed vehicles, i.e. array of vehicle ids.

Example: ["driver-A","driver-B"]
shipments[].​preferred_vehiclesArray of objects(PreferredVehicle)

Specifies an array of preferred vehicles.

shipments[].​max_time_in_vehicleinteger(int64)

Specifies the maximum time in seconds a shipment can stay in the vehicle.

Default 9223372036854776000
Example: 1800
relationsArray of JobRelation (object) or GroupRelation (object)

Defines additional relationships between orders.

Any of:
relations[].​typestringrequired

Specifies the type of relation. It must be either of type in_same_route, not_in_same_route, in_sequence, in_direct_sequence or neighbor.

in_same_route: As the name suggest, it enforces the specified services or shipments to be in the same route. It can be specified as follows:

{
   "type": "in_same_route",
   "ids": ["serv_i_id","serv_j_id"]
}

This enforces service i to be in the same route as service j no matter which vehicle will be employed. If a specific vehicle (driver) is required to conduct this, just add a vehicle_id like this:

{
   "type": "in_same_route",
   "ids": ["serv_i_id","serv_j_id"],
   "vehicle_id": "vehicle1"
}

This not only enforce service i and j to be in the same route, but also makes sure that both services are in the route of vehicle1.

Tip: This way initial loads and vehicle routes can be modelled. For example, if your vehicles are already on the road and new orders come in, then vehicles can still be rescheduled subject to the orders that have already been assigned to these vehicles.

not_in_same_route: It ensures that 2 or more orders are not transported by the same vehicle. It can be specified as follows:

{
   "type": "not_in_same_route",
   "ids": ["serv_i_id","serv_j_id"]
}

in_sequence: This relation type enforces n jobs to be in sequence. It can be specified as

{
   "type": "in_sequence",
   "ids": ["serv_i_id","serv_j_id"]
}

which means that service j need to be in the same route as service i AND it needs to occur somewhere after service i. As described above if a specific vehicle needs to conduct this, just add vehicle_id.

in_direct_sequence: This enforces n services or shipments to be in direct sequence. It can be specified as

{
   "type": "in_direct_sequence",
   "ids": ["serv_i_id","serv_j_id","serv_k_id"]
}

yielding service j to occur directly after service i, and service k to occur directly after service j i.e. in strong order. Again, a vehicle can be assigned a priority by adding a vehicle_id to the relation.

neighbor: This specifies a neighbor relationship, i.e., if services i and j are to be neighbors, i must be either immediately before or after j. I can be specified as follows:

{
    "type": "neighbor",
    "ids": ["serv_i_id","serv_j_id"]
}

Special IDs: If you look at the previous example and you want service i to be the first in the route, use the special ID start as follows:

{
   "type": "in_direct_sequence",
   "ids": ["start","serv_i_id","serv_j_id","serv_k_id"]
}

Latter enforces the direct sequence of i, j and k at the beginning of the route. If this sequence should be bound to the end of the route, use the special ID end like this:

{
   "type": "in_direct_sequence",
   "ids": ["serv_i_id","service_j_id","serv_k_id","end"]
}

If you deal with services then you need to use the 'id' of your services in the field 'ids'. To also consider sequences of the pickups and deliveries of your shipments, you need to use a special ID, i.e. use the shipment id plus the keyword _pickup or _delivery. For example, to ensure that the pickup and delivery of the shipment with the id 'my_shipment' are direct neighbors, you need the following specification:

{
   "type": "in_direct_sequence",
   "ids": ["my_ship_pickup","my_ship_delivery"]
}
Example: "in_direct_sequence"
relations[].​idsArray of stringsrequired

Specifies an array of shipment and/or service ids that are in relation. If you deal with services then you need to use the id of your services in ids. To also consider sequences of the pickups and deliveries of your shipments, you need to use a special ID, i.e. use your shipment id plus the keyword _pickup or _delivery. If you want to place a service or shipment activity at the beginning of your route, use the special ID start. In turn, use end to place it at the end of the route.

Example: ["pickup-1","pickup-2"]
relations[].​vehicle_idstring

Id of pre-assigned vehicle, i.e. the vehicle id that is determined to conduct the services and shipments in this relation.

Example: "driver-Peter"
objectivesArray of objects(Objective)

Specifies an objective function. The vehicle routing problem is solved in such a way that this objective function is minimized.

Example: [{"type":"min","value":"vehicles"},{"type":"min","value":"completion_time"}]
objectives[].​typestringrequired

Type of objective function, i.e. min or min-max.

  • min: Minimizes the objective value.
  • min-max: Minimizes the maximum objective value.

For instance, min -> vehicles minimizes the number of employed vehicles. min -> completion_time minimizes the sum of your vehicle routes' completion time.

If you use, for example, min-max -> completion_time, it minimizes the maximum of your vehicle routes' completion time, i.e. it minimizes the overall makespan. This only makes sense if you have more than one vehicle. In case of one vehicle, switching from min to min-max should not have any impact. If you have more than one vehicle, then the algorithm tries to constantly move stops from one vehicle to another such that the completion time of longest vehicle route can be further reduced. For example, if you have one vehicle that takes 8 hours to serve all customers, adding another vehicle (and using min-max) might halve the time to serve all customers to 4 hours. However, this usually comes with higher transport costs.

If you want to minimize vehicles first and, second, completion_time, you can also combine different objectives like this:

"objectives" : [
   {
      "type": "min",
      "value": "vehicles"
   },
   {
      "type": "min",
      "value": "completion_time"
   }
]

If you want to balance activities or the number of stops among all employed drivers, you need to specify it as follows:

"objectives" : [
   {
      "type": "min-max",
      "value": "completion_time"
   },
   {
      "type": "min-max",
      "value": "activities"
   }
]
Default "min"
Enum"min""min-max"
Example: "min"
objectives[].​valuestringrequired

The value of the objective function. The objective value transport_time solely considers the time your drivers spend on the road, i.e. transport time. In contrary to transport_time, completion_time also takes waiting times at customer sites into account. The completion_time of a route is defined as the time from starting to ending the route, i.e. the route's transport time, the sum of waiting times plus the sum of activity durations. The completion_time_last_stop, on the other hand, refers to the completion time of the very last order in a tour or, in other words, the completion time without the last section from the last stop to the end of the tour. This is typically used if the orders are to be processed as quickly as possible. The objective value vehicles can only be used along with min and minimizes vehicles.

Default "transport_time"
Enum"completion_time""completion_time_last_stop""transport_time""vehicles""activities"
Example: "vehicles"
cost_matricesArray of objects(CostMatrix)

Specifies your own tranport time and distance matrices.

cost_matrices[].​typestring

type of cost matrix, currently default or google are supported

Enum"default""google"
cost_matrices[].​location_idsArray of strings
cost_matrices[].​dataobject

JSON data of matrix response

cost_matrices[].​profilestring

vehicle profile or empty if catch all fallback

configurationobject(Configuration)

Specifies general configurations.

configuration.​routingobject(Routing)

This contains all routing specific configurations.

configuration.​optimizationobject(Optimization)

This contains all optimization specific configurations.

algorithmobject(Algorithm)Deprecated

Use objectives instead.

algorithm.​problem_typestring
Enum"min""min-max"
algorithm.​objectivestring
Enum"transport_time""completion_time"
curl -X POST -H "Content-Type: application/json"   "https://graphhopper.com/api/1/vrp/optimize?key=api_key"   -d '{
  "vehicles": [
    {
      "vehicle_id": "my_vehicle",
      "start_address": {
        "location_id": "berlin",
        "lon": 13.406,
        "lat": 52.537
      }
    }
  ],
  "services": [
    {
      "id": "hamburg",
      "name": "visit_hamburg",
      "address": {
        "location_id": "hamburg",
        "lon": 9.999,
        "lat": 53.552
      }
    },
    { 
     "id": "munich",
      "name": "visit_munich",
      "address": {
        "location_id": "munich",
        "lon": 11.57,
        "lat": 48.145
      }
    }
  ]}'

Responses

A jobId you can use to retrieve your solution from the server - see solution endpoint.

Headers
X-RateLimit-Limitinteger

Your current daily credit limit.

X-RateLimit-Remaininginteger

Your remaining credits until the reset.

X-RateLimit-Resetinteger

The number of seconds that you have to wait before a reset of the credit count is done.

X-RateLimit-Creditsinteger

The credit costs for this request. Note it could be a decimal and even negative number, e.g. when an async request failed.

Bodyapplication/json
job_idstring(uuid)

UUID. Unique id for your job/request with which you can fetch your solution

Example: "44886560-b584-4da5-b245-768151dacd8f"
Response
application/json
{ "job_id": "44886560-b584-4da5-b245-768151dacd8f" }

Retrieve solution of a route optimization job

Request

Take the job id and fetch the solution for the vehicle routing problem from this URL:

https://graphhopper.com/api/1/vrp/solution/<job_id>?key=<your_key>

You get the job id by sending a vehicle routing problem to the batch mode URL.

Path
jobIdstringrequired

Request solution with jobId

curl -X GET "https://graphhopper.com/api/1/vrp/solution/job_id?key=api_key"

Responses

A response containing the solution

Headers
X-RateLimit-Limitinteger

Your current daily credit limit.

X-RateLimit-Remaininginteger

Your remaining credits until the reset.

X-RateLimit-Resetinteger

The number of seconds that you have to wait before a reset of the credit count is done.

X-RateLimit-Creditsinteger

The credit costs for this request. Note it could be a decimal and even negative number, e.g. when an async request failed.

Bodyapplication/json
copyrightsArray of strings
Example: ["GraphHopper","OpenStreetMap contributors"]
statusstring

Indicates the current status of the job

Enum"waiting_in_queue""processing""finished"
Example: "finished"
waiting_time_in_queueinteger(int64)

Waiting time in ms

Example: 300000
processing_timeinteger(int64)

Processing time in ms. If job is still waiting in queue, processing_time is 0

Example: 900000
solutionobject(Solution)

Only available if status field indicates finished.

solution.​distanceinteger(int32)

Overall distance travelled in meter, i.e. the sum of each route's transport distance

Example: 1200
solution.​transport_timeinteger(int64)

Overall time travelled in seconds, i.e. the sum of each route's transport time.

Example: 12000
solution.​max_operation_timeinteger(int64)

Operation time of longest route in seconds.

Example: 4000
solution.​waiting_timeinteger(int64)

Overall waiting time in seconds.

Example: 200
solution.​service_durationinteger(int64)

Overall service time in seconds.

Example: 1200
solution.​preparation_timeinteger(int64)

Overall preparation time in seconds.

solution.​completion_timeinteger(int64)

Overall completion time in seconds, i.e. the sum of each routes/drivers operation time.

Example: 12000
solution.​no_vehiclesinteger(int32)

Number of employed vehicles.

Example: 10
solution.​no_unassignedinteger(int32)

Number of jobs that could not be assigned to final solution.

Example: 1
solution.​routesArray of objects(Route)

An array of routes

solution.​unassignedobject
solution.​costsinteger(int32)Deprecated
solution.​timeinteger(int64)Deprecated

Use transport_time instead.

Response
application/json
{ "copyrights": [ "GraphHopper", "OpenStreetMap contributors" ], "job_id": "d62fcadd-c84a-4298-90b5-28550125bec5", "status": "finished", "waiting_time_in_queue": 0, "processing_time": 459, "solution": { "costs": 438, "distance": 17994, "time": 4094, "transport_time": 4094, "completion_time": 4172, "max_operation_time": 2465, "waiting_time": 78, "service_duration": 0, "preparation_time": 0, "no_vehicles": 2, "no_unassigned": 0, "routes": [ { "vehicle_id": "vehicle-2", "distance": 10618, "transport_time": 2465, "completion_time": 2465, "waiting_time": 0, "service_duration": 0, "preparation_time": 0, "points": [ { "coordinates": [ [ 13.40608, 52.53701 ], [ 13.40643, 52.53631 ], [ 13.40554, 52.53616 ], [ 13.4054, 52.53608 ], [ 13.40445, 52.53513 ], [ 13.40436, 52.53509 ], [ 13.40428, 52.53508 ], [ 13.40463, 52.53419 ], [ 13.40451, 52.53419 ], [ 13.4034, 52.53401 ], [ 13.403, 52.53359 ], [ 13.40291, 52.53354 ], [ 13.40268, 52.53347 ], [ 13.39888, 52.53259 ], [ 13.39839, 52.53253 ], [ 13.39812, 52.53251 ], [ 13.39616, 52.53243 ], [ 13.39579, 52.5324 ], [ 13.38973, 52.53173 ], [ 13.39163, 52.53025 ], [ 13.38797, 52.52935 ], [ 13.38763, 52.52996 ] ], "type": "LineString" }, { "coordinates": [ [ 13.38763, 52.52996 ], [ 13.38739, 52.53039 ], [ 13.38724, 52.53036 ], [ 13.38464, 52.52929 ], [ 13.38538, 52.52871 ], [ 13.38634, 52.52792 ], [ 13.38638, 52.52779 ], [ 13.38657, 52.52763 ], [ 13.38676, 52.52741 ], [ 13.38698, 52.52713 ], [ 13.38704, 52.52701 ], [ 13.38753, 52.524 ], [ 13.3877, 52.52307 ], [ 13.3878, 52.52282 ], [ 13.38788, 52.52252 ], [ 13.38802, 52.52174 ], [ 13.38519, 52.52009 ], [ 13.38539, 52.5191 ], [ 13.38548, 52.51852 ], [ 13.38042, 52.51819 ], [ 13.38071, 52.5167 ], [ 13.38076, 52.51652 ], [ 13.38084, 52.51634 ], [ 13.3821, 52.51396 ], [ 13.38055, 52.51365 ] ], "type": "LineString" }, { "coordinates": [ [ 13.38055, 52.51365 ], [ 13.38229, 52.514 ], [ 13.38363, 52.51429 ], [ 13.3848, 52.51445 ], [ 13.38504, 52.51358 ], [ 13.39124, 52.51397 ], [ 13.3911, 52.51488 ], [ 13.39303, 52.51499 ], [ 13.39317, 52.5141 ], [ 13.39548, 52.51419 ], [ 13.39571, 52.51421 ] ], "type": "LineString" }, { "coordinates": [ [ 13.39571, 52.51421 ], [ 13.39695, 52.51434 ], [ 13.39674, 52.51523 ], [ 13.39742, 52.51531 ], [ 13.39873, 52.51558 ], [ 13.39846, 52.51599 ], [ 13.39825, 52.51729 ], [ 13.39805, 52.51755 ], [ 13.39892, 52.51761 ], [ 13.39917, 52.51764 ], [ 13.39964, 52.51775 ], [ 13.40009, 52.51791 ], [ 13.40034, 52.51797 ], [ 13.4021, 52.51864 ], [ 13.40288, 52.51896 ], [ 13.40375, 52.51936 ], [ 13.40498, 52.52001 ], [ 13.40463, 52.5203 ], [ 13.40311, 52.52144 ], [ 13.40442, 52.52189 ], [ 13.40448, 52.52192 ], [ 13.40451, 52.52195 ], [ 13.40473, 52.52199 ], [ 13.40504, 52.52208 ], [ 13.40572, 52.52235 ], [ 13.40687, 52.52294 ], [ 13.40693, 52.52299 ], [ 13.40706, 52.52319 ], [ 13.40738, 52.52378 ], [ 13.40787, 52.52443 ], [ 13.4079, 52.52453 ], [ 13.40938, 52.52401 ], [ 13.40962, 52.52398 ], [ 13.41001, 52.52395 ], [ 13.41072, 52.52391 ], [ 13.41215, 52.52389 ], [ 13.41233, 52.52386 ], [ 13.4131, 52.5235 ], [ 13.41288, 52.52333 ], [ 13.41475, 52.52247 ], [ 13.41496, 52.52264 ], [ 13.41523, 52.52251 ], [ 13.41633, 52.52338 ], [ 13.41631, 52.52346 ], [ 13.41654, 52.52364 ], [ 13.41684, 52.52351 ] ], "type": "LineString" }, { "coordinates": [ [ 13.41684, 52.52351 ], [ 13.41654, 52.52364 ], [ 13.41631, 52.52346 ], [ 13.4163, 52.52344 ], [ 13.41587, 52.52363 ], [ 13.41572, 52.5235 ], [ 13.41409, 52.5242 ], [ 13.41454, 52.52461 ], [ 13.41454, 52.52466 ], [ 13.41358, 52.52508 ], [ 13.41366, 52.52514 ], [ 13.41344, 52.52525 ], [ 13.4133, 52.52514 ], [ 13.41316, 52.5252 ], [ 13.41107, 52.52585 ], [ 13.41118, 52.52606 ], [ 13.41118, 52.52616 ], [ 13.41095, 52.52664 ], [ 13.41097, 52.52678 ], [ 13.41084, 52.52706 ], [ 13.41057, 52.52747 ], [ 13.41028, 52.52809 ], [ 13.41032, 52.52821 ], [ 13.4102, 52.52847 ], [ 13.40999, 52.52875 ], [ 13.40984, 52.52905 ], [ 13.40982, 52.52914 ], [ 13.40984, 52.52926 ], [ 13.4104, 52.52998 ], [ 13.4105, 52.53001 ], [ 13.41064, 52.53016 ], [ 13.41082, 52.5303 ], [ 13.41198, 52.53107 ], [ 13.4122, 52.53128 ], [ 13.41232, 52.53143 ], [ 13.41247, 52.53192 ], [ 13.41267, 52.53245 ], [ 13.41275, 52.53259 ], [ 13.41215, 52.5327 ], [ 13.40731, 52.53463 ], [ 13.40608, 52.53701 ] ], "type": "LineString" } ], "activities": [ { "type": "start", "location_id": "berlin", "address": { "location_id": "berlin", "lat": 52.537, "lon": 13.406 }, "end_time": 1554804329, "end_date_time": null, "distance": 0, "driving_time": 0, "preparation_time": 0, "waiting_time": 0, "load_after": [ 0 ] }, { "type": "pickupShipment", "id": "7fe77504-7df8-4497-843c-02d70b6490ce", "location_id": "13.387613_52.529961", "address": { "location_id": "13.387613_52.529961", "lat": 52.529961, "lon": 13.387613 }, "arr_time": 1554804789, "arr_date_time": null, "end_time": 1554804789, "end_date_time": null, "waiting_time": 0, "distance": 2012, "driving_time": 460, "preparation_time": 0, "load_before": [ 0 ], "load_after": [ 1 ] }, { "type": "deliverShipment", "id": "7fe77504-7df8-4497-843c-02d70b6490ce", "location_id": "13.380575_52.513614", "address": { "location_id": "13.380575_52.513614", "lat": 52.513614, "lon": 13.380575 }, "arr_time": 1554805344, "arr_date_time": null, "end_time": 1554805344, "end_date_time": null, "waiting_time": 0, "distance": 4560, "driving_time": 1015, "preparation_time": 0, "load_before": [ 1 ], "load_after": [ 0 ] }, { "type": "service", "id": "s-4", "location_id": "13.395767_52.514038", "address": { "location_id": "13.395767_52.514038", "lat": 52.514038, "lon": 13.395767 }, "arr_time": 1554805632, "arr_date_time": null, "end_time": 1554805632, "end_date_time": null, "waiting_time": 0, "distance": 5887, "driving_time": 1303, "preparation_time": 0, "load_before": [ 0 ], "load_after": [ 1 ] }, { "type": "service", "id": "s-3", "location_id": "13.416882_52.523543", "address": { "location_id": "13.416882_52.523543", "lat": 52.523543, "lon": 13.416882 }, "arr_time": 1554806253, "arr_date_time": null, "end_time": 1554806253, "end_date_time": null, "waiting_time": 0, "distance": 8486, "driving_time": 1924, "preparation_time": 0, "load_before": [ 1 ], "load_after": [ 2 ] }, { "type": "end", "location_id": "berlin", "address": { "location_id": "berlin", "lat": 52.537, "lon": 13.406 }, "arr_time": 1554806794, "arr_date_time": null, "distance": 10618, "driving_time": 2465, "preparation_time": 0, "waiting_time": 0, "load_before": [ 2 ] } ] }, { "vehicle_id": "vehicle-1", "distance": 7376, "transport_time": 1629, "completion_time": 1707, "waiting_time": 78, "service_duration": 0, "preparation_time": 0, "points": [ { "coordinates": [ [ 13.40608, 52.53701 ], [ 13.40674, 52.53571 ], [ 13.40433, 52.53313 ], [ 13.40271, 52.53149 ], [ 13.40246, 52.53121 ], [ 13.40148, 52.52999 ], [ 13.40128, 52.52993 ], [ 13.40118, 52.52988 ], [ 13.40133, 52.5296 ], [ 13.40138, 52.52951 ], [ 13.40167, 52.52914 ], [ 13.40188, 52.52895 ], [ 13.398, 52.52885 ], [ 13.39289, 52.52748 ], [ 13.39354, 52.5264 ], [ 13.39358, 52.52628 ], [ 13.39324, 52.52575 ], [ 13.39334, 52.52573 ], [ 13.39339, 52.52584 ] ], "type": "LineString" }, { "coordinates": [ [ 13.39339, 52.52584 ], [ 13.3934, 52.52599 ], [ 13.39358, 52.52628 ], [ 13.39354, 52.5264 ], [ 13.39242, 52.52823 ], [ 13.39381, 52.52852 ], [ 13.38973, 52.53173 ], [ 13.38717, 52.5315 ], [ 13.38678, 52.5315 ], [ 13.38641, 52.53147 ], [ 13.38617, 52.53143 ], [ 13.38607, 52.53155 ], [ 13.38526, 52.53225 ], [ 13.38501, 52.53252 ], [ 13.38316, 52.53418 ], [ 13.38179, 52.5355 ], [ 13.38084, 52.53523 ], [ 13.38081, 52.53531 ], [ 13.3795, 52.53677 ], [ 13.37941, 52.53682 ], [ 13.37935, 52.53683 ], [ 13.37919, 52.53682 ], [ 13.37617, 52.5361 ], [ 13.37502, 52.53698 ], [ 13.37584, 52.53734 ] ], "type": "LineString" }, { "coordinates": [ [ 13.37584, 52.53734 ], [ 13.37566, 52.53726 ], [ 13.37515, 52.53763 ], [ 13.37644, 52.53841 ], [ 13.37807, 52.53935 ], [ 13.37946, 52.5402 ], [ 13.3796, 52.54019 ], [ 13.37984, 52.54021 ], [ 13.37988, 52.54012 ], [ 13.38062, 52.53936 ], [ 13.38169, 52.53832 ], [ 13.38236, 52.5377 ], [ 13.38363, 52.53661 ], [ 13.38492, 52.53555 ], [ 13.38613, 52.53447 ], [ 13.38757, 52.53338 ], [ 13.38791, 52.53354 ], [ 13.38812, 52.53368 ], [ 13.38833, 52.53392 ], [ 13.38977, 52.53518 ], [ 13.39003, 52.53539 ], [ 13.39256, 52.53701 ], [ 13.39316, 52.53739 ], [ 13.39327, 52.53744 ], [ 13.3936, 52.53757 ], [ 13.40155, 52.53982 ], [ 13.40357, 52.53715 ], [ 13.40372, 52.53719 ], [ 13.40465, 52.53727 ], [ 13.4048, 52.53726 ], [ 13.4059, 52.53736 ], [ 13.40608, 52.53701 ] ], "type": "LineString" } ], "activities": [ { "type": "start", "location_id": "berlin", "address": { "location_id": "berlin", "lat": 52.537, "lon": 13.406 }, "end_time": 1554804329, "end_date_time": null, "distance": 0, "driving_time": 0, "preparation_time": 0, "waiting_time": 0, "load_after": [ 0 ] }, { "type": "service", "id": "s-2", "location_id": "13.393364_52.525851", "address": { "location_id": "13.393364_52.525851", "lat": 52.525851, "lon": 13.393364 }, "arr_time": 1554804743, "arr_date_time": null, "end_time": 1554804743, "end_date_time": null, "waiting_time": 0, "distance": 1884, "driving_time": 414, "preparation_time": 0, "load_before": [ 0 ], "load_after": [ 1 ] }, { "type": "service", "id": "s-1", "location_id": "13.375854_52.537338", "address": { "location_id": "13.375854_52.537338", "lat": 52.537338, "lon": 13.375854 }, "arr_time": 1554805251, "arr_date_time": null, "end_time": 1554805329, "end_date_time": null, "waiting_time": 78, "distance": 4205, "driving_time": 922, "preparation_time": 0, "load_before": [ 1 ], "load_after": [ 2 ] }, { "type": "end", "location_id": "berlin", "address": { "location_id": "berlin", "lat": 52.537, "lon": 13.406 }, "arr_time": 1554806036, "arr_date_time": null, "distance": 7376, "driving_time": 1629, "preparation_time": 0, "waiting_time": 0, "load_before": [ 2 ] } ] } ], "unassigned": { "services": [], "shipments": [], "breaks": [], "details": [] } } }

Routing

The Routing API calculates the best path connecting two or more points, where the meaning of ''best'' depends on the vehicle profile and use case. Besides path coordinates it can return turn-by-turn instructions, elevation, path details and other useful information about the route.

Use our API Explorer to explore the Routing API.

Operations

Matrices

Operations

Geocoding

Geocoding describes the process of transforming an textual address representation to a coordinate (latitude,longitude). For example the conversion from Berlin to 52.5170365,13.3888599.

Reverse geocoding converts a coordinate to a textual address representation or place name. Find out more about Geocoding itself on Wikipedia.

Operations

Isochrones

An isochrone of a location is ''a line connecting points at which a vehicle arrives at the same time'', see Wikipedia. With the same API you can also calculate isodistances, just use the parameter distance_limit instead of time_limit`.

Some possible areas in which this API may be useful to you:

  • real estate analysis
  • realtors
  • vehicle scheduling
  • geomarketing
  • reach of electric vehicles
  • transport planning
  • logistics (distribution and retail network planning)

See the clients section in the main documentation, and our API explorer.

Operations

Map Matching

You can snap measured GPS points typically as GPX files to a digital road network to e.g. clean data or attach certain data like elevation or turn instructions to it.

See the clients section in the main documentation, and our API explorer.

The cost for one request depends on the number of GPS location and is documented here.

One request should not exceed the Map Matching API location limit depending on the package, see the pricing in our dashboard.

Operations

Clustering

It solves the “capacity clustering problem” by assigning a set of customers to a given number of distinct groups (called clusters). The API “clusters” by minimizing the total distance from each individual customer to its designated group median. It can also consider minimum and maximum capacity restrictions for each group.

Clustering can be used in many practical applications. For example, it can help to plan territories, i.e. territory optimization for field teams with large territories for field workers, or to solve large vehicle routing problems (VRP).

Try Clustering in our API Explorer!

The idea is to divide a certain number of customers, a pre-specified number of clusters. As already written above, a distribution is sought that minimizes the total cost (e.g. distance or time or a function of distance and time). We currently support two approaches.

  1. You can simply define a certain number of clusters via configuration ("clustering" with empty set of "clusters") and additionally how many customers should be in such a cluster. This is defined by an upper and lower limit ("min_quantity" and "max_quantity). The algorithm then searches for suitable clusters and divides the customers into these clusters.

  2. You can explicitly define clusters via "clusters". In this way, each individual cluster can be defined. This approach not only allows each cluster to have its own capacity upper and lower bound, but each cluster can also be assigned a fixed cluster center. In contrast to 1. the algorithm then does not search for a suitable center, but assigns the customers given the fixed centers to each cluster. Note that if you define clusters explicitly, any configuration of "clustering" will be overwritten by these explicit clusters.

Operations

Custom Model

A custom model allows you to modify the default routing behavior of a vehicle profile by specifying a set of rules in JSON language. There are three JSON properties to change a profile: priority, speed and distance_influence that are described in great detail in the next sections and you can get a quick overview in this example-driven blog post.

But first we will give an introductory example for each of these JSON properties. Let's start with speed:

{
  "speed": [{
    "if": "road_class == MOTORWAY",
    "limit_to": "90"
  }]
}

As you might have already guessed this limits the speed on motorways to 90km/h. Changing the speed will of course change the travel time, but at the same time this makes other road classes more likely as well, so you can use this model to avoid motorways.

You can immediately try this out in the Browser on GraphHopper Maps. GraphHopper Maps offers an interactive text editor to comfortably enter custom models. You can open it by pressing the "custom" button. It will check the syntax of your custom model and mark errors in red. You can press Ctrl+Space or Alt+Enter to retrieve auto-complete suggestions. Pressing Ctrl+Enter will send a routing request for the custom model you entered. To disable the custom model you click the "custom" button again.

In the second example we show how to avoid certain road classes without changing the travel time:

{
  "priority": [{
    "if": "road_class == LIVING_STREET || road_class == RESIDENTIAL || road_class == UNCLASSIFIED",
    "multiply_by": "0.1"
  }]
}

This example avoids certain smaller streets. View it in GraphHopper Maps.

The third example shows how to prefer shortest paths:

{
  "distance_influence": 200
}

View this example in GraphHopper Maps.

There is a fourth JSON property areas that allows you to define areas that can then be used in the if or else_if conditions for speed and priority. Please read more about this and the other properties below and try some examples in GraphHopper Maps with the help of this blog post.

Custom Profiles

You can create routing profiles that are customized to your needs. You can take advantage of all the modelling options described in the Custom Model section and use the created custom profile (prefix cp_) with our Routing, Matrix and Route Optimization APIs.

Important notes

  • Each custom profile is limited to a geographic area boundary. Within this boundary there is maximum flexibility for adjusting the profile and you can expect fast response times.
  • Currently this feature is only available to selected customers and customers with a premium package. If you are interested please contact us.
  • This feature is currently in beta status. It is fully functional, but the API might change in the future. Changes will of course be announced well in advance.
  • You can use the following profiles as base profile: car, bike, foot and ecargobike. Contact us if you have different requirements. Motor vehicles can be emulated like done for truck in this post.

A curl example:

curl -X POST -H "Content-Type: application/json" "https://graphhopper.com/api/1/profiles?key=YOUR_KEY" -d '{"bounds":{"bbox":[11.45462,48.00954,11.77322,48.2076]},"custom_model":{"priority":[{"if":"road_class == MOTORWAY","multiply_by":"0"}]},"profile":"car"}'

If you plan to tweak your custom_model frequently it is recommended to initially use the Routing API where a different custom model can be specified in every request. Or use GraphHopper Maps and click the gear button.

Creating custom profiles using the API Explorer

Besides using the /profiles endpoint directly you can also create custom profiles from our API explorer.

The API Explorer's Profiles Section

  1. Visit the API explorer.
  2. Set your API key with the "API key" button. If an error occurs we might have to activate custom profiles for your account before you can continue. Contact us.
  3. Now copy and paste the JSON to create a custom profile into the input window. To get started you can use the already pre-filled example, which will create a custom profile that excludes motorways and is limited to the Munich area.
  4. Click "Send". This creates a custom profile. Copy the returned id from the output window (it starts with cp_).
  5. To try this profile out you now change the drop down to "Optimization API", pick the first example and replace "car" in "profile": "car" (vehicle_types section) with the profile id and click "Send":

The API Explorer's Optimization Section

You should now see that the solution no longer uses motorways. Keep in mind that this is a simple example. The custom model language is a lot more powerful than this. Make sure you read the Custom Model section to learn about all the details.

Note that you can use the profile id just as well for the /matrix or /route endpoint. E.g. select "Routing API" and use the profile id in the request:

The API Explorer's Routing Section

Operations