VOI is a Swedish ride sharing company focused on electric scooters. They have scooters placed in several cities and countries around the world, including Sweden, Spain, Italy, France and more.
Base url of the API is https://api.voiapp.io/v1
The API requires an Access Token. This token is valid for only a short time (10 minutes I think, I haven’t tried to measure). You get the Access Token by opening a session. You need an Authentication Token to open a session. When opening a session, you get:
To get the first Authentication Token, see steps 1,2,3 below.
See here example of python implementation of the session authentication (once the step 1-2-3 are done): https://github.com/hawisizu/scooter_scrapper/blob/master/providers/voi.py
POST
request to https://api.voiapp.io/v1/auth/verify/phone
Body: raw/JSON
{
"country_code": "DE",
"phone_number": "176xxxxxxxx"
}
Note: phone number is without any 0.
In the body of the answer, you get a UUID in a param token
, and of course an SMS message to the provided phone number.
{
"token": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
This request gets nothing in the answer, but is necessary so that the token works. The code
should be the value received by SMS.
POST
request to https://api.voiapp.io/v1/auth/verify/code
Body: raw/JSON
{
"code": "123456",
"token": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
Answer is 204 with no content.
POST
request to https://api.voiapp.io/v1/auth/verify/presence
Body: raw/JSON:
{
"email": "xxx@xxx.com",
"token": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
(the email should apparently be valid) Answer will be:
{
"authenticationToken": "xxxxxxxxxxxxxxxx"
}
(the token is really super long)
POST
request to https://api.voiapp.io/v1/auth/session
Body: raw/JSON
{
"authenticationToken": "xxxxxxxxxxxxxxxx"
}
Answer will be:
{
"accessToken": "yyyyyyyyyyyyyyyyy",
"authenticationToken": "zzzzzzzzzzzzzzzzzzz"
}
You will then use the accessToken
to query the data, and the authenticationToken
to open the next session, so that you don’t have to re-do step 1-2-3
Once you have an Access Token, you can query the zones info, or if you already know which zone you want to query, get the scooters of the zone.
GET
request to https://api.voiapp.io/v1/zones
In the headers you need the access token you got when opening a session:
x-access-token
: yyyyyyyyyyyyyyyyy
Answer: a long json with all the zones where VOI is currently operating, with details on the prices and forbidden zones, the max speed, etc. See here an example of the full zones json retrieved on Dec 20th, 2019: https://gist.github.com/hawisizu/4d54000dc4d5d6d2e39f6994006b74d2
Notes:
lng
and lat
as params of the GET request.GET
request to https://api.voiapp.io/v2/rides/vehicles?zone_id=<ZONE_ID>
<ZONE_ID>
has to be the ID of one of the zones.
In the headers you need the access token you got when opening a session:
x-access-token
: yyyyyyyyyyyyyyyyy
Answer:
{
"data": {
"vehicle_groups": [
{
"price_token": "...",
"group_type": "scooter",
"vehicles": [
{
"id": "274db72d-f108-417a-93e3-46acb61cfd26",
"short": "kpne",
"battery": 55,
"location": {
"lng": 18.11346435546875,
"lat": 59.34138107299805
},
"zone_id": "1"
},
{
"id": "3bd0b7bf-15c0-46f8-9d3b-ecb962f1f5d5",
"short": "bnjs",
"battery": 78,
"location": {
"lng": 18.088924407958984,
"lat": 59.354530334472656
},
"zone_id": "1"
}
]
}
]
}
}
The response is a nested object with information about each scooter, in a JSON format. Here is a list of the parameters in each scooter object and information about what they (most likely) do:
id
: A scooter ID that most likely is used internally.
short
: A four-character shortcode of the VOI scooter, which is used to unlock it in the app if you don´t scan the QR code on the scooter.
battery
: An integer representing the battery percentage of the scooter.
location
: An object of the scooter location.
zone_id
: This is most likely an indication of what zone the scooter is located in. Each VOI zone is represented by an integer.