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.
Hi fact200. Thanks for the reply.

All requests that just read data work perfectly fine. I am logging my data every minute since some month now. But none of the command POST calls work (not even honking).

So I guess the vehicle ID must be correct.

Does this script work with your vehicle ID and token?

Can I set the CORS header on my page with the javascript on it? I thought that has to be set on the Tesla server, right?
 
If I add a chrome extension that sets "Allow-Control-Allow-Origin: *" I get this:

Code:
XMLHttpRequest cannot load https://owner-api.teslamotors.com/api/1/vehicles/71923....506/wake_up. Response for preflight has invalid HTTP status code 404
 
If I add a chrome extension that sets "Allow-Control-Allow-Origin: *" I get this:

Code:
XMLHttpRequest cannot load https://owner-api.teslamotors.com/api/1/vehicles/71923....506/wake_up. Response for preflight has invalid HTTP status code 404

It looks like you're getting the same 404 response as your PHP. For CORS, it sends a preflight OPTIONS request to the target url for certain requests to ensure you have access, and the method and headers are all allowed.

But I'm, not sure why it's not working for you. Fundamentally, the important items are the Auth header and the vehicle id. If your GET requests are working, then something must be wrong with POSTing. I would experiment with using the curl variation of calls; fewer things that can get munged by the implementation.
 
This is very strange. Both, the PHP and the Jscript code is 1:1 copied from the api documentation. The PHP code runs on the webserver (so no CORS) and the Jscript was tested on my local chrome browser. So totally different machines and networks.

Did you test the jscript code with one of your tokens and vehicle IDs?

I don't get why this seems to work for everybody else?

Thanks!
Chris
 
This is very strange. Both, the PHP and the Jscript code is 1:1 copied from the api documentation. The PHP code runs on the webserver (so no CORS) and the Jscript was tested on my local chrome browser. So totally different machines and networks.

Did you test the jscript code with one of your tokens and vehicle IDs?

I don't get why this seems to work for everybody else?

Thanks!
Chris

How comfortable are you with Powershell? I can give you some of the code I use on my car that I know works for you to test of its the code or the ID giving you issues.
 
Yes I would love to try some scripts in Powershell. That should work. Thanks a lot!

I dissected some of the code I use to backup the car to a DB and added 2 post functions, one that requires a body and one that doesn't so you can see both

here's the code.

[Power Shell] #region Functions function Get-TeslaToken($email, $password) { Writ - Pastebin.com

make sure you add your email and password to the first 2 lines as on the first run there won't be a token saved, after the first run it'll be saved locally to C:\Scripts (folder must exist btw) and encrypted for future use so you're not spamming the API.
 
Thanks! I guess that worked:

Code:
PS C:\> .\tesla.ps1
AUSFÜHRLICH: Decrypting Token
AUSFÜHRLICH: Getting new token from API
AUSFÜHRLICH: Encrypting Token
AUSFÜHRLICH: Veryfying Token
AUSFÜHRLICH: Getting Vehicles
Invoke-RestMethod : Der Remoteserver hat einen Fehler zurückgegeben: (401) Nicht autorisiert.
In C:\tesla.ps1:126 Zeichen:21
+ ... tResponse = Invoke-RestMethod -Uri "https://owner-api.teslamotors.com ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

AUSFÜHRLICH: Token passed all checks
AUSFÜHRLICH: Token Successfully Generated, Encrypted and Saved to C:\Users\Prefect\AppData\Roaming
AUSFÜHRLICH: Veryfying Token
AUSFÜHRLICH: Getting Vehicles
AUSFÜHRLICH: Token passed all checks
AUSFÜHRLICH: Getting Vehicles
AUSFÜHRLICH: Getting Vehicle State


api_version               : 3
autopark_state            : unavailable
autopark_state_v2         : ready
autopark_style            : dead_man
calendar_supported        : True
car_type                  : s
car_version               : 2.24.102
center_display_state      : 0
dark_rims                 : False
df                        : 0
dr                        : 0
exterior_color            : White
ft                        : 0
has_spoiler               : False
homelink_nearby           : True
last_autopark_error       : no_error
locked                    : True
notifications_supported   : True
odometer                  : 7955.766527
parsed_calendar_supported : True
perf_config               : P1
pf                        : 0
pr                        : 0
rear_seat_heaters         : 0
remote_start              : False
remote_start_supported    : True
rhd                       : False
roof_color                : None
rt                        : 0
seat_type                 : 1
spoiler_type              : None
sun_roof_installed        : 2
sun_roof_percent_open     : 0
sun_roof_state            : unknown
third_row_seats           : None
valet_mode                : False
valet_pin_needed          : True
vehicle_name              : ENTERPRISE
wheel_type                : Turbine19Dark

AUSFÜHRLICH: Getting Vehicle Climate State
reason :
result : True

AUSFÜHRLICH: Moving pano on ENTERPRISE
reason :
result : True



PS C:\>

What I noticed: My token is only 64 characters long. But the one you save to the TeslaToken.bin is 1729 characters? What does that mean?

"Getting Vehicle Climate State" did actually honk the horn? The pano roof was not moved.
 
Thanks! I guess that worked:

Code:
PS C:\> .\tesla.ps1
AUSFÜHRLICH: Decrypting Token
AUSFÜHRLICH: Getting new token from API
AUSFÜHRLICH: Encrypting Token
AUSFÜHRLICH: Veryfying Token
AUSFÜHRLICH: Getting Vehicles
Invoke-RestMethod : Der Remoteserver hat einen Fehler zurückgegeben: (401) Nicht autorisiert.
In C:\tesla.ps1:126 Zeichen:21
+ ... tResponse = Invoke-RestMethod -Uri "https://owner-api.teslamotors.com ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

AUSFÜHRLICH: Token passed all checks
AUSFÜHRLICH: Token Successfully Generated, Encrypted and Saved to C:\Users\Prefect\AppData\Roaming
AUSFÜHRLICH: Veryfying Token
AUSFÜHRLICH: Getting Vehicles
AUSFÜHRLICH: Token passed all checks
AUSFÜHRLICH: Getting Vehicles
AUSFÜHRLICH: Getting Vehicle State


api_version               : 3
autopark_state            : unavailable
autopark_state_v2         : ready
autopark_style            : dead_man
calendar_supported        : True
car_type                  : s
car_version               : 2.24.102
center_display_state      : 0
dark_rims                 : False
df                        : 0
dr                        : 0
exterior_color            : White
ft                        : 0
has_spoiler               : False
homelink_nearby           : True
last_autopark_error       : no_error
locked                    : True
notifications_supported   : True
odometer                  : 7955.766527
parsed_calendar_supported : True
perf_config               : P1
pf                        : 0
pr                        : 0
rear_seat_heaters         : 0
remote_start              : False
remote_start_supported    : True
rhd                       : False
roof_color                : None
rt                        : 0
seat_type                 : 1
spoiler_type              : None
sun_roof_installed        : 2
sun_roof_percent_open     : 0
sun_roof_state            : unknown
third_row_seats           : None
valet_mode                : False
valet_pin_needed          : True
vehicle_name              : ENTERPRISE
wheel_type                : Turbine19Dark

AUSFÜHRLICH: Getting Vehicle Climate State
reason :
result : True

AUSFÜHRLICH: Moving pano on ENTERPRISE
reason :
result : True



PS C:\>

What I noticed: My token is only 64 characters long. But the one you save to the TeslaToken.bin is 1729 characters? What does that mean?

"Getting Vehicle Climate State" did actually honk the horn? The pano roof was not moved.

Yea sorry about that, I hatched together some code via copy and paste off multiple sources and forgot to clean up the outputs, that function is supposed to honk the horn, that's an example of a POST without parameters, the pano function on the other hand does have parameters.

Did you change the state of the Move-TeslaPano function? It has 3 valid states, for example:

Code:
#opens pano
Move-TeslaPano -tokenObject $token -vehicleID $VehicleInfo.id -state open

#vents pano
Move-TeslaPano -tokenObject $token -vehicleID $VehicleInfo.id -state vent

#closes pano
Move-TeslaPano -tokenObject $token -vehicleID $VehicleInfo.id -state pano
 
No problem, the thing that script was intended to test did work. Issuing commands did work, I heard the honking :)

So the only difference I noticed was the much longer token. Is that intentionally? Is a 64 character long token not valid? But then again, why does my 64char token work for all the request type calls but not for the commands?

Did you try with the jscript code or the php code? Maybe it works for you or you can find the bug in the api documentation examples?

Thanks and Best Regards!
Chris
 
No problem, the thing that script was intended to test did work. Issuing commands did work, I heard the honking :)

So the only difference I noticed was the much longer token. Is that intentionally? Is a 64 character long token not valid? But then again, why does my 64char token work for all the request type calls but not for the commands?

Did you try with the jscript code or the php code? Maybe it works for you or you can find the bug in the api documentation examples?

Thanks and Best Regards!
Chris

the bin file contains the JSON response from the API but it's encrypted, to see the actual token you run the Decrypt-Token function which returns the decrypted token converted from JSON into an object, for example:

Code:
$token = Decrypt-Token
VERBOSE: Decrypting Token


$token.access_token.ToString() | Measure-Object -Character

Lines Words Characters Property
----- ----- ---------- --------
                    64

Which after is decrypted you can see the my token is also 64 characters

I have some jscript code I use with tasker, let me find it.
 
  • Love
Reactions: Prefect
here's my javascript code from tasker, keep in mind that tasker doesn't have the CORS issue that a browser console does, until you fix that even if this code is fine a browser console won't be able to run it.

Code:
var url = "https://owner-api.teslamotors.com/api/1/vehicles/" + INSERT_YOUR_VEH_ID + "/command/sun_roof_control";
var token = INSERT_YOUR_TOKEN
var params = "state=open"

var http = new XMLHttpRequest();

http.open("POST", url+"?"+params, false);

http.setRequestHeader("Authorization", " Bearer " + token);
http.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

http.send(params);

var restresp = JSON.parse(http.responseText);

flash(restresp.response.result);
 
Thanks. I think there where some typos, I corrected it to this for a javascript html page:


Code:
<script>
var url = "https://owner-api.teslamotors.com/api/1/vehicles/7192....0506/command/sun_roof_control";
var token = "a516......62a262c9b15";
var params = "state=open";

var http = new XMLHttpRequest();

http.open("POST", url, false);

http.setRequestHeader("Authorization", " Bearer " + token);
http.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

http.send(params);

var restresp = JSON.parse(http.responseText);

alert(restresp.response.result);
</script>

and I get this in the console:

Code:
tesla.html:15 OPTIONS https://owner-api.teslamotors.com/api/1/vehicles/71923157932960506/command/sun_roof_control 404 (Not Found)(anonymous function) @ tesla.html:15
tesla.html:15 XMLHttpRequest cannot load https://owner-api.teslamotors.com/api/1/vehicles/71923157932960506/command/sun_roof_control. Response for preflight has invalid HTTP status code 404(anonymous function) @ tesla.html:15
tesla.html:15 Uncaught NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'https://owner-api.teslamotors.com/api/1/vehicles/71923157932960506/command/sun_roof_control'.(anonymous function) @ tesla.html:15
 
Thanks. I think there where some typos, I corrected it to this for a javascript html page:


Code:
<script>
var url = "https://owner-api.teslamotors.com/api/1/vehicles/7192....0506/command/sun_roof_control";
var token = "a516......62a262c9b15";
var params = "state=open";

var http = new XMLHttpRequest();

http.open("POST", url, false);

http.setRequestHeader("Authorization", " Bearer " + token);
http.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

http.send(params);

var restresp = JSON.parse(http.responseText);

alert(restresp.response.result);
</script>

and I get this in the console:

Code:
tesla.html:15 OPTIONS https://owner-api.teslamotors.com/api/1/vehicles/71923157932960506/command/sun_roof_control 404 (Not Found)(anonymous function) @ tesla.html:15
tesla.html:15 XMLHttpRequest cannot load https://owner-api.teslamotors.com/api/1/vehicles/71923157932960506/command/sun_roof_control. Response for preflight has invalid HTTP status code 404(anonymous function) @ tesla.html:15
tesla.html:15 Uncaught NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'https://owner-api.teslamotors.com/api/1/vehicles/71923157932960506/command/sun_roof_control'.(anonymous function) @ tesla.html:15

Can you send me the whole html file without your token? I'll test it on my car.
 
In general, yes, if your GET requests for car state (charge, climate, etc..) are working then the commands should work to; they both share the header authorization as well as the vehicle id. The primary difference is that one is POST and one is GET. It's possible there's something else going on thats preventing the proper Authorization header to be sent when you're doing your POST calls...

I'm not an expert on the CORS stuff, but I believe the service provider (i.e. Tesla) also needs to provide an Access-Control-Allow-Origin: * header in order for everything to work. However, the fact that you're getting a 404 means that it's not even getting that far.....
 
Would anyone be kind enough to write a tutorial explaining how to use this API with PHP? Not that I need it or anything.

I've used PHP, but never used an API, so any help would be greatly appreciated,

If I understand correctly, all you pretty much need to do, is have a button on a web page link you to this code, and adjust the command at the end of the curlopt_url as needed, according to the api?

<?php

$token = "fdf3d02....553c798909c7e4";
$VEHICLE_ID = "719.....506";

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, "https://owner-api.teslamotors.com/api/1/vehicles/".$VEHICLE_ID."/command/honk_horn");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_HEADER, FALSE);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
"Authorization: Bearer $token"
));

$response = curl_exec($ch);

var_dump($response);
 
Last edited:
Here, my whole project so far:

www.iteconomy.ch/public/tesla.zip

first, import the tesla.sql database structure to your database.
then set your database access parameters and your mytesla login in settings.php
then start cronjob.php at least twice, so you get a valid token saved to the database and one set of all parameters accessible from your car.

you can run cronjob.php periodically to have a complete log from all your cars parameters. I run it every minute.

tablet.php will show your current status of your car.

Please report back any improvements you did to the code. Thanks!
 
  • Like
Reactions: robertvg