I finally decided to address the Tesla API and work on a project that includes talking to the API. This means of course that I have to take a closer look at how it works and how I can actually make it work with my own code. There are a few wonderful GitHub libraries that you can implement in your own application and a very thorough documentation on the Tesla API, which can be found under http://docs.timdorr.apiary.io. But nonetheless, this all didn’t quite work for me. I’m coding with Swift 2.x in a command line based application as I’m going to make the shift to a fully server-based application in the long run.

Getting Started with Tesla API

The basics that need to be understood when coding with the Tesla API is the underlying protocol – or at least which protocol it tries to follow. In this case we are closely related to the OAuth2.0 protocol. You initiate your API connection by requesting an access token (Bearer token) by throwing a POST request at the server with quite some content in it. So, what is really required to make it work?

  • “grant_type” : “password”
  • “client_id” : [can be found in a link on the apiary docs page]
  • “client_secret” : [can be found in a link on the apiary docs page]
  • “email” : [your personal email address used for the Tesla account]
  • “password” : [your holy grail of passwords as this grants access to the vehicle, if enabled]

The above listed elements are required to be put into the HTTPBody of the request in JSON format. But you also have to pay attention to your header variables. Luckily, there is only one thing you need to set.

  • “Content-Type” : “application/json; charset=utf-8”

Now go ahead and throw this request at the Tesla API server address (https://owner-api.teslamotors.com/oauth/token) and read the access_token from the response. It will look like this:

{ 
    "access_token" : "e5f...e1d",
    "token_type"   : "bearer",
    "expires_in"   : 7776000,
    "created_at"   : 1467907225
}

In the next step you are going to need to request a list of vehicles that are registered under your account. This is going to be straight forward. Throw a GET request at the correct web address from Tesla (https://owner-api.teslamotors.com/api/1/vehicles), but be aware that you need to add your access_token to the headers of the request. You can do that just like you did above with the Content-Type (not needed now!), but now as follows:

  • “Authorization” : “Bearer e5f…e1d”

This in result will grant you a response such as this one:

{
    "response" : [
        {
            "id" : 1132...3230,
            "vehicle_id" : 58...60,
            "vin" : "5YJ...259",
            "display_name" : "Hurricane",
            "option_codes" : "REEU,AD04,X003",
            "color" : null,
            "tokens" : [
                "2903...4468",
                "c13f...9968"
            ],
            "state" : "online",
            "id_s" : "1132...3230",
            "remote_start_enabled" : true,
            "calendar_enabled" : true,
            "notifications_enabled" : true,
            "backseat_token" : null,
            "backseat_token_updated_at" : null
        }
    ],
    "count" : 1
}

All personal information have been shortened with three dots in the middle, in case you were wondering. This list will now provide you the basic information for all vehicles registered under your personal account. The most important information is going to be a personal identifier for use within your application if you plan to use more than one vehicle and the “id”, not the “vehicle_id” or “vin”. This is essential or else your commands and requests cannot be accounted for and you will receive a 404 message. Now you probably want to do some stuff with your Tesla and, for example, would like to request its battery information. We can do that by throwing a GET request at the correct address (https://owner-api.teslamotors.com/api/1/vehicles/11…[Insert your vehicle’s ID]…30/data_request/charge_state) and parsing through the returned JSON object. The web address has to be assembled individually with the vehicle’s “id” – neither “vehicle_id”, nor the digit 1 – but the very long “id” that came with the vehicle list. Additionally, same as above: include the “Authorization” header with your Bearer token and you should get a response like this:

{
    "response" : {
        "charging_state" : "Disconnected",
        "charge_limit_soc" : 90,
        "charge_limit_soc_std" : 90,
        "charge_limit_soc_min" : 50,
        "charge_limit_soc_max" : 100,
        "charge_to_max_range" : false,
        "battery_heater_on" : null,
        "not_enough_power_to_heat" : null,
        "max_range_charge_counter" : 0,
        "fast_charger_present" : null,
        "fast_charger_type" : "",
        "battery_range" : 130.46,
        "est_battery_range" : 123.91,
        "ideal_battery_range" : 104.37,
        "battery_level" : 44,
        "usable_battery_level" : 44,
        "battery_current" : null,
        "charge_energy_added" : null,
        "charge_miles_added_rated" : 0.0,
        "charge_miles_added_ideal" : 0.0,
        "charger_voltage" : null,
        "charger_pilot_current" : null,
        "charger_actual_current" : null,
        "charger_power" : null,
        "time_to_full_charge" : 0.0,
        "trip_charging" : null,
        "charge_rate" : 0.0,
        "charge_port_door_open" : null,
        "motorized_charge_port" : false,
        "scheduled_charging_start_time" : null,
        "scheduled_charging_pending" : false,
        "user_charge_enable_request" : null,
        "charge_enable_request" : true,
        "eu_vehicle" : true,
        "charger_phases" : null,
        "charge_port_latch" : "",
        "charge_current_request" : 32,
        "charge_current_request_max" : 32,
        "managed_charging_active" : false,
        "managed_charging_user_canceled" : false,
        "managed_charging_start_time" : null
    }
}

Feels good to have gotten so far, eh? Took me a while to figure it all out. Contrary to the apiary documentation, for example, the vehicle_id in the URL is NOT a simple 1 or 2, depending on how many vehicles you have in your account, but the actual unique ID that is assigned to your Tesla. Okay, now lets take it a step further and go crazy. How about we set our charge limit to 85%? So this time we need to throw a POST request at the accordingly correct address from Tesla (https://owner-api.teslamotors.com/api/1/vehicles/11…[Insert your ID]…30/command/set_charge_limit) and let’s see if this was actually successful. Make sure you add the Bearer token in your headers and the “id” of the vehicle. The desired percentage has to go into the HTTP body in JSON format similar to the request of the access_token. So, the header information needs to be extended with the following:

  • “Content-Type” : “application/json; charset=utf-8”
  • “Authorization” : “Bearer e5f…e1d”

Your data content will then go in the HTTPBody as follows:

  • “percent” : 85 (alternatively “85”)

You can use the number as both a string or an integer, so basically with or without the quotation marks. Again, in contrary to the apiary documentation, do not add the ?percent=85 at the end of the URL, this will most likely do nothing, it didn’t do anything for me. The resulting response looks like this:

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

Conclusion

The apiary documentation is a very helpful resource for the various functions of the Tesla API and the parameters they take, but the actual “making it work” seems to be quite off there. It’s been a great first start knowing how to get to work with the API and the next step in the game will be to implement the Streaming API for the Tesl, which should provide additional information on the vehicle’s current state. But that’s going to be another blog post sometime in the future. Have fun and good luck coding! 😊

If you enjoy this type of content, I’d love to enjoy a cup of coffee while typing the next one!