Welcome to Tesla Motors Club
Discuss Tesla's Model S, Model 3, Model X, Model Y, Cybertruck, Roadster and More.
Register

Model S REST API

This site may earn commission on affiliate links.
Zas,

Just so you know, you'll need a machine running some flavor of Linux or perhaps Mac OS or CygWin or a virtual machine on Windows to run this script. It's not a native script for Windows... Once you've got that setup, you'll need to learn this ins and outs of cron (a built-in timer/automated task system in GNU systems like Linux).

If all this doesn't sound daunting, then by all means, continue the research. :) If it does, I'm sure the app will soon provide timer-based events which will make this a lot easier.

I like the challenge !.... i will try it out - thanks
 
Also, note that as written, it won't necessarily work if you have more than one vehicle on your account. It would be a relatively simple change to fix that, but until someone asks, I figured I wouldn't bother.

- - - Updated - - -



On what sort of machine will you be trying it?

I have only one Model S, for now :)

and i will likely try it out on either Red Hat, or just a Mac OSX
 
I've created an Apiary.io page and Github repo for tracking the documentation of the API:

My hope is that we can build some cool apps out of this for our smartphones and for the web. For example, we could build a Windows Phone app (which is being worked on) or an Android widget. Or you could build web service to turn on the climate control at set times or after certain triggers. There are tons of possibilities here and I'm really excited to see what people can think up. REST means the API is easy to use and friendly, so there should be lots of us able to produce something against the API.

Is there really no client auth?
 
For Windows users, here is a pretty simple PowerShell script that allows access to the car. This version requires PS 3.0 (because it uses Invoke-RestMethod), which is installed by default on Windows 8 and Windows Server 2012, but can also be installed on Windows 7. If you save it as Tesla.ps1, for example, then you can lock your car by running ".\Tesla.ps1 -Lock". You can put in your username and password at line 44, or you can have it ask for them by specifying the -Credentials switch.
Code:
param([switch]$Credentials,
      [switch]$TestUrl,
      [switch]$ClimateOn,
      [switch]$ClimateOff,
      [switch]$Lock,
      [switch]$Unlock,
      [switch]$CloseSunroof,
      [switch]$StopCharge,
      [switch]$StartCharge
)
$ErrorActionPreference = "Stop"
Set-StrictMode -Version 2.0
$m_ts = $null
$m_carID = 0
function InvokeCarCommand($command, $successtext, $failtext)
{
    $resp = Invoke-RestMethod -Uri "$uriRoot/vehicles/$m_carID/command/$command" -Method GET -WebSession $m_ts
    if ($resp.result -eq "true") {
        Write-Output $successtext
    }
    else {
        Write-Output "Unable to ${failtext}. Reason returned: `"$($resp.reason)`""
    }
}
if ($TestUrl) {
    $uriRoot = "[URL]http://timdorr.apiary.io[/URL]"
}
else {
    $uriRoot = "[URL]https://portal.vn.teslamotors.com[/URL]"
}
if ($Credentials) {
    $creds = Get-Credential
    $plaintextpwd = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($creds.Password))
    $credsjson = @{ "user_session[email]" = "$($creds.UserName)"; "user_session[password]" = "$plaintextpwd" }
}
else {
    $credsjson = @{ "user_session[email]" = "[EMAIL="[email protected]"][email protected][/EMAIL]"; "user_session[password]" = "MyPassword" }
}
# Login and establish session
$r = Invoke-RestMethod -Uri "$uriRoot/login" -Method GET -SessionVariable m_ts
# We ignore the return form.
$r = Invoke-RestMethod -Uri "$uriRoot/login" -Method POST -WebSession $m_ts -Body $credsjson
# Now, get the vehicle information
$vehicle = Invoke-RestMethod -Uri "$uriRoot/vehicles" -Method GET -WebSession $m_ts
if ($vehicle.Count -gt 1) {
    Write-Output "You have multiple vehicles:"
    $i = 1
    foreach ($entry in $vehicle) {
        $entry | Add-Member -NotePropertyName "Index" -NotePropertyValue $i -Force
        $i++
    }
    $vehicle | Select-Object -Property Index,display_name,vin,state | Format-Table -Auto
    $resp = Read-Host "Enter the index of the vehicle you wish to control"
    $value = -1
    if (-not [Int32]::TryParse($resp, [ref]$value)) {
        throw "Entered value is not a valid number."
    }
    if (($value -lt 1) -or ($value -gt $vehicle.Count)) {
        throw "Invalid entry selected."
    }
    $vehicle = $vehicle[$value - 1]
}
else {
    Write-Output "Controlling vehicle $($vehicle.vin)."
}
$script:m_carID = $vehicle.id
$mobileEnabled = Invoke-RestMethod -Uri "$uriRoot/vehicles/$m_carID/mobile_enabled" -Method GET -WebSession $m_ts
if ($mobileEnabled.result -ne "true") {
    throw "Mobile access is not enabled on the vehicle. Please enable it through the console of the vehicle and try again."
}
$physical_state = Invoke-RestMethod -Uri "$uriRoot/vehicles/$m_carID/command/vehicle_state" -Method GET -WebSession $m_ts
$climate_state = Invoke-RestMethod -Uri "$uriRoot/vehicles/$m_carID/command/climate_state" -Method GET -WebSession $m_ts
$charge_state = Invoke-RestMethod -Uri "$uriRoot/vehicles/$m_carID/command/charge_state" -Method GET -WebSession $m_ts
Write-Output "Current Vehicle State (before executing any commands):"
$physical_state | Select-Object -Property locked,sun_roof_percent_open,car_version,df,dr,pf,pr,ft,rt | Format-Table -Auto
$climate_state | Select-Object -Property inside_temp,outside_temp,fan_status,is_auto_conditioning_on | Format-Table -Auto
$charge_state | Select-Object -Property charging_state,battery_range,battery_level,charger_voltage,charger_actual_current,charger_power,time_to_full_charge,charge_rate | Format-Table -Auto
if ($ClimateOn) {
    InvokeCarCommand "auto_conditioning_start" "Climate control turned on." "turn on climate control"
}
if ($ClimateOff) {
    InvokeCarCommand "auto_conditioning_stop" "Climate control turned off." "turn off climate control"
}
if ($Lock) {
    InvokeCarCommand "door_lock" "Doors are locked." "lock doors"
}
if ($Unlock) {
    InvokeCarCommand "door_unlock" "Doors are unlocked." "unlock doors"
}
if ($CloseSunroof) {
    InvokeCarCommand "sun_roof_control?state=close" "Sunroof is closed." "close sunroof"
}
if ($StopCharge) {
    InvokeCarCommand "charge_stop" "Charging has been stopped." "stop charging"
}
if ($StartCharge) {
    InvokeCarCommand "charge_start" "Charging has been started." "start charging"
}
 
I have only one Model S, for now :)

and i will likely try it out on either Red Hat, or just a Mac OSX

Got it to work !.. but I didnt get any email when not plugged in ?.. when i had my car plugged in .. and it came back "car plugged in".. and when i unplugged it, it states "Not plugged inNull message body; hope that's ok"..but no email ?

another question, how this script 'install' into the car , so that in the future it auto-emails me ?.. or how does it work in general , as surely, its not a script you would run every time manually.
 
There is client auth. Not sure how you got that idea. You need to authenticate with your teslamotors.com login and password and then use the cookie that it returns for all subsequent requests.

I was expecting to have to include some type of token identifying the app, the developer, etc. You see some models where you register as a developer and then get a token which is included in API calls in addition to the user auth.

So if someone gets my website credentials they can view/change my car?
 
I was expecting to have to include some type of token identifying the app, the developer, etc. You see some models where you register as a developer and then get a token which is included in API calls in addition to the user auth.

So if someone gets my website credentials they can view/change my car?

Even if they required developers to register, anyone with your website credentials could download the official app and access your car.
 
Got it to work !.. but I didnt get any email when not plugged in ?.. when i had my car plugged in .. and it came back "car plugged in".. and when i unplugged it, it states "Not plugged inNull message body; hope that's ok"..but no email ?

another question, how this script 'install' into the car , so that in the future it auto-emails me ?.. or how does it work in general , as surely, its not a script you would run every time manually.

It's one of two things: 1) You don't have mail configured on that machine. 2) It's going into your spam. Mine went into spam until I added the address to my contacts. Check your spam, or try messing around with the command line Mail by hand until you successfully get a message through.

You won't be able to install it in the car. You'll need to use cron on the Unix machine to run the script at the time you want.

Good job, by the way.
 
Modified aviators99 script. I now have a cron script so I can plug in as soon as I get home and within 5 miutes, charging will stop and recommence at midnight.

Code:
#! /bin/sh

HOME_DIRECTORY="HOMEDIR"
# Tesla Fashion Island 33.62 -117.90
HOME_LATITUDE=33
HOME_LATITUDE_FRACTION=62
HOME_LONGITUDE=-117
HOME_LONGITUDE_FRACTION=90
TM_USERNAME="USERNAME"
TM_PASSWORD="PASSWORD"
ALERT_EMAIL="EMAILADDRESS"

curl -s --cookie $HOME_DIRECTORY/cookie.jar -c $HOME_DIRECTORY/cookie.jar -X POST -F "user_session[email]=$TM_USERNAME" -F "user_session[password]=$TM_PASSWORD" -k "https://portal.vn.teslamotors.com/login" > /dev/null 2>&1

vehicle=`curl -s --cookie $HOME_DIRECTORY/cookie.jar -c $HOME_DIRECTORY/cookie.jar -k "https://portal.vn.teslamotors.com/vehicles" | awk -F, '{for(i=1;i<NF;i++){if($i ~ /"id":.*/) {print  substr($i,6)} }}'`

if [ "$vehicle" == "" ]; then
#   echo "Could not communicate with vehicle"
   exit 0
fi

ps=`curl -s --cookie $HOME_DIRECTORY/cookie.jar -c $HOME_DIRECTORY/cookie.jar -k "https://portal.vn.teslamotors.com/vehicles/$vehicle/command/charge_state" | awk -F, '{for(i=1;i<NF;i++) {if($i ~ /".*pilot_current":.*/) {print substr($i,25)} }}'`

if [ "$ps" == "" ]; then
#   echo "Could not communicate with vehicle"
   exit 0
fi

if [ "$ps" == "0" ]; then
#   echo "Not plugged in"
#   Mail -s 'Car not plugged in!' $ALERT_EMAIL < /dev/null
   exit 1
fi

cs=`curl -s --cookie $HOME_DIRECTORY/cookie.jar -c $HOME_DIRECTORY/cookie.jar -k "https://portal.vn.teslamotors.com/vehicles/$vehicle/command/charge_state" | awk -F, '{for(i=1;i<NF;i++) {if($i ~ /".*charging_state":.*/) {print substr($i,19)} }}'`
#echo "Charging state = $cs"
lat=`curl -s --cookie $HOME_DIRECTORY/cookie.jar -c $HOME_DIRECTORY/cookie.jar -k "https://portal.vn.teslamotors.com/vehicles/$vehicle/command/drive_state" | awk -F, '{for(i=1;i<NF;i++) {if($i ~ /".*latitude":.*/) {print substr($i,12)} }}'`
cur_lat=`echo $lat | sed -e 's/\./ /g' | awk '{print $1}'`
cur_lat_frac=`echo $lat | sed -e 's/\./ /g' | awk '{print substr($2,0,2)}'`
long=`curl -s --cookie $HOME_DIRECTORY/cookie.jar -c $HOME_DIRECTORY/cookie.jar -k "https://portal.vn.teslamotors.com/vehicles/$vehicle/command/drive_state" | awk -F, '{for(i=1;i<NF;i++) {if($i ~ /".*longitude":.*/) {print substr($i,13)} }}'`
cur_long=`echo $long | sed -e 's/\./ /g' | awk '{print $1}'`
cur_long_frac=`echo $long | sed -e 's/\./ /g' | awk '{print substr($2,0,2)}'`
#echo "Current location = $cur_lat.$cur_lat_frac ($lat) $cur_long.$cur_long_frac ($long)"
cur_hour=$(date "+%k")
cur_min=$(date "+%M")
#echo "Plugged in $cur_hour:$cur_min"
if (( ($HOME_LATITUDE == $cur_lat && $HOME_LATITUDE_FRACTION == $cur_lat_frac) && ($HOME_LONGITUDE == $cur_long && $HOME_LONGITUDE_FRACTION == $cur_long_frac) )); then
#    echo "Parked at home"
    if (( $cur_hour > 5 && $cur_hour < 24 )); then
        if [ "$cs" == "\"Charging\"" ]; then
#            echo "Charging stopped due to high rates"
            cs=`curl -s --cookie $HOME_DIRECTORY/cookie.jar -c $HOME_DIRECTORY/cookie.jar -k "https://portal.vn.teslamotors.com/vehicles/$vehicle/command/charge_stop"`
        fi
    elif [ "$cs" == "\"Stopped\"" ]; then
#            echo "Charging started at optimal rates"
            cs=`curl -s --cookie $HOME_DIRECTORY/cookie.jar -c $HOME_DIRECTORY/cookie.jar -k "https://portal.vn.teslamotors.com/vehicles/$vehicle/command/charge_start"`
    fi
fi

Modified the script to only work when the car is at home. Set your HOME_LATITUDE, HOME_LATITUDE_FRACTION (2 digits) and HOME_LONGITUDE, HOME_LONGITUDE_FRACTION (2 digits) to your home coordinates.

Started a cron job with "crontab -e" and added the following entry:
0-59/5 * * * * /path/to/script
 
Last edited:
It's one of two things: 1) You don't have mail configured on that machine. 2) It's going into your spam. Mine went into spam until I added the address to my contacts. Check your spam, or try messing around with the command line Mail by hand until you successfully get a message through.

You won't be able to install it in the car. You'll need to use cron on the Unix machine to run the script at the time you want.

Good job, by the way.

ohhh.. so i have to run the script manually each time ?.. that reduces its 'coolness' :( its super fun to be able to communicate with the car with some coding - i can see a bright future with some killer customized apps !!
 
^ you can run it as a cron job

Any way to get the lat/lon coordiates?

No, you don't have to run manually. cron is a program that will run any script at the time you want, or how often you want.
Yes, I should have made myself more clear.

I'm a Linux sysadmin as my daily job and we sometimes see things different.

But yes, you should run this script using CRON or something like that. Just wanted to point out that it's not a daemon :)
 
Yes, I should have made myself more clear.

I'm a Linux sysadmin as my daily job and we sometimes see things different.

But yes, you should run this script using CRON or something like that. Just wanted to point out that it's not a daemon :)

See my thread above (#72). It shows how to get latitude and longitude and it will charge the car from midnight to 6 am when at home.
 
Here's the output from a webpage I created for my friends to keep track of me:

mypage.jpg