# Driver Assignment API

## Introduction

The Driver Assignment API assigns best available drivers to open tasks based on specific constraints. It helps optimize the resource allocation in real-time, ensuring efficient service to ride-hailing passengers and any other service appointments.

### Key Features

* **Smart Order-to-Driver Matching**: Assign drivers intelligently based on task requirements, vehicle specifications, and other custom business rules.
* **Flexible Cost Models**: Optimize driver assignments with multiple cost options - time-based, distance-based, or straight-line calculations.
* **Advanced Filtering**: Refine driver selection with distance and duration constraints to ensure optimal efficiency.
* **Back-to-back orders**: Allow drivers to efficiently complete consecutive trips without delays.
* **Alternate Assignments**: Automatically suggests backup drivers for each order to ensure service continuity.
* **Prioritized Assignments**: Allows ranking orders and vehicles by priority so that high-value orders and preferred vehicles are matched first.

The Driver Assignment API offers both synchronous and asynchronous methods for requesting optimal driver assignments. Let’s look at each method in detail.

## Synchronous Driver Assignment Method

### Create a request

The Driver Assignment API’s synchronous method caters to quick, near real-time assignment requirements like in case of ride hailing applications. It is best suited for situations when drivers and orders are spread in a relatively smaller area. The service requires the pickup and drop off locations of the orders and the details of available vehicles to fulfill the orders. A vehicle with an ongoing trip can also be configured by specifying the waypoints remaining on the current trip. The distance or duration based filters and custom vehicle preferences for each order can also be configured to establish rules identifying the most favoured vehicle for fulfilling each order.

POST

https://api.nextbillion.io/optimization/driver-assignment/v1?key={your_api_key}

#### Request Parameters

| Name | Required | Format and Usage | Description |
|------|----------|------------------|-------------|
| `key` | Yes | Type: `string`<br>Format: `32 character alphanumeric string`<br>Example: `key=API_KEY`<br> | A key is a unique identifier that is required to authenticate a request to the API. |

#### Request Body

| Field | Type | Description |
|-------|------|-------------|
| `orders` | array of object | Collects the details of open orders to be fulfilled. Each object represents one order. All requests must include `orders` as a mandatory input. A maximum of 200 orders is allowed per request. |
| `orders[].id` | string | Specify a unique ID for the order. |
| `orders[].pickup` | object | Specify the location coordinates of the pickup location of the order. This input is mandatory for each order. |
| `orders[].pickup.lat` | number | Latitude of the pickup location. |
| `orders[].pickup.lng` | number | Longitude of the pickup location. |
| `orders[].dropoffs` | array of object | Use this parameter to specify the location coordinates of the destination of the trip or the intermediate stops to be completed before it.<br>Please note<br>*   The last location provided is treated as the destination of the trip.<br>*   `dropoffs` is mandatory when `dropoff_details` is set to **true**. |
| `orders[].dropoffs[].lat` | number | Latitude of the stop location. |
| `orders[].dropoffs[].lng` | number | Longitude of the stop location. |
| `orders[].service_time` | integer | Specify the service time, in seconds, for the order. Service time is the duration that the driver is likely to wait at the pickup location after arriving. The impact of the service time is realized in the ETA for the "dropoff" type step. |
| `orders[].vehicle_preferences` | object | Define custom preferences for task assignment based on vehicle's attributes. If multiple criteria are provided, they are evaluated using an AND condition—meaning all specified criteria must be met individually for a vehicle to be considered.<br>For example, if `required_all_of_attributes`, `required_any_of_attributes`, and `exclude_all_of_attributes` are all provided, an eligible vehicle must satisfy the following to be considered for assignments:<br>1.  Meet all conditions specified in `required_all_of_attributes`.<br>2.  Meet at least one of the conditions listed in `required_any_of_attributes`.<br>3.  Not meet any conditions mentioned in `exclude_all_of_attributes`.<br>Consequently, a vehicle which does not have any `attributes` defined can't be assigned to an order which has `vehicle_preferences` configured. |
| `orders[].vehicle_preferences.required_all_of_attributes` | array of object | An array of objects to add mandatory requirements for the order. A vehicle must **meet** **all conditions** specified here to be considered for assignment. Each object represents a single condition. Please note that a maximum of 10 conditions can be added here for a given order. |
| `orders[].vehicle_preferences.required_all_of_attributes[].attribute` | string | Specify the name of the attribute. The `attribute` is compared to the keys (of each `key:value` pair) in `vehicles.attributes` during evaluation. |
| `orders[].vehicle_preferences.required_all_of_attributes[].value` | string | Specify the desired value of the attribute to be applied for this order. `value` provided here is compared to the values (of each `key:value` pair) in `vehicles.attributes` during evaluation. |
| `orders[].vehicle_preferences.required_all_of_attributes[].operator` | string | Specify the operator to denote the relation between `attribute` and the `value` specified above. The `attribute` , `operator` and `value` together constitute the condition that a vehicle must meet to be eligible for assignment. Currently, we support following operators currently:<br>*   Equal to (==)<br>*   Less than (<)<br>*   Less tha equal to (<=)<br>*   Greater than (>)<br>*   Greater than equal to (>=)<br>*   Contains (contains)<br>Please note that when using "contains" operator only one `value` can be specified and the corresponding `attribute` must contain multiple values when defined for a vehicle. |
| `orders[].vehicle_preferences.required_any_of_attributes` | array of object | An array of objects to add optional requirements for the order. A vehicle must **meet** **at least one of the conditions** specified here to be considered for assignment. Each object represents a single condition. Please note that a maximum of 10 conditions can be added here for a given order. |
| `orders[].vehicle_preferences.required_any_of_attributes[].attribute` | string | Specify the name of the attribute. The `attribute` is compared to the keys (of each `key:value` pair) in `vehicles.attributes` during evaluation. |
| `orders[].vehicle_preferences.required_any_of_attributes[].value` | string | Specify the desired value of the attribute to be applied for this order. `value` provided here is compared to the values (of each `key:value` pair) in `vehicles.attributes` during evaluation. |
| `orders[].vehicle_preferences.required_any_of_attributes[].operator` | string | Specify the operator to denote the relation between `attribute` and the `value` specified above. The `attribute` , `operator` and `value` together constitute the condition that a vehicle must meet to be eligible for assignment. Currently, we support following operators currently:<br>*   Equal to (==)<br>*   Less than (<)<br>*   Less tha equal to (<=)<br>*   Greater than (>)<br>*   Greater than equal to (>=)<br>*   Contains (contains)<br>Please note that when using "contains" operator only one `value` can be specified and the corresponding `attribute` must contain multiple values when defined for a vehicle. |
| `orders[].vehicle_preferences.exclude_all_of_attributes` | array of object | An array of objects to add exclusion requirements for the order. A vehicle must **not meet any of the conditions** specified here to be considered for assignment. Each object represents a single condition. Please note that a maximum of 10 conditions can be added here for a given order. |
| `orders[].vehicle_preferences.exclude_all_of_attributes[].attribute` | string | Specify the name of the attribute. The `attribute` is compared to the keys (of each `key:value` pair) in `vehicles.attributes` during evaluation. |
| `orders[].vehicle_preferences.exclude_all_of_attributes[].value` | string | Specify the desired value of the attribute to be applied for this order. `value` provided here is compared to the values (of each `key:value` pair) in `vehicles.attributes` during evaluation. |
| `orders[].vehicle_preferences.exclude_all_of_attributes[].operator` | string | Specify the operator to denote the relation between `attribute` and the `value` specified above. The `attribute` , `operator` and `value` together constitute the condition that a vehicle must meet to be eligible for assignment. Currently, we support following operators currently:<br>*   Equal to (==)<br>*   Less than (<)<br>*   Less tha equal to (<=)<br>*   Greater than (>)<br>*   Greater than equal to (>=)<br>*   Contains (contains)<br>Please note that when using "contains" operator only one `value` can be specified and the corresponding `attribute` must contain multiple values when defined for a vehicle. |
| `orders[].priority` | integer | Specify the priority for this order. A higher value indicates a higher priority. When specified, it will override any priority score deduced from `order_attribute_priority_mappings` for this order. Valid values are \[1, 10\] and default is 0. |
| `orders[].attributes` | object | Specify custom attributes for the orders. Each attribute should be created as a `key:value` pair. The **keys** provided can be used in `options.order_attribute_priority_mappings` to assign a custom priority for this order based on its attributes.<br>The maximum number of key:value pairs that can be specified under `attributes` for a given order, is limited to 30. |
| `vehicles` | array of object | Collects the details of vehicles available to fulfill the orders. Each object represents one vehicle. All requests must include `vehicles` as a mandatory input. A maximum of 100 vehicles is allowed per request. |
| `vehicles[].id` | string | Specify a unique ID for the vehicle. |
| `vehicles[].location` | object | Specify the location coordinates where the vehicle is currently located. This input is mandatory for each vehicle. |
| `vehicles[].location.lat` | number | Latitude of the vehicle's current location. |
| `vehicles[].location.lng` | number | Longitude of the vehicle's current location. |
| `vehicles[].attributes` | object | Specify custom attributes for the vehicle. Each attribute should be created as a `key:value` pair. These attributes can be used in the `orders.vehicle_preferences` input to refine the search of vehicles for each order.<br>The maximum number of key:value pairs that can be specified under `attributes` for a given vehicle, is limited to 30. |
| `vehicles[].remaining_waypoints` | array of object | An array of objects to collect the location coordinates of the stops remaining on an ongoing trip of the vehicle. The service can assign new orders to the vehicle if they are cost-effective. Once a new order is assigned, the vehicle must complete all the steps in the ongoing trip before proceeding to pickup the newly assigned order.<br>Please note that a maximum of 10 waypoints can be specified for a given vehicle. |
| `vehicles[].remaining_waypoints[].lat` | number | Specify the latitude of the location. |
| `vehicles[].remaining_waypoints[].lng` | number | Specify the longitude of the location. |
| `vehicles[].priority` | integer | Specify the priority for this vehicle. A higher value indicates a higher priority. When specified, it will override any priority score deduced from `vehicle_attribute_priority_mappings` for this vehicle. Valid values are \[1, 10\] and default is 0. |
| `filter` | object | Specify the filtering criterion for the vehicles with respect to each order's location. `filter` is a mandatory input for all requests. |
| `filter.radius` | number | Specify a radius, in meters, which will be used to filter out ineligible vehicles for each order. The pickup location of an order will act as the center of the circle when identifying eligible vehicles. Valid values for `radius` are \[1, 10000\]. |
| `filter.pickup_eta` | integer | Specify a duration, in seconds, which will be used to filter out ineligible vehicles for each order. Any vehicle which would take more time than specified here, to reach the pickup location of a given order, will be ruled out for assignment for that particular order. Valid values for `pickup_eta` are \[1, 3600\]. |
| `filter.driving_distance` | number | Defines a `driving_distance` filter, in meters. If a vehicle needs to drive further than this distance to reach a pickup location, it will not be assigned to that order. Valid range of values for this filter is \[1, 10000\]. |
| `options` | object | Configure the assignment constraints and response settings. |
| `options.travel_cost` | string | Choose a travel cost that will be used by the service for assigning vehicles efficiently from a set of qualifying ones. |
| `options.dropoff_details` | boolean | When **true**, the service returns the drop-off steps for each trip and related details in the response. Defaults to **false**. |
| `options.order_attribute_priority_mappings` | array of object | Collection of rules for assigning custom priority to orders based on their attributes. In case an order satisfies more than one rule, the highest priority score from all the rules satisfied, would be the effective priority score for such an order. |
| `options.order_attribute_priority_mappings[].attribute` | string | Specify the name of the attribute. The `attribute` is compared to the keys (of each `key:value` pair) in `orders.attributes` during evaluation. |
| `options.order_attribute_priority_mappings[].value` | string | Specify the desired value of the attribute to be applied for this order. `value` provided here is compared to the values (of each `key:value` pair) in `orders.attributes` during evaluation. |
| `options.order_attribute_priority_mappings[].operator` | string | Specify the operator to denote the relation between `attribute` and the `value` specified above. The `attribute` , `operator` and `value` together constitute the condition that an order must meet to assume the specified priority. We support the following operators currently:<br>*   Equal to (==)<br>*   Less than (<)<br>*   Less tha equal to (<=)<br>*   Greater than (>)<br>*   Greater than equal to (>=)<br>*   Contains (contains)<br>Please note that when using "contains" operator only one `value` can be specified and the corresponding `attribute` must contain multiple values when defined for an order. |
| `options.order_attribute_priority_mappings[].priority` | string | Specify the priority score that should be assigned when an order qualifies the criteria specified above. A higher value indicates a higher priority. Valid values are \[1,10\]. |
| `options.vehicle_attribute_priority_mappings` | array of object | Collection of rules for assigning custom priority to vehicles based on their attributes. In case a vehicle satisfies more than one rule, the highest priority score from all the rules satisfied, would be the effective priority score for such a vehicle. |
| `options.vehicle_attribute_priority_mappings[].attribute` | string | Specify the name of the attribute. The `attribute` is compared to the keys (of each `key:value` pair) in `vehicles.attributes` during evaluation. |
| `options.vehicle_attribute_priority_mappings[].value` | string | Specify the desired value of the attribute to be applied for this vehicle. `value` provided here is compared to the values (of each `key:value` pair) in `vehicles.attributes` during evaluation. |
| `options.vehicle_attribute_priority_mappings[].operator` | string | Specify the operator to denote the relation between `attribute` and the `value` specified above. The `attribute` , `operator` and `value` together constitute the condition that a vehicle must meet to assume the specified priority. We support the following operators currently:<br>*   Equal to (==)<br>*   Less than (<)<br>*   Less tha equal to (<=)<br>*   Greater than (>)<br>*   Greater than equal to (>=)<br>*   Contains (contains)<br>Please note that when using "contains" operator only one `value` can be specified and the corresponding `attribute` must contain multiple values when defined for a vehicle. |
| `options.vehicle_attribute_priority_mappings[].priority` | string | Specify the priority score that should be assigned when a vehicle qualifies the criteria specified above. A higher value indicates a higher priority. Valid values are \[1,10\]. |
| `options.alternate_assignments` | integer | Specify the maximum number of potential, alternate vehicle assignments to be returned for each order, apart from the vehicle which was assigned as recommended. Please note that:<br>*   The maximum number of alternate assignments that can be requested are 3.<br>*   It is not necessary that the service will return the specified number of alternate assignments for each order. The number of alternate assignments returned will depend on the number of vehicles provided in the input.<br>*   Order which could not be assigned to any vehicles due to their `filter` or attribute matching criteria will not be eligible for alternate assignments as well. |
| `options.routing` | object | Specify routing preferences for route calculations and identifications. |
| `options.routing.mode` | string | Specify the traveling mode to be used for identifying routes, ETAs and distances. |

### Response Schema

The Driver Assignment API response includes the details of assignments along with the sequence in which the ongoing steps and pickups can be completed. The orders which remained unassigned and the vehicles which were not assigned to any orders are also returned.
The complete details of a trip along with drop off steps can be accessed by setting the `dropoff_details` parameter to true in the input request.

| Field | Type | Description |
|-------|------|-------------|
| `status` | integer | An integer indicating the HTTP response code. See the [API Error Handling](https://docs.nextbillion.ai/optimization/driver-assignment-api#api-error-handling) section below for more information. |
| `message` | string | Displays indicative error message in case of a failed request or operation. Please note that this parameter is not returned in the response in case of a successful request. |
| `result` | object | An object containing the details of the assignments. |
| `result.trips` | array of object | An collection of objects returning the trip details for each vehicle which was assigned to an order. Each object corresponds to one vehicle. |
| `result.trips[].trip_id` | string | Returns a unique trip ID. |
| `result.trips[].vehicle` | object | Returns the details of the vehicle, assigned order and the trip steps. |
| `result.trips[].vehicle.id` | string | Returns the ID of the vehicle. |
| `result.trips[].vehicle.steps` | object | A collection of objects returning the sequence of steps that the vehicle needs to perform for a trip. |
| `result.trips[].vehicle.steps.type` | string | Returns the type of the step. Currently, it can take following values:<br>*   **pickup:** Indicates the pickup step for an order<br>*   **dropoff:** Indicates the dropoff step for an order. It is returned only if `dropoff_details` was **true** in the input request.<br>*   **ongoing:** Indicates a step that the vehicle needs to complete on its current trip. This is returned in the response only when `remaining_waypoints` input was provided for the given vehicle.<br>*   **intermediate_waypoint:** Indicates an intermediate stop that the vehicle needs to complete in case multiple dropoffs are provided in the input. |
| `result.trips[].vehicle.steps.order_id` | string | Returns the ID of the order. In case the step type is **ongoing**, an empty string is returned. |
| `result.trips[].vehicle.steps.location.lat` | number | Specify the latitude of the location. |
| `result.trips[].vehicle.steps.location.lng` | number | Specify the longitude of the location. |
| `result.trips[].vehicle.steps.distance` | integer | Returns the driving distance, in meters, to the step's location from previous step's location. For the first step of a trip, `distance` indicates the driving distance from `vehicle_current_location` to the step's location. |
| `result.trips[].vehicle.steps.eta` | integer | Returns the driving duration, in seconds, to the step's location from previous step's location. For the first step of a trip, `eta` indicates the driving duration from `vehicle_current_location` to the step's location. |
| `result.trips[].vehicle.vehicle_current_location.lat` | number | Specify the latitude of the location. |
| `result.trips[].vehicle.vehicle_current_location.lng` | number | Specify the longitude of the location. |
| `result.unassigned_orders` | array of object | A collection of objects listing the details of orders which remained unassigned. Each object represents a single order. A `null` value is returned if there are no unassigned orders. |
| `result.unassigned_orders[].order_id` | string | Returns the ID of the order which remained unassigned. |
| `result.unassigned_orders[].unassigned_reason` | string | Returns the most probable reason due to which the order remained unassigned. |
| `result.available_vehicles` | array of string | A collection of vehicles IDs that were not assigned to any orders. A `null` value is returned if there are no vehicles without an order assignment. |
| `result.alternate_assignments` | array of object | An array of objects containing the details of the potential, alternate vehicle assignments for the orders in the input. This attribute will not be returned in the response if the `alternate_assignments` was not provided in the input. Each object represents alternate assignments for a single order. |
| `result.alternate_assignments[].order_id` | string | Returns the order ID associated with the alternate assignments. |
| `result.alternate_assignments[].assignments` | array of object | An array of objects containing the details of the alternate vehicle assignments. Each object represents an alternate vehicle assignment. |
| `result.alternate_assignments[].assignments[].vehicle_id` | string | Returns the vehicle ID which could potentially be assigned to the given order. |
| `result.alternate_assignments[].assignments[].pickup_eta` | integer | Returns the ETA to the order's pickup location for the given vehicle. |

### Synchronous Driver Assignment API Example

#### Sample Request

```bash
curl --location 'https://api.nextbillion.io/optimization/driver-assignment/v1?key=<your_api_key>' \
--header 'Content-Type: application/json; charset=utf-8' \
--data '{
    "filter": {
        "radius": 5000
    },
    "options": {
        "dropoff_details": true
    },
    "orders": [
        {
            "id": "Order_1",
            "pickup": {
                "lat": 34.05804700,
                "lng": -118.31405300
            },
            "dropoffs": [
                {
                    "lat": 33.98911618,
                    "lng": -118.25476129
                }
            ],
            "vehicle_preferences": {
                "required_all_of_attributes": [
                    {
                        "attribute": "Driver_rating",
                        "operator": ">",
                        "value": "4.0"
                    },
                    {
                        "attribute": "trip_types",
                        "operator": "contains",
                        "value": "premium"
                    }
                ],
                "required_any_of_attributes": [
                    {
                        "attribute": "payments",
                        "operator": "contains",
                        "value": "cards"
                    },
                    {
                        "attribute": "payments",
                        "operator": "contains",
                        "value": "cash"
                    }
                ]
            }
        }
    ],
    "vehicles": [
        {
            "id": "Vehicle_1",
            "attributes": {
                "seats": "4",
                "Driver_rating": "4.1",
                "trip_types": "premium",
                "payments": "cash, cards"
            },
            "remaining_waypoints": [
                {
                    "lat": 34.06393888,
                    "lng": -118.28705851
                }
            ],
            "location": {
                "lat": 34.08366592,
                "lng": -118.31028386
            }
        }
    ]
}'
```


#### Sample Response

```json
{
   "status": 200,
   "result": {
       "trips": [
           {
               "trip_id": "b6f24491-6a38-42fe-a448-987e5b8954fb",
               "vehicle": {
                   "id": "Vehicle_1",
                   "steps": [
                       {
                           "type": "ongoing",
                           "order_id": "",
                           "location": {
                               "lat": 34.06393888,
                               "lng": -118.28705851
                           },
                           "distance": 4523,
                           "eta": 461
                       },
                       {
                           "type": "pickup",
                           "order_id": "Order_1",
                           "location": {
                               "lat": 34.058047,
                               "lng": -118.314053
                           },
                           "distance": 7707,
                           "eta": 897
                       },
                       {
                           "type": "dropoff",
                           "order_id": "Order_1",
                           "location": {
                               "lat": 33.98911618,
                               "lng": -118.25476129
                           },
                           "distance": 22330,
                           "eta": 1972
                       }
                   ],
                   "vehicle_current_location": {
                       "lat": 34.08366592,
                       "lng": -118.31028386
                   }
               }
           }
       ],
       "unassigned_orders": null,
       "available_vehicles": null
   }
}
```

## Asynchronous Driver Assignment Method

The Asynchronous version Driver Assignment API returns a unique solution ID upon submitting a valid input request. The solution ID can then be used to retrieve the assignment solution anytime. The async method also offers enhanced `filter` limits for searching and matching orders to available drivers spread over a large region. Use the GET method to retrieve the solution. All the details are covered in the following sections.

### Submit a request

Use the following endpoint to submit an asynchronous driver assignment request

POST

https://api.nextbillion.io/optimization/driver-assignment/v1/async?key={your_api_key}

#### Request Parameters

| Name | Required | Format and Usage | Description |
|------|----------|------------------|-------------|
| `key` | Yes | Type: `string`<br>Format: `32 character alphanumeric string`<br>Example: `key=API_KEY`<br> | A key is a unique identifier that is required to authenticate a request to the API. |

#### Request Body

| Field | Type | Description |
|-------|------|-------------|
| `orders` | array of object | Collects the details of open orders to be fulfilled. Each object represents one order. All requests must include `orders` as a mandatory input. A maximum of 200 orders is allowed per request. |
| `orders[].id` | string | Specify a unique ID for the order. |
| `orders[].pickup` | object | Specify the location coordinates of the pickup location of the order. This input is mandatory for each order. |
| `orders[].pickup.lat` | number | Latitude of the pickup location. |
| `orders[].pickup.lng` | number | Longitude of the pickup location. |
| `orders[].dropoffs` | array of object | Use this parameter to specify the location coordinates of the destination of the trip or the intermediate stops to be completed before it.<br>Please note<br>*   The last location provided is treated as the destination of the trip.<br>*   `dropoffs` is mandatory when `dropoff_details` is set to **true**. |
| `orders[].dropoffs[].lat` | number | Latitude of the stop location. |
| `orders[].dropoffs[].lng` | number | Longitude of the stop location. |
| `orders[].service_time` | integer | Specify the service time, in seconds, for the order. Service time is the duration that the driver is likely to wait at the pickup location after arriving. The impact of the service time is realized in the ETA for the "dropoff" type step. |
| `orders[].vehicle_preferences` | object | Define custom preferences for task assignment based on vehicle's attributes. If multiple criteria are provided, they are evaluated using an AND condition—meaning all specified criteria must be met individually for a vehicle to be considered.<br>For example, if `required_all_of_attributes`, `required_any_of_attributes`, and `exclude_all_of_attributes` are all provided, an eligible vehicle must satisfy the following to be considered for assignments:<br>1.  Meet all conditions specified in `required_all_of_attributes`.<br>2.  Meet at least one of the conditions listed in `required_any_of_attributes`.<br>3.  Not meet any conditions mentioned in `exclude_all_of_attributes`.<br>Consequently, a vehicle which does not have any `attributes` defined can't be assigned to an order which has `vehicle_preferences` configured. |
| `orders[].vehicle_preferences.required_all_of_attributes` | array of object | An array of objects to add mandatory requirements for the order. A vehicle must **meet** **all conditions** specified here to be considered for assignment. Each object represents a single condition. Please note that a maximum of 10 conditions can be added here for a given order. |
| `orders[].vehicle_preferences.required_all_of_attributes[].attribute` | string | Specify the name of the attribute. The `attribute` is compared to the keys (of each `key:value` pair) in `vehicles.attributes` during evaluation. |
| `orders[].vehicle_preferences.required_all_of_attributes[].value` | string | Specify the desired value of the attribute to be applied for this order. `value` provided here is compared to the values (of each `key:value` pair) in `vehicles.attributes` during evaluation. |
| `orders[].vehicle_preferences.required_all_of_attributes[].operator` | string | Specify the operator to denote the relation between `attribute` and the `value` specified above. The `attribute` , `operator` and `value` together constitute the condition that a vehicle must meet to be eligible for assignment. Currently, we support following operators currently:<br>*   Equal to (==)<br>*   Less than (<)<br>*   Less tha equal to (<=)<br>*   Greater than (>)<br>*   Greater than equal to (>=)<br>*   Contains (contains)<br>Please note that when using "contains" operator only one `value` can be specified and the corresponding `attribute` must contain multiple values when defined for a vehicle. |
| `orders[].vehicle_preferences.required_any_of_attributes` | array of object | An array of objects to add optional requirements for the order. A vehicle must **meet** **at least one of the conditions** specified here to be considered for assignment. Each object represents a single condition. Please note that a maximum of 10 conditions can be added here for a given order. |
| `orders[].vehicle_preferences.required_any_of_attributes[].attribute` | string | Specify the name of the attribute. The `attribute` is compared to the keys (of each `key:value` pair) in `vehicles.attributes` during evaluation. |
| `orders[].vehicle_preferences.required_any_of_attributes[].value` | string | Specify the desired value of the attribute to be applied for this order. `value` provided here is compared to the values (of each `key:value` pair) in `vehicles.attributes` during evaluation. |
| `orders[].vehicle_preferences.required_any_of_attributes[].operator` | string | Specify the operator to denote the relation between `attribute` and the `value` specified above. The `attribute` , `operator` and `value` together constitute the condition that a vehicle must meet to be eligible for assignment. Currently, we support following operators currently:<br>*   Equal to (==)<br>*   Less than (<)<br>*   Less tha equal to (<=)<br>*   Greater than (>)<br>*   Greater than equal to (>=)<br>*   Contains (contains)<br>Please note that when using "contains" operator only one `value` can be specified and the corresponding `attribute` must contain multiple values when defined for a vehicle. |
| `orders[].vehicle_preferences.exclude_all_of_attributes` | array of object | An array of objects to add exclusion requirements for the order. A vehicle must **not meet any of the conditions** specified here to be considered for assignment. Each object represents a single condition. Please note that a maximum of 10 conditions can be added here for a given order. |
| `orders[].vehicle_preferences.exclude_all_of_attributes[].attribute` | string | Specify the name of the attribute. The `attribute` is compared to the keys (of each `key:value` pair) in `vehicles.attributes` during evaluation. |
| `orders[].vehicle_preferences.exclude_all_of_attributes[].value` | string | Specify the desired value of the attribute to be applied for this order. `value` provided here is compared to the values (of each `key:value` pair) in `vehicles.attributes` during evaluation. |
| `orders[].vehicle_preferences.exclude_all_of_attributes[].operator` | string | Specify the operator to denote the relation between `attribute` and the `value` specified above. The `attribute` , `operator` and `value` together constitute the condition that a vehicle must meet to be eligible for assignment. Currently, we support following operators currently:<br>*   Equal to (==)<br>*   Less than (<)<br>*   Less tha equal to (<=)<br>*   Greater than (>)<br>*   Greater than equal to (>=)<br>*   Contains (contains)<br>Please note that when using "contains" operator only one `value` can be specified and the corresponding `attribute` must contain multiple values when defined for a vehicle. |
| `orders[].priority` | integer | Specify the priority for this order. A higher value indicates a higher priority. When specified, it will override any priority score deduced from `order_attribute_priority_mappings` for this order. Valid values are \[1, 10\] and default is 0. |
| `orders[].attributes` | object | Specify custom attributes for the orders. Each attribute should be created as a `key:value` pair. The **keys** provided can be used in `options.order_attribute_priority_mappings` to assign a custom priority for this order based on its attributes.<br>The maximum number of key:value pairs that can be specified under `attributes` for a given order, is limited to 30. |
| `vehicles` | array of object | Collects the details of vehicles available to fulfill the orders. Each object represents one vehicle. All requests must include `vehicles` as a mandatory input. A maximum of 100 vehicles is allowed per request. |
| `vehicles[].id` | string | Specify a unique ID for the vehicle. |
| `vehicles[].location` | object | Specify the location coordinates where the vehicle is currently located. This input is mandatory for each vehicle. |
| `vehicles[].location.lat` | number | Latitude of the vehicle's current location. |
| `vehicles[].location.lng` | number | Longitude of the vehicle's current location. |
| `vehicles[].attributes` | object | Specify custom attributes for the vehicle. Each attribute should be created as a `key:value` pair. These attributes can be used in the `orders.vehicle_preferences` input to refine the search of vehicles for each order.<br>The maximum number of key:value pairs that can be specified under `attributes` for a given vehicle, is limited to 30. |
| `vehicles[].remaining_waypoints` | array of object | An array of objects to collect the location coordinates of the stops remaining on an ongoing trip of the vehicle. The service can assign new orders to the vehicle if they are cost-effective. Once a new order is assigned, the vehicle must complete all the steps in the ongoing trip before proceeding to pickup the newly assigned order.<br>Please note that a maximum of 10 waypoints can be specified for a given vehicle. |
| `vehicles[].remaining_waypoints[].lat` | number | Specify the latitude of the location. |
| `vehicles[].remaining_waypoints[].lng` | number | Specify the longitude of the location. |
| `vehicles[].priority` | integer | Specify the priority for this vehicle. A higher value indicates a higher priority. When specified, it will override any priority score deduced from `vehicle_attribute_priority_mappings` for this vehicle. Valid values are \[1, 10\] and default is 0. |
| `filter` | object | Specify the filtering criterion for the vehicles with respect to each order's location. `filter` is a mandatory input for all requests. |
| `filter.radius` | number | Specify a radius, in meters, which will be used to filter out ineligible vehicles for each order. The pickup location of an order will act as the center of the circle when identifying eligible vehicles. Valid values for `radius` are \[1, 200000\]. |
| `filter.pickup_eta` | integer | Specify a duration, in seconds, which will be used to filter out ineligible vehicles for each order. Any vehicle which would take more time than specified here, to reach the pickup location of a given order, will be ruled out for assignment for that particular order. Valid values for `pickup_eta` are \[1, 28800\]. |
| `filter.driving_distance` | number | Defines a `driving_distance` filter, in meters. If a vehicle needs to drive further than this distance to reach a pickup location, it will not be assigned to that order. Valid range of values for this filter is \[1, 700000\]. |
| `options` | object | Configure the assignment constraints and response settings. |
| `options.travel_cost` | string | Choose a travel cost that will be used by the service for assigning vehicles efficiently from a set of qualifying ones. |
| `options.routing` | object | Specify routing preferences for route calculations and identifications. |
| `options.routing.mode` | string | Specify the traveling mode to be used for identifying routes, ETAs and distances. |
| `options.dropoff_details` | boolean | When **true**, the service returns the drop-off steps for each trip and related details in the response. Defaults to **false**. |
| `options.order_attribute_priority_mappings` | array of object | Collection of rules for assigning custom priority to orders based on their attributes. In case an order satisfies more than one rule, the highest priority score from all the rules satisfied, would be the effective priority score for such an order. |
| `options.order_attribute_priority_mappings[].attribute` | string | Specify the name of the attribute. The `attribute` is compared to the keys (of each `key:value` pair) in `orders.attributes` during evaluation. |
| `options.order_attribute_priority_mappings[].value` | string | Specify the desired value of the attribute to be applied for this order. `value` provided here is compared to the values (of each `key:value` pair) in `orders.attributes` during evaluation. |
| `options.order_attribute_priority_mappings[].operator` | string | Specify the operator to denote the relation between `attribute` and the `value` specified above. The `attribute` , `operator` and `value` together constitute the condition that an order must meet to assume the specified priority. We support the following operators currently:<br>*   Equal to (==)<br>*   Less than (<)<br>*   Less tha equal to (<=)<br>*   Greater than (>)<br>*   Greater than equal to (>=)<br>*   Contains (contains)<br>Please note that when using "contains" operator only one `value` can be specified and the corresponding `attribute` must contain multiple values when defined for an order. |
| `options.order_attribute_priority_mappings[].priority` | string | Specify the priority score that should be assigned when an order qualifies the criteria specified above. A higher value indicates a higher priority. Valid values are \[1,10\]. |
| `options.vehicle_attribute_priority_mappings` | array of object | Collection of rules for assigning custom priority to vehicles based on their attributes. In case a vehicle satisfies more than one rule, the highest priority score from all the rules satisfied, would be the effective priority score for such a vehicle. |
| `options.vehicle_attribute_priority_mappings[].attribute` | string | Specify the name of the attribute. The `attribute` is compared to the keys (of each `key:value` pair) in `vehicles.attributes` during evaluation. |
| `options.vehicle_attribute_priority_mappings[].value` | string | Specify the desired value of the attribute to be applied for this vehicle. `value` provided here is compared to the values (of each `key:value` pair) in `vehicles.attributes` during evaluation. |
| `options.vehicle_attribute_priority_mappings[].operator` | string | Specify the operator to denote the relation between `attribute` and the `value` specified above. The `attribute` , `operator` and `value` together constitute the condition that a vehicle must meet to assume the specified priority. We support the following operators currently:<br>*   Equal to (==)<br>*   Less than (<)<br>*   Less tha equal to (<=)<br>*   Greater than (>)<br>*   Greater than equal to (>=)<br>*   Contains (contains)<br>Please note that when using "contains" operator only one `value` can be specified and the corresponding `attribute` must contain multiple values when defined for a vehicle. |
| `options.vehicle_attribute_priority_mappings[].priority` | string | Specify the priority score that should be assigned when a vehicle qualifies the criteria specified above. A higher value indicates a higher priority. Valid values are \[1,10\]. |
| `options.alternate_assignments` | integer | Specify the maximum number of potential, alternate vehicle assignments to be returned for each order, apart from the vehicle which was assigned as recommended. Please note that:<br>*   The maximum number of alternate assignments that can be requested are 3.<br>*   It is not necessary that the service will return the specified number of alternate assignments for each order. The number of alternate assignments returned will depend on the number of vehicles provided in the input.<br>*   Order which could not be assigned to any vehicles due to their `filter` or attribute matching criteria will not be eligible for alternate assignments as well. |

#### Response Schema

| Field | Type | Description |
|-------|------|-------------|
| `id` | string | An unique ID returned by the service for user's reference. This ID should be used in the `GET` request to retrieve the optimized assignment solution. |
| `status` | string | Returns the actual HTTP status code for the request. |
| `msg` | string | Displays the message indicating the status of the request. Returns the error messages as well in case of 4xx, 5xx errors. |
| `warning` | string | Returns the warning messages, in case any. |

### Retrieve a solution

To obtain the calculated assignment solution, you must provide the specific `id` that was generated and returned after submitting the initial POST request. Access the solution using the following endpoint:

GET

https://api.nextbillion.io/optimization/driver-assignment/v1/result?id={id}&key={your_api_key}

#### Request Parameters

| Name | Required | Format and Usage | Description |
|------|----------|------------------|-------------|
| `key` | Yes | Type: `string`<br>Format: `32 character alphanumeric string`<br>Example: `key=API_KEY`<br> | A key is a unique identifier that is required to authenticate a request to the API. |
| `id` | Yes | Type: `string`<br> | Unique ID of the asynchronous solution to be retrieved. The unique ID of a solution is generated at the time of submitting the `POST` request. |

#### Response Schema

| Field | Type | Description |
|-------|------|-------------|
| `id` | string | Returns the unique ID of the assignment solution. |
| `status` | string | Indicates the status of the optimized assignments. For successful requests, it returns one of the 3 values - `processing`, `completed` and `failed` depending on the state of the solution.<br>For unsuccessful requests, it would return the actual HTTP error code. |
| `msg` | string | Displays indicative error message in case of a failed request or operation. Please note that this parameter is not returned in the response when the assignment solution is in `completed` state. |
| `trips` | array of object | An collection of objects returning the trip details for each vehicle which was assigned to an order. Each object corresponds to one vehicle.<br>Please note `trips` is not returned in the response when the `status` is either `processing` or `failed`. |
| `trips[].trip_id` | string | Returns a unique trip ID. |
| `trips[].vehicle` | object | Returns the details of the vehicle, assigned order and the trip steps. |
| `trips[].vehicle.id` | string | Returns the ID of the vehicle. |
| `trips[].vehicle.steps` | object | A collection of objects returning the sequence of steps that the vehicle needs to perform for a trip. |
| `trips[].vehicle.steps.type` | string | Returns the type of the step. Currently, it can take following values:<br>*   **pickup:** Indicates the pickup step for an order<br>*   **dropoff:** Indicates the dropoff step for an order. It is returned only if `dropoff_details` was **true** in the input request.<br>*   **ongoing:** Indicates a step that the vehicle needs to complete on its current trip. This is returned in the response only when `remaining_waypoints` input was provided for the given vehicle.<br>*   **intermediate_waypoint:** Indicates an intermediate stop that the vehicle needs to complete in case multiple dropoffs are provided in the input. |
| `trips[].vehicle.steps.order_id` | string | Returns the ID of the order. In case the step type is **ongoing**, an empty string is returned. |
| `trips[].vehicle.steps.location.lat` | number | Specify the latitude of the location. |
| `trips[].vehicle.steps.location.lng` | number | Specify the longitude of the location. |
| `trips[].vehicle.steps.distance` | integer | Returns the driving distance, in meters, to the step's location from previous step's location. For the first step of a trip, `distance` indicates the driving distance from `vehicle_current_location` to the step's location. |
| `trips[].vehicle.steps.eta` | integer | Returns the driving duration, in seconds, to the step's location from previous step's location. For the first step of a trip, `eta` indicates the driving duration from `vehicle_current_location` to the step's location. |
| `trips[].vehicle.vehicle_current_location.lat` | number | Specify the latitude of the location. |
| `trips[].vehicle.vehicle_current_location.lng` | number | Specify the longitude of the location. |
| `unassigned_orders` | array of object | A collection of objects listing the details of orders which remained unassigned. Each object represents a single order. The attribute is not returned in the response if there are no unassigned orders or if the `status` is either `processing` or `failed`. |
| `unassigned_orders[].order_id` | string | Returns the ID of the order which remained unassigned. |
| `unassigned_orders[].unassigned_reason` | string | Returns the most probable reason due to which the order remained unassigned. |
| `available_vehicles` | array of string | A collection of vehicles IDs that were not assigned to any orders. The attribute is not present in the response if there are no vehicles without an order assignment or if the `status` is either `processing` or `failed`. |
| `alternate_assignments` | array of object | An array of objects containing the details of the potential, alternate vehicle assignments for the orders in the input. Each object represents alternate assignments for a single order. This attribute will not be returned in the response if the `alternate_assignments` was not requested in the input or if the `status` is either `processing` or `failed`. |
| `alternate_assignments[].order_id` | string | Returns the order ID associated with the alternate assignments. |
| `alternate_assignments[].assignments` | array of object | An array of objects containing the details of the alternate vehicle assignments. Each object represents an alternate vehicle assignment. |
| `alternate_assignments[].assignments[].vehicle_id` | string | Returns the vehicle ID which could potentially be assigned to the given order. |
| `alternate_assignments[].assignments[].pickup_eta` | integer | Returns the ETA to the order's pickup location for the given vehicle. |

### Asynchronous Driver Assignment API Example

Here is a sample input problem that we submit using the POST endpoint for asynchronous method.

```bash
curl --location 'https://api.nextbillion.io/optimization/driver-assignment/v1/async?key=<your_api_key>' \
--header 'Content-Type: application/json; charset=utf-8' \
--data '{
    "filter": {
        "radius": 10000,
        "pickup_eta": 3600
    },
    "options": {
        "travel_cost":"driving_eta",
        "order_attribute_priority_mappings": [
            {
                "attribute": "trip_types",
                "value": "premium",
                "operator": "==",
                "priority": 3
            },
            {
                "attribute": "customer_rating",
                "value": "4.0",
                "operator": ">=",
                "priority": 2
            }
        ],
        "routing":{
            "mode": "truck"
        }
    },
    "orders": [
        {
            "id": "o5",
            "pickup": {
                "lat": 1.3248396306932009,
                "lng": 103.90053027285155
            },
            "priority": 5,
            "attributes": {
                "customer_rating": "4.0",
                "trip_types": "premium"
            }
        },
        {
            "id": "o6",
            "pickup": {
                "lat": 1.3229408993456373,
                "lng": 103.89108887391842
            },
            "priority": 10,
            "attributes": {
                "customer_rating": "4.0",
                "trip_types": "premium"
            }
        }
    ],
    "vehicles": [
        {
            "id": "v1",
            "location": {
                "lat": 1.3350270516448868,
                "lng": 103.9369200854675
            }
        }
    ]
}'
```

Once the input request is successfully submitted, we get the following sample response containing the unique ID for the solution:

```json
{
    "id": "9a3226f7-aa0f-422f-afaf-3639a3cc7b29",
    "status": "200",
    "message": "Driver Assignment request created successfully",
    "warning": []
}
```

We then use the GET endpoint of to access the calculated solution

```bash
curl --location 'https://api.nextbillion.io/optimization/driver-assignment/v1/result?id=9a3226f7-aa0f-422f-afaf-3639a3cc7b29&key=<your_api_key>'
```

The response from the GET solution contains the optimal assignment details for the given orders and drivers.

```json
{
    "id": "2eea99e6-294a-40cc-b630-04cfc2c82291",
    "status": "completed",
    "trips": [
        {
            "trip_id": "d2402228-bf31-416c-8be0-d218e9d40cf1",
            "vehicle": {
                "id": "v1",
                "steps": [
                    {
                        "type": "pickup",
                        "order_id": "o6",
                        "effective_order_priority": 10,
                        "location": {
                            "lat": 1.3229408993456373,
                            "lng": 103.89108887391842
                        },
                        "distance": 5463,
                        "eta": 347
                    }
                ],
                "vehicle_current_location": {
                    "lat": 1.3350270516448868,
                    "lng": 103.9369200854675
                }
            }
        }
    ],
    "unassigned_orders": [
        {
            "order_id": "o5",
            "unassigned_reason": "Travel cost constraints"
        }
    ]
}
```

## API Rate Limits and Usage Restrictions

1. Nextbillion.ai allows a maximum rate limit of 300 queries per minute or 5 queries/second for continuous requests.  
   *Note*: We can increase the quota if needed on request. Contact [support@nextbillion.ai](mailto:support@nextbillion.ai) for more details.
2. For *synchronous* method,
   1. maximum `filter.radius` allowed is 10,000 meters.
   2. maximum `filter.pickup_eta` allowed is 3600 seconds.
   3. maximum `filter.driving_distance` allowed is 10,000 meters.
3. For *asynchronous* method,
   1. maximum `filter.radius` allowed is 200,000 meters (200kms).
   2. maximum `filter.pickup_eta` allowed is 28,800 seconds (8hrs).
   3. maximum `filter.driving_distance` allowed is 700,000 meters (700kms).
4. The maximum number of `orders` that can be added in a single request is 200.
5. The maximum number of `vehicles` that can be specified in a single request is 100.
6. The maximum number of `remaining_waypoints` that can be added for a vehicle is 10.
7. The maximum number of `attributes` that can be specified for a single vehicle is 30.
8. A maximum of 10 attribute conditions can be specified under each of `required_all_of_attributes`, `required_any_of_attributes` and `exclude_all_of_attributes` for an order.

## API Error Handling

| Response Code | Description | Additional Notes |
| --- | --- | --- |
| 200 | Normal success case. | Normal success case. |
| 400 | Input validation failed. | There is a missing or an invalid parameter or a parameter with an invalid value type is added to the request. |
| 401 | APIKEY not supplied or invalid. | This error occurs when the wrong API key is passed in the request or the key is missing altogether |
| 403 | APIKEY is valid but does not have access to requested resources. | You might be querying for a geographical region which is not valid for your account, or requesting a service which is not enabled for you. |
| 404 | Requested host/path not found. | This error occurs when a malformed hostname is used. |
| 422 | Could not process the request. | The clustering request could not be completed successfully for the given set of locations or parameter configuration. Please check the API error message for more details. |
| 429 | Too many requests. | QPM or API request count quota reached |
| 500 | Internal Service error. | There was an internal issue with NextBillion.ai services. You can reach out to [support@nextbillion.ai](mailto:support@nextbillion.ai) for an explanation. |
