A Beginner’s Guide to the Unofficial Tesla API

Jimmy Huang
Nov 13, 2018 · 6 min read

Check out my basic implementation using React Native on Github.

Image for post
Image for post
Source: https://www.tesla.com/support/tesla-app

Before we begin, we should briefly explore a few concepts.

First, what exactly is an API? API stands for Application Programming Interface. It allows applications to talk to each other and lets external users consume data without resorting to web scraping. The easiest way to describe an API is a server that will fulfill your requests for data and/or actions. As you might have guessed, the Tesla API will be the main resource for our application.

APIs will usually send back data in the form of JSON, or JavaScript Object Notation. With JSON, you can easily query the information you need and update the state of your own application with that information.

APIs are also generally designed with an architectural style called REST, or Representational State Transfer. It covers the 4 CRUD actions: Create, Read, Update, and Delete. The two most common type of requests are: GET (read), and POST (create) requests. These are the two that we will be using today.

The last nominal topic to cover is what an unofficial/private API is. It refers to an API that isn’t officially acknowledged by the provider but still allows access (with authentication). It is hard to speculate on the reasons why this is the case for the Tesla API, but it could vary from not being ready for public use to the company not wanting to have engineers maintain the service.

Luckily for us, people have been able to reverse engineer the API. There are two sites that have graciously provided documentation on how to access these API endpoints. An endpoint is the URI of the server that will receive our requests and allow us to communicate directly with the API. There will be multiple endpoints — each serving their own purpose.

The two sites are here:


Before we continue, note that that certain API requests can perform remote actions on your car.

Image for post
Image for post
Source: https://www.teslarati.com/tesla-model-3-app-phone-key-features-screenshots/

Let’s start by getting data about our car. We can kick off the process by submitting POST and GET requests to the Tesla API endpoint. But before we can do that, we must figure out which endpoint to hit and then complete the authorization process through OAuth 2.0. OAuth is a protocol to tell the API that we have the proper credentials and should be permitted access.

From the Unofficial API documentation, we have Tesla’s Client ID and their Client Secret. The client ID is a public identifier for the app, and the client secret is used for identifying with the authorization server.

All we need to now is to go through the OAuth Password Grant which exchanges our first-party (rather than third-party) credentials for an access token. Since Tesla owners must make an account before purchasing a car, it is relatively simple. The username and password we use for the Tesla site can be exchanged directly for a token.

We can send a POST request to:


through the Fetch API which is built into any modern browser.

An easy way to do this is by using Postman. It also allows us to debug the initial requests (e.g. Did we hit the right route? Is the header and body valid? What type of JSON data is being send back?) easily. However, we need to send header information to authenticate ourselves.

The POST request requires two things in this case:

  1. a header that contains the below key-value pair

{ Content-Type: application/json }

2. a body that contains the information mentioned above — grant type, client id, client secret, our email, and our password.

"grant_type": "password",
"email": "YOUR_EMAIL",
"password": "YOUR_PASSWORD"
// Note that the "grant_type" value is literally the string "password."

A successful response should return JSON similar to below:

"access_token": "YOUR_ACCESS_TOKEN",
"token_type": "bearer",
"expires_in": 3888000,
"refresh_token": "YOUR_REFRESH_TOKEN",
"created_at": 1540704299

A bad response (likely from an incorrect username/password combo) will return the below response:

{ "response": "authorization_required_for_txid_``" }

If all went well, congrats on submitting your first POST request and getting your bearer/access token. Treat this like your password — you do not want to share this with other people because it will allow them to perform remote actions on your car!

With the token, we can finally start receiving real-time data from your car. Instead of passing around your Tesla username and password like before, we can authenticate ourselves with only a token. For all future GET requests, we should attach the following header (again as a key-value pair):

{ Authorization: Bearer "YOUR_BEARER_TOKEN"}

Note: You will need to add the word “Bearer” as it is above and your bearer token does not have to be in quotes.

The endpoint to hit here is:


It will list your vehicle (or vehicles if you are lucky enough to own more than one).

If you receive the following error:

"response": null,
"error": "vehicle unavailable: {:error=>\"vehicle unavailable:\"}",
"error_description": ""

You should wake up the car from your official Tesla app or turn on your car by pressing the handle. Sometimes your car will go into a deep sleep and will need to be triggered awake manually.

The response should look something like this:

"response": [
"id": "YOUR_ID_HERE"
"vehicle_id": "YOUR_VEHICLE_ID_HERE"
"vin": "YOUR_VIN_HERE",
"display_name": "Curiosity",
"option_codes": "AD15,MDL3,PBSB,RENA,BT37,ID3W"
"color": null,
"tokens": [
"state": "asleep",
"in_service": false,
"id_s": "YOUR_ID_S_HERE",
"calendar_enabled": true,
"api_version": null,
"backseat_token": null,
"backseat_token_updated_at": null
"count": 1

At this point, you should be getting comfortable with sending requests. Before we steamroll ahead, take note of the key “ id_s” . The value of “id_s” if your Vehicle ID, NOT the actual “vehicle_id” key. This is a mistake that most beginners make when trying to access the Tesla API.

To find out the state of the vehicle, we can send another GET request.


You’ll notice that in our URI, we need to send the Vehicle ID we received from Step 2. Again, use the “id_s” value and not the “vehicle_id” value.

We must also send the same header as we did in Step 2. Both the Vehicle ID and Bearer Token will be necessary to continue.

{ Authorization: Bearer "YOUR_BEARER_TOKEN"}

Finally, we receive back our first piece of exciting data. It should respond with:

"response": {
"api_version": 3,
"autopark_state_v3": "standby",
"autopark_style": "dead_man",
"calendar_supported": true,
"car_version": "2018.41 4c56698",
"center_display_state": 0,
"df": 0,
"dr": 0,
"ft": 0,
"homelink_nearby": false,
"is_user_present": false,
"last_autopark_error": "no_error",
"locked": true,
"media_state": {
"remote_control_enabled": true
"notifications_supported": true,
"odometer": 1650.501152,
"parsed_calendar_supported": true,
"pf": 0,
"pr": 0,
"remote_start": false,
"remote_start_supported": true,
"rt": 0,
"software_update": {
"expected_duration_sec": 2700,
"status": ""
"speed_limit_mode": {
"active": false,
"current_limit_mph": 85,
"max_limit_mph": 90,
"min_limit_mph": 50,
"pin_code_set": true
"sun_roof_percent_open": null,
"sun_roof_state": "unknown",
"timestamp": 8546705108352,
"valet_mode": false,
"valet_pin_needed": true,
"vehicle_name": "Curiosity"

We can view certain things in our vehicle state like our odometer, firmware version, valet mode, speed limit, etc.

There are many actions that we can trigger from the API. I would recommend referring back to the Unofficial API documentation as endpoints can be deprecated or act in odd manners (e.g. setting charge limits).

We can do a simple one by starting/stopping climate control in our car. Again, the pattern similarly follows Step 3. This is an example of how RESTful architecture works to standardize the way we interact with APIs.


{ Authorization: Bearer "YOUR_BEARER_TOKEN"}

Auto Conditioning Start Endpoint:


Response (if successful):

"response": {
"reason": "",
"result": true

Auto Conditioning End Endpoint:


Congrats! You’ve made it through to the end. You now know how to generate a bearer token, check your vehicle’s state, as well as perform a remote action. These functions can be integrated into an app or even executed whimsically from your desktop. More likely than not, the official mobile Tesla App is using the same API when you connect with your car.

Keep playing around with different endpoints in the Unofficial API documentation — you never know if and when new features will be added. I hope you enjoyed following along this tutorial.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store