Updating Routes

Overview

This example will guide you through the following:

  • Using HTTP PATCH semantics to correctly update the following aspects of a route:
    • The route name and notes
    • The route assignment
    • Updating, adding, and removing route stops

PATCH Semantics

The endpoint to update a route is:

PATCH https://api.samsara.com/fleet/routes/<id_or_externalID>

Full reference docs here.

The PATCH HTTP method only requires you to provide the fields you wish to update in the request body. Whatever you list in the request body will overwrite the corresponding field of the route. All other fields will remain the same. To unset a field, you set it to null.

When updating the stops array, you MUST include the full, new list of stops. Whatever you provide to the stops array field in the request body will overwrite the previous stop array, so it's important to include the full, new list of stops.

Retaining Existing Stops

When you are modifying the stop/job array for a specific route, always include the stop ID if you wish to retain existing stops in that route. Failure to include the stop ID will result in the API removing those stops—even if all other parameters for that stop remain unchanged. This could lead to unintended consequences such as resetting the tracking state for that particular stop, affecting your real-time monitoring or analytics.

Updatable Fields

Here is what you can update:

  • External IDs: externalIds
  • Name: name
  • Notes: notes
  • Route assignment: adding, removing, or modifying the driverId or vehicleId
  • Route starting and/or completion conditions: settings
  • Adding or removing stops.
  • Editing the following properties of the stops:
    • External IDs: externalIds
    • Name: name
    • Notes: notes
    • Destination location: addressId or singleUseLocation
    • Scheduled arrival time: scheduledArrivalTime
    • Scheduled departure time: scheduledDepartureTime

You cannot update the following fields. If you provide these fields in your request, they will be ignored. This includes:

  • Anything that is “actual” (i.e. tracked by Samsara through route tracking):
    • actualRouteStartTime
    • actualRouteEndTime
    • Stop state: state
    • State change times: enRouteTime, eta, actualArrivalTime, actualDepartureTime, skippedTime

Updating Live or Finished Routes

Once Samsara has started tracking a route, it is recommended that you ONLY MAKE UPDATES TO THE FOLLOWING FIELDS:

  • externalIds
  • name
  • notes
  • stops: You should only add or modify stops whose scheduled arrival time is after the current time.

❗️

Modifying route stops whose scheduled arrival time has already passed WILL RESULT IN UNPREDICTABLE BEHAVIOR.

Examples

Name and Notes

curl --request PATCH 'https://api.samsara.com/fleet/routes/routePlanningSystem:route1234' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <<token>>' \
--data-raw '{
    "name": "New Name",
    "notes": "New Notes"
}'

Route Assignment

Routes can be assigned to either drivers or vehicles. They cannot be assigned to both.

curl --request PATCH 'https://api.samsara.com/fleet/routes/routePlanningSystem:route1234' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <<token>>' \
--data-raw '{
    "vehicleId": null,
    "driverId": "1654973"
}'
curl --request PATCH 'https://api.samsara.com/fleet/routes/routePlanningSystem:route1234' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <<token>>' \
--data-raw '{
    "driverId": null,
    "vehicleId": "281474977075805"
}'
curl --request PATCH 'https://api.samsara.com/fleet/routes/routePlanningSystem:route1234' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <<token>>' \
--data-raw '{
    "driverId": null,
    "vehicleId": null
}'

Adding Stops

To add a route stop, create a new route stop object and add it to the stops array. Samsara will automatically order routes stops based on scheduled arrival time.

import requests
import json

url = "https://api.samsara.com/fleet/routes/routePlanningSystem:route1234"

headers = {
  'Content-Type': 'application/json',
  'Authorization': 'Bearer <<token>>'
}

# Retrieve full list of route stops
route = requests.request('GET', url, headers=headers).json()
stops = route['data']['stops']

# Add a new stop to the existing list
new_stop = {
    "addressId": "21275762",
    "scheduledArrivalTime": "2021-05-07T15:30:00.000Z"
}
stops.append(new_stop)

# Submit PATCH request
payload = json.dumps({
    'stops': stops
})
response = requests.request("PATCH", url, headers=headers, data=payload)

Removing Stops

To remove a route stop you must remove it from the stops array. It is helpful if you know the dispatch job's ID.

import requests
import json

url = "https://api.samsara.com/fleet/routes/routePlanningSystem:route1234"

headers = {
  'Content-Type': 'application/json',
  'Authorization': 'Bearer <<token>>'
}

# Retrieve full list of route stops
route = requests.request('GET', url, headers=headers).json()
stops = route['data']['stops']

# ID of the stop to remove
stop_id = '4439854173'

# Find the stop in the stops array and remove it
stop_index = None
for i, stop in enumerate(stops):
  if stop['id'] == stop_id:
    stop_index = i
if stop_index:
    stops.pop(stop_index)

# Depending on which stop was removed and the route settings, you may need to remove the first and last stop's scheduledArrivalTime or scheduledDepartureTime
if route['data']['settings']['routeStartingCondition'] == 'departFirstStop':
    stops[0]['scheduledArrivalTime'] = None

if route['data']['settings']['routeCompletionCondition'] == 'arriveLastStop':
    stops[-1]['scheduledDepartureTime'] = None

# Submit PATCH request
payload = json.dumps({
    'stops': stops
})
response = requests.request("PATCH", url, headers=headers, data=payload)

Stop Schedule

import requests
import json

url = "https://api.samsara.com/fleet/routes/routePlanningSystem:route1234"

headers = {
  'Content-Type': 'application/json',
  'Authorization': 'Bearer <<token>>'
}

# Retrieve full list of route stops
# THIS IS IMPORTANT BECAUSE EVEN THOUGH YOU ARE ONLY UPDATING ONE STOP, YOU MUST INCLUDE ALL THE OTHERS IN THE REQUEST OR ELSE THEY WILL BE DELETED
route = requests.request('GET', url, headers=headers).json()
stops = route['data']['stops']

# ID of the stop to update
stop_id = '4439748158'
new_arrival_time = '2021-05-07T16:15:00Z'

# Find the stop in the stops array and update it
stop_index = None
for i, stop in enumerate(stops):
  if stop['id'] == stop_id:
    stop_index = i
# Check if the stop is the first, and update according to route settings
if stop_index == 0 and route['data']['settings']['routeStartingCondition'] == 'departFirstStop':
        stops[stop_index]['scheduledArrivalTime'] = None
        stops[stop_index]['scheduledDepartureTime'] = new_arrival_time
else:
        stops[stop_index]['scheduledArrivalTime'] = new_arrival_time
        stops[stop_index]['scheduledDepartureTime'] = None

# Submit PATCH request
payload = json.dumps({
    'stops': stops
})
response = requests.request("PATCH", url, headers=headers, data=payload)

📘

Samsara will automatically order stops based on scheduledArrivalTime, regardless of the order you arrange them in the stops array.

Stop Locations

Route locations can either reference a registered Address object by its ID (recommended), or they can be defined inline within the route (single-use location). See the Stop Locations guide for more details.

import requests
import json

url = "https://api.samsara.com/fleet/routes/routePlanningSystem:route1234"

headers = {
  'Content-Type': 'application/json',
  'Authorization': 'Bearer <<token>>'
}

# Retrieve full list of route stops
# THIS IS IMPORTANT BECAUSE EVEN THOUGH YOU ARE ONLY UPDATING ONE STOP, YOU MUST INCLUDE ALL THE OTHERS IN THE REQUEST OR ELSE THEY WILL BE DELETED
route = requests.request('GET', url, headers=headers).json()
stops = route['data']['stops']

# ID of the stop to update
stop_id = '4439748158'
new_address_id = '21275794'

# Find the stop in the stops array and update it
for stop in stops:
    if stop['id'] == stop_id:
        # Clear old location data
        stop['singleUseLocation'] = None
        stop['address'] = None
        # Provide new address ID
        stop['addressId'] = new_address_id

# Submit PATCH request
payload = json.dumps({
    'stops': stops
})
response = requests.request("PATCH", url, headers=headers, data=payload)