Smartlane API

The Smartlane API Developer Hub

Welcome to the Smartlane API developer hub. You'll find comprehensive guides and documentation to help you start working with Smartlane API as quickly as possible, as well as support if you get stuck. Let's jump right in!

Get Started    

Search results for "{{ search.query }}"

No results found for "{{search.query}}". 
View All Results

Getting Started

This tutorial introduces some basics of the Smartlane API. For a detailed description of all API endpoints, check out the API reference.

Sign Up

In order to get started with the Smartlane API, you need to sign up to get your own personal access key and database instance.

You can request free test access and a personal demo of the application via our registration form or just by getting in touch with us directly at info@smartlane.de.

We will then provide you with a link to a registration form. Your email address will be set as your user name and once you choose your private password, you're ready for authentication with our API.

Data privacy and security

All API calls are secured by SSL via HTTPS, so you don't have to worry about anybody intercepting your data via the Internet. All supplied data are stored securely on professionally operated servers in Germany and they are only accessible by the API itself - they cannot be accessed by anyone outside the application. The API itself is secured by a user name and password, which are supplied only to you during the registration process. Of course, passwords are always stored as encrypted hashes and thus are never readable by anybody.

Authentication

Next to being accessible exclusively via https, all API calls (exceptions aside) are secured by JWT tokens. That means you always need to provide an authorization header with a security token.

The token is generated via a POST request to the API endpoint /auth, with your registered email address and password information in the body:

curl --request POST \
     --url 'https://dispatch.smartlane.io/your_company_name/auth' \
     --header 'Content-Type: application/json' \
     --data '{"email": "your@email.net", 
              "password": "your_choosen_password"}'
import requests

url = "https://dispatch.smartlane.io/your_company_name/auth"
login = {'email': 'your@email.net', 'password': 'your_choosen_password'}

response = requests.post(url, json=login)
jQuery, yet to be added

If done successfully, this responds with a JSON body containing the access_token,

{'access_token': 'your.Long_Randomfghxlcnebem.Secure_AccessToken'}

which can - and must - be used for all further API calls in the request header in the following form as a JSON object:

{'Authorization': 'JWT your.Long_Randomfghxlcnebem.Secure_AccessToken'}

Please make sure that you don't miss the mandatory JWT prefix! As an example, it may serve a request to the /company endpoint.

curl --request GET \
     "https://dispatch.smartlane.io/your_company_name/api/company" \
     --header "Authorization: JWT your.Long_Randomfghxlcnebem.Secure_AccessToken"
import requests

api_url = "https://dispatch.smartlane.io/your_company_name/api/company"

auth_header = {'Authorization': 'JWT your.Long_Randomfghxlcnebem.Secure_AccessToken'}

response = requests.get(url, headers=auth_header)

It's all JSON

All request bodies and headers, as well as the produced responses, are exclusively of the type application/json.

If everything goes right, the response is a HTTP status code 200 containing a body similar to

{'num_results': 1,
 'objects': [{'companyname': 'Your_company_name',
              'id': 1,
              'location_id': 1,
              'pricing_package': 500,
              'test_phase': True}],
 'page': 1,
 'total_pages': 1}

Another thing you might want to try is a call to /companyaddress, to get the address information of the company you signed up with. This should be done before you actually get started with planning a whole tour, which is a core feature of the Smartlane API.

Pagination

Some of the responses are "paginated" by default. To request a specific page, add a page=N query parameter to the request URL, where N is a positive integer, e.g. /api/company?page=2.

Planing a First Tour

During the next steps, we'll walk through some basic API requests, necessary to plan your first tour: for example, adding a driver and activating it, uploading addresses necessary to schedule deliveries, calculating the actual tour, as well as updates concerning the state of the driver, which the notification to the customers depend upon.

While the Smartlane API is one single API, it may be useful to introduce a distinction between the API calls, attributed to the two kinds of users: the dispatchers and the drivers. The dispatcher supervises and manages the deliveries and tours, usually from the company's central office, while the driver takes care of the actual deliveries and deals with the inevitable disruptions that happen out on the road. The Smartlane API can help by reporting these unexpected changes and rescheduling automatically.

API Endpoint URLs

All URLs of the API requests are composed of the the base url https://dispatch.smartlane.io/your_company_name plus /api and the /name of the API endpoint. The only exception is the call to /auth, where /api is absent.

Adding Drivers

Before planning the actual tour, you need to add one or more drivers who take care of the actual deliveries. You can do this by posting the necessary data to the API endpoint /driver

curl --request POST \
     --url "https://dispatch.smartlane.io/your_company_name/api/driver" \
     --header "Content-Type: application/json" \
     --header "Authorization: JWT your.Long_Randomfghxlcnebem.Secure_AccessToken" \
     --data '{"firstname":"John",  
              "lastname": "Driver",
              "email": "driver@mail.net",
              "mobilenr": "017012345678"}'
import requests

auth_header = {"Authorization": "JWT your.Long_Randomfghxlcnebem.Secure_AccessToken"}
api_url = "https://dispatch.smartlane.io/your_company_name/api"

url = api_url + "/driver"

driver_data = {"firstname":"John",
               "lastname": "Driver",
               "email": "driver@mail.net",
               "mobilenr": "017012345678"}

response = requests.post(url, headers=auth_header, json=data)

If you see a response with HTML code 201 "Created", you know you've successfully added a new driver, along with your posted information and a couple of default values (e.g. the vehicle type "car").

{ "active": false,
  "company_id": null,
  "confirmed_at": null,
  "driveravailabilities": [],
  "email": "driver@mail.net",
  "expires": null,
  "firstname": "John",
  "htmlcolor": "0000ff",
  "id": 2,
  "lastname": "Driver",
  "mobilenr": "017012345678",
  "status": 0,
  "usertype": "driver",
  "vehicle": "car"
 }

More important than the direct response of the call to /driver, the call also triggers an email sent to the driver, which includes the activation code. (In addition, another email is sent to the dispatcher and another to Smartlane, for logging purposes.) That's neccesary because routes can only be assigned to drivers that have been activated and, as you can see above, the "active" property is still set to false.

The email's template is currently designed to work for the SmartlaneDISPATCH Android App. But you should still be able to find the activation code in it. (Hint: The code parameter in the "Fahrer aktivieren" button's URL.)

This activation code and the IMEI number (our current way to identify your mobile device) combine for the /activate/driver call.

curl --request POST \
     --url "https://dispatch.smartlane.io/your_company_name/api/activatedriver" \
     --header "Content-Type: application/json" \
     --header "Authorization: JWT your.Long_Randomfghxlcnebem.Secure_AccessToken" \
     --data '{"code":"uaFGH_your.LongRandomCxlcce_Activation.code",  
              "imei": "123456789012345"}'
import requests

data = {"code": "uaFGH_your.LongRandomCxlcce_Activation.code", 
        "imei": "123456789012345"}

url = api_url + "activatedriver"
response = requests.post(url, json=data)

When that's done, your driver should be registered

{"message": "driver successfully activated.",    "status": 200}

and you're ready to schedule some deliveries for him.

Deliveries

The main information necessary to carry out a delivery is ..., yes, the address.
So let's add some to our database by posting them to /address.

curl --request POST \
     --url 'https://dispatch.smartlane.io/your_company_name/api/address' \
     --header 'Content-Type: application/json' \
     --header 'Authorization: JWT your.Long_Randomfghxlcnebem.Secure_AccessToken' \
     --data '{"contactcompany": "The Supply Center",
              "street": "Grafinger Str.",
              "housenumber": "6",
              "city": "München",
              "postalcode": "81671"}'
import requests

auth_header = {"Authorization": "JWT your.Long_Randomfghxlcnebem.Secure_AccessToken"}
api_url = "https://dispatch.smartlane.io/your_company_name/api"

url = api_url + "address"

data = {"contactcompany": "The Supply Center",
        "street": "Grafinger Str.",
        "housenumber": "6",
        "city": "München",
        "postalcode": "81671"}

response = requests.post(url, headers=auth_header, json=data)

You can have a look below at what other fields you may want to provide, e.g. an email address or phone number, whether the customer should be informed before the package arrives, etc. You may also notice that the most relevant information for our routing system - the location represented as geo coordinates (latitude and longitude) - has been added automatically. Please remember that it's important to provide enough information so that it can be correctly determined.

{'addresstype': None,
 'city': 'München',
 'contactcompany': 'The Supply Center',
 'contactfirstname': None,
 'contactlastname': None,
 'country': 'DE',
 'deliverylocations': [],
 'distances': None,
 'district': None,
 'email': None,
 'housenumber': '6',
 'id': 2,
 'location': {'coordinates': [11.60768, 48.12467], 'type': 'Point'},
 'phonenr': None,
 'postalcode': '81671',
 'source_for_deliveries': [],
 'street': 'Grafinger Str.'}

Each address in the database gets assigned an id, which is, among other things, used for the identification of the supplier as well as the delivery location (compare supplierlocation_id and deliverylocation_id below). So after you've added a second address, you can schedule your first delivery via the /delivery endpoint,
like this:

curl --request POST \
     --url 'https://dispatch.smartlane.io/your_company_name/api//delivery' \
     --header 'Content-Type: application/json' \
     --header 'Authorization: JWT your.Long_Randomfghxlcnebem.Secure_AccessToken' \
     --data '{"supplierlocation_id": 2,
              "deliverylocation_id": 3,
              "pdt_from": "2019-04-28T15:51:41.471680+02:00",
              "pdt_to":   "2019-04-28T16:51:41.471680+02:00"}'
import requests
from datetime import datetime, timedelta

auth_header = {"Authorization": "JWT your.Long_Randomfghxlcnebem.Secure_AccessToken"}
api_url = "https://dispatch.smartlane.io/your_company_name/api"

url = api_url + "/delivery"

data = {"supplierlocation_id": 2,
        "deliverylocation_id": 3,
        "pdt_to": (datetime.now() + timedelta(days=1)).isoformat(),
        "pdt_from": datetime.now().isoformat()}

response = requests.post(url, headers=auth_header, json=data)

The properties pdt_to and pdt_from, defining the "planned delivery time" span, is the other information necessary for calculating the optimal tour with the routing type we're using in this example. Make sure that all dates and times are formatted according to the ISO 8601 standard. Be aware that the time zone designator is mandatory, unless you're in UTC±0.

Let's skip over the rather complex response object at this point. Just make sure that you've got a 201 HTML response code and remember the id, which is used to identify the deliveries when we calculate the tour.
Because it's not a real challenge to calculate the optimal route between two locations, you may want to add another delivery in a similar manner, before we get ready for processing the actual routing.

Routing

An overview across the different routing types is given in docs and you also get a listing directly through the API via /routingvariants for a specific list of deliveries. Here we're just going to use our most common type: Optimized time window routing. For this type of routing it's necessary to have the same starting point (supplierlocation_id) for all deliveries,
meaning "pick up the packages once and deliver all of them without needing to come back to the supply center".
The other important feature of this routing type is the time window, which defines the planned arrival time of the delivery. This is the reason why we added the pdt _to and pdt_from to our deliveries before. It allows taking into account, for example, the time a customer is at home, or that a certain shipment needs to be delivered earlier, and still get an optimized tour.

The required parameters for the /calcroute/optimized/timewindow endpoint are just the delivery ids. Assuming that the ids of the deliveries are 2and 9, it's simple as this:

curl --request POST \
     --url 'https://dispatch.smartlane.io/your_company_name/api/calcroute/optimized/timewindow' \
     --header 'Content-Type: application/json' \
     --header 'Authorization: JWT your.Long_Randomfghxlcnebem.Secure_AccessToken' \
     --data '{"deliveryids": [2, 9]}'
import requests

auth_header = {"Authorization": "JWT your.Long_Randomfghxlcnebem.Secure_AccessToken"}
api_url = "https://dispatch.smartlane.io/your_company_name/api"

url = api_url + "calcroute/optimized/timewindow"
data = {"deliveryids": [2, 9]}

response = requests.post(url, headers=auth_header, json=data)

After you've calculated the route, you can assign a driver to it, by updating the route's driver_id via the patch /route API call. If we assume the route's id is 1, it looks like this:

curl --request PATCH \
     --url 'https://dispatch.smartlane.io/your_company_name/api/route/29' \
     --header 'Content-Type: application/json' \
     --header 'Authorization: JWT your.Long_Randomfghxlcnebem.Secure_AccessToken' \
     --data '{"driver_id": 2}'
import requests

auth_header = {"Authorization": "JWT your.Long_Randomfghxlcnebem.Secure_AccessToken"}
api_url = "https://dispatch.smartlane.io/your_company_name/api"

requrl = api_url + "route/1"
data = {"driver_id": 2}

response = requests.patch(requrl, headers=auth_header, json=data)

The driver's smartphone, or another device that he chooses, can now know, by frequently polling the required data, that the driver has been assigned to the job.

Driver updates

Now that the route has been calculated, it has an assigned driver_id and the driver's mobile device now displays it. To make sure that the actual person who is assigned the ID also knows about the route, he must accept the tour. This can be done by updating the status of the route, from the default value 1 "assigned" to 2 "accepted". When the driver is actually in the car and starts the tour, his status is reported to the backend, and therefore also to the dispatcher, by setting the status to 3 "on the way". This is done in the same way, by patching the route via the API call /route/{route_id}.
Let's do this in just one step, to save some space:

curl --request PATCH \
     --url 'https://dispatch.smartlane.io/your_company_name/api/route/738' \
     --header 'Content-Type: application/json' \
     --header 'Authorization: JWT your.Long_Randomfghxlcnebem.Secure_AccessToken' \
#    --data '{"status": 2}'    
     --data '{"status": 3}'
import requests

auth_header = {"Authorization": "JWT your.Long_Randomfghxlcnebem.Secure_AccessToken"}
api_url = "https://dispatch.smartlane.io/your_company_name/api"

requrl = api_url + "route/738"

data = {"status": 2}
data = {"status": 3}

response = requests.patch(requrl, headers=auth_header, json=data)

Once the driver has reported he's "on the way", the target delivery times and potential delays are calculated based on the current traffic forecast. The customer can optionally receive a message via email or SMS with the estimated delivery time, if notify_customer was set to true in the delivery information.

After the driver has arrived at the customer's address, he is required to update the status via /deliverydone/delivery_id to either delivered or undelivered.

curl --request POST \
     --url 'https://dispatch.smartlane.io/your_company_name/api/deliverydone/421' \
     --header 'Content-Type: application/json' \
     --header 'Authorization: JWT your.Long_Randomfghxlcnebem.Secure_AccessToken' \
     --data '{"status": "deliverd",
              "drivernotes": "Optional notes from the driver."}'
import requests

auth_header = {"Authorization": "JWT your.Long_Randomfghxlcnebem.Secure_AccessToken"}
api_url = "https://dispatch.smartlane.io/your_company_name/api"

requrl = api_url + "deliverydone/1" # 1 is delivery_id

data = {"status": "delivered"
        "drivernotes": "Optional notes from the driver."}

response = requests.post(requrl, headers=auth_header, json=data)

In the same way, the driver is expected to make the deliveries and report their status until he has completed the whole tour.
If a package couldn't be delivered, it will automatically be placed back on the list of undelivered entries, ready to be reassigned to the next tour.

Request limit

There is a general limit of 200 API requests per second. If more requests are called, the response will be 429 Too Many Requests. If you need a higher request frequency, please et us know at support@smartlane.de.

Getting Started