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.
Using @timdorr's documentation (Authentication) I was able to get my scripts working with the new authentication scheme. Since the only user of my scripts is me, I skipped the whole HTML parsing part, and instead I just put the URL from step 1 into a web browser, login to the website, then using the web browser's network debug tool, I copy the authentication code out of the Location header. I plug that code back into my script, which does the rest. I figure I only have to do the initial login once, and then use the refresh tokens after that, so there's not much point in putting more effort into the first part.
Have you got a working refresh script as I have valid tokens but have been unable to generate a new pair using the new refresh token.

Thanks
 
Have you got a working refresh script as I have valid tokens but have been unable to generate a new pair using the new refresh token.

Thanks

Yes. It's more proof of concept than finished script, but it does work!

Code:
#!/usr/bin/env python3

import requests
import json

token = input('Enter OAuth refresh token: ')

payload = {
    'grant_type': 'refresh_token',
    'client_id': 'ownerapi',
    'refresh_token': token,
    'scope': 'openid email offline_access'
}

r = requests.post('https://auth.tesla.com/oauth2/v3/token', json=payload)

data = r.json()
print(data)

headers = {'Authorization': f"Bearer {data['access_token']}"}
payload = {
    'grant_type': 'urn:ietf:params:oauth:grant-type:jwt-bearer',
    'client_id': 'xxxx',
    'client_secret': 'xxxx'
}

r = requests.post('https://owner-api.teslamotors.com/oauth/token', headers=headers, json=payload)
tokens = r.json()
tokens['oauth2_refresh_token'] = data['refresh_token']
print(json.dumps(tokens, indent=4, separators=(',', ': ')))

Note, you'll have to fill in the client id and client secret in the second payload. Also, be sure to use the right refresh token. It's the really long one! (It's the one you get from auth.tesla.com, not from owner-api.teslamotors.com.)
 
Yes. It's more proof of concept than finished script, but it does work!

Code:
#!/usr/bin/env python3

import requests
import json

token = input('Enter OAuth refresh token: ')

payload = {
    'grant_type': 'refresh_token',
    'client_id': 'ownerapi',
    'refresh_token': token,
    'scope': 'openid email offline_access'
}

r = requests.post('https://auth.tesla.com/oauth2/v3/token', json=payload)

data = r.json()
print(data)

headers = {'Authorization': f"Bearer {data['access_token']}"}
payload = {
    'grant_type': 'urn:ietf:params:oauth:grant-type:jwt-bearer',
    'client_id': 'xxxx',
    'client_secret': 'xxxx'
}

r = requests.post('https://owner-api.teslamotors.com/oauth/token', headers=headers, json=payload)
tokens = r.json()
tokens['oauth2_refresh_token'] = data['refresh_token']
print(json.dumps(tokens, indent=4, separators=(',', ': ')))

Note, you'll have to fill in the client id and client secret in the second payload. Also, be sure to use the right refresh token. It's the really long one! (It's the one you get from auth.tesla.com, not from owner-api.teslamotors.com.)
Excellent, thanks I'll have a play tomorrow.
 
I appreciate those of you that are waaaaaayyyyy smarter on this stuff than I am for sorting all this out. I had been continuing to use VisibleTesla since mid-2016 but over Christmas with help of my daughter got a very basic logger of my own created via python. Had just got it where I had shut down VT when the change the new auth system rendered my python script inoperable.

I've just successfully pulled in the new method to login and generate a token such that I have my code back up and running. That may not seem like much, but for someone with programming skills still rooted in FORTRAN77, even taking a python code block off github and splicing it back into what I had was not trivial. I'm as much needing to teaching myself python at the same time as I'm trying to comprehend the auth change. I'm also doing all this now without out the help of my daughter as spring term for her has started and I've returned back overseas where I'm on assignment. That's where having functioning code again is really nice being able to monitor and log my charging sessions from 14 time zones away from my car!

Thanks again for those that helped document this stuff for those of us that others would be totally out of luck.
 
I have a question about anyones experience with a couple of the values returned by the charge state API call.

I logged data today for a charging session with my Gen1 UMC at 240V / 40 amp. Everything with the actual charging worked fine and I logged basic charging parameters through my charge such as SOC, reported rated miles, etc.

One looks odd are the values returned for "charge_energy_added" and "charge_miles_added_rated". Both values report 0 for about the first 20 minutes. At that point both values start counting up, with the miles_added value tracking 1:1 with the incremental range reported through the end of the charging session. Net of this is that when charging completes both values are under reported by the amount of miles/energy added over that first 20 minutes of charging.

Anyone else ever notice anything like this? As I've commented in other posts, I'm converting over from VisibleTesla finally, gradually building up my own logger to capture similar data. That's where I was looking at the "charge_energy_added" value today to see how it equates to the value that VT would report when I'd generate a charging sessions report.

Probably be about a week before I'd plan to charge again and have another dataset to see if today's experience is consistent or a fluke.

Thanks!
 
I have a question about anyones experience with a couple of the values returned by the charge state API call.

I logged data today for a charging session with my Gen1 UMC at 240V / 40 amp. Everything with the actual charging worked fine and I logged basic charging parameters through my charge such as SOC, reported rated miles, etc.

One looks odd are the values returned for "charge_energy_added" and "charge_miles_added_rated". Both values report 0 for about the first 20 minutes. At that point both values start counting up, with the miles_added value tracking 1:1 with the incremental range reported through the end of the charging session. Net of this is that when charging completes both values are under reported by the amount of miles/energy added over that first 20 minutes of charging.

Anyone else ever notice anything like this? As I've commented in other posts, I'm converting over from VisibleTesla finally, gradually building up my own logger to capture similar data. That's where I was looking at the "charge_energy_added" value today to see how it equates to the value that VT would report when I'd generate a charging sessions report.

Probably be about a week before I'd plan to charge again and have another dataset to see if today's experience is consistent or a fluke.

Thanks!

Maybe heating of the battery?
 
Maybe heating of the battery?
Heating the battery does not explain it for me.
The issue isn't that the actual SOC or rated range does not increase during the first 20 minutes. Those values both start incrementing from when the battery first starts charging.
Charging starts at 7:54 am with reported SOC = 56% and RM = 159.99.
By 8:25 am reported SOC = 62% and RM = 167.64. That says I've added over that period of time about 6% and 17 miles range. However the add_miles and added_kW values are both still reporting 0.

Then suddenly around 8:30 am both the added_miles and added_kW start to increment. When charging stops at 9:06 am, I'm at 70% SOC and RM = 188.74. That says I've added a total of ~38.75 miles, but the value reported over the API only says added_miles = 17.5, so short the ~20 miles that were already added by the time the car starts to report the value.

Maybe I chalk it up to an aging MCU1 that is beginning to act flaky. I'd try resetting the MCU to see if that causes it to behave, but I'm on assignment in overseas location at the moment and monitoring my car remotely with it back at my home in the US.
 
  • Like
Reactions: goRt
Yes. It's more proof of concept than finished script, but it does work!
Note, you'll have to fill in the client id and client secret in the second payload. Also, be sure to use the right refresh token. It's the really long one! (It's the one you get from auth.tesla.com, not from owner-api.teslamotors.com.)
Are the client ID and the client secret the same as they were in the old system? If not where does one find them? I set up code in Python to do a few things years ago but I can't remember where I found this info.
 
Using @timdorr's documentation (Authentication) I was able to get my scripts working with the new authentication scheme. Since the only user of my scripts is me, I skipped the whole HTML parsing part, and instead I just put the URL from step 1 into a web browser, login to the website, then using the web browser's network debug tool, I copy the authentication code out of the Location header. I plug that code back into my script, which does the rest. I figure I only have to do the initial login once, and then use the refresh tokens after that, so there's not much point in putting more effort into the first part.
@markb1 - Just to clarify you only have to do steps 1&2 (as defined here) one time to get an auth code and then you can just reuse that auth code every 45 days (or more frequently if you wish) to get a bearer token. Is that correct?
 
@markb1 - Just to clarify you only have to do steps 1&2 (as defined here) one time to get an auth code and then you can just reuse that auth code every 45 days (or more frequently if you wish) to get a bearer token. Is that correct?

I think it's the refresh_token you reuse every 45 days to get a new bearer token (from step 3) and then a new token from step 4 using the bearer token (within 300s)
 
@markb1 - Just to clarify you only have to do steps 1&2 (as defined here) one time to get an auth code and then you can just reuse that auth code every 45 days (or more frequently if you wish) to get a bearer token. Is that correct?

I think it's the refresh_token you reuse every 45 days to get a new bearer token (from step 3) and then a new token from step 4 using the bearer token (within 300s)

Correct, it's the refresh token. The python script I posted above does everything that I expect to need from here on out. The initial login steps are actually 1, 2, 3, and 4. And then the refresh steps are 5 and then 4. So the 5,4 part is the only part I have to repeat.
 

I'm using the above PHP code which has been updated for the new SSO auth scheme. It fails on Step 2 (obtain auth code). As far as I can tell, it correctly retrieves the "hidden" form inputs and cookie value, but a subsequent call to the /oauth2/v3/authorize endpoint returns HTTP 403 (forbidden) instead of HTTP 302 (redirect).

Several other users commented on github that it recently stopped working for them so I guess I'm not alone. Anyone figure out a fix?
 
I have a python script that does the new SSO auth scheme Steps 1-4 that works. I have saved the final tokens from step 4 and have been using those successfully for about 4 weeks to run my logger routine, having restarted many times just using this save token file. I'm not wanting to extend this do do the refresh to get updated tokens as the tokens near their expiration date.

However, I'm still struggling to get the refresh token steps 5 and then repeat of step 4 to work to get an updated token before my original set expire. Let me try playing back what I think I understand, what I have working, and what's not working.

What I thought I now understand is I need to save the really long access token from Step 3, then use this is Step 5, and then use it 40-45 days later to do step 5, then using the access_token from step 5 to then redo step 4? I thought the info from Step 3 would expire in 300 sec, but I can still use that save long access_token 40ish days later?
 
I have a python script that does the new SSO auth scheme Steps 1-4 that works. I have saved the final tokens from step 4 and have been using those successfully for about 4 weeks to run my logger routine, having restarted many times just using this save token file. I'm not wanting to extend this do do the refresh to get updated tokens as the tokens near their expiration date.

However, I'm still struggling to get the refresh token steps 5 and then repeat of step 4 to work to get an updated token before my original set expire. Let me try playing back what I think I understand, what I have working, and what's not working.

What I thought I now understand is I need to save the really long access token from Step 3, then use this is Step 5, and then use it 40-45 days later to do step 5, then using the access_token from step 5 to then redo step 4? I thought the info from Step 3 would expire in 300 sec, but I can still use that save long access_token 40ish days later?
Step 3 creates a bearer token valid for 300s which is exchanged for an access token in step 4 - within that is the long refresh token you require in step 5
The refresh token from 4 is then used in step 5 to create a bearer token 300s that is then taken through step 4 to create a new 45 day set of tokens (access and refresh)
There's some conjecture that the refresh token doesn't expire - I've not tested that.
 
Step 3 creates a bearer token valid for 300s which is exchanged for an access token in step 4 - within that is the long refresh token you require in step 5
The refresh token from 4 is then used in step 5 to create a bearer token 300s that is then taken through step 4 to create a new 45 day set of tokens (access and refresh)
There's some conjecture that the refresh token doesn't expire - I've not tested that.
@goRt - Thanks. Last night I went through the full Step 1-4, saving the full bearer token response from Step 3 with the long refresh token which I had not done previously. I then successfully used this information to successfully do Step 5 / repeat Step 4 to generate a new access token. I did the step 5-4 sequence about 30 minutes after the initial Step 1-4 to prove I'm doing the steps now correctly. It's the part about whether the long refresh token from Step 3 has some time expiration limit on it that was confusing me.

I have all this inside a logger program that I've created. At the moment I can set through a set of configs for my logger to run to some fixed date/time. Each time it starts it currently checks and if the token is going to expire within a few days it would just go ahead and redo the full login to generate and save new tokens. I'm looking to update that now to automatically track the token expiration and as needed do the refresh automatically. Not sure I'll ever have this running continuously for over 45 days, but that's what I'm trying to work towards. So far about 8 days continuous is my current streak, mainly limited by how often I have made upgrades/bug fixes so that I'm wanting to restart it anyway. However I'm starting to reach a pretty stable logger core, so now starting to work more and more on secondary data analysis routines that process off my saved datalog files, and with that, I anticipate leaving the logger running uninterrupted for longer and longer periods.

While I call it a logger, I've been able to get running well is an automated charging management routine. I'm actually overseas on an expat assignment at the moment with my car parked in my garage back in the US. What I like doing is routinely charging it up to around 70%, let it sit until the battery drops back down to around 50% and repeat. I know I can just let the car maintain at the minimum 50% set point, but this every week or so to do a 50-70% charge cycle is nearer what I'd be doing in daily driving. This lets the BMS at least see some range of charge to try and remain a decent BMS calibration. My logger now tracks SOC and using a predefined set of min/max limits, automatically manages those charge cycle. Soon as it sees it below the min limit, will automatically reset the charge limit to my defined max (70%) and the car starts to charge. Once charge is completed, it automatically resets the charge limit back to the min allowed 50% value.

So for a guy that hasn't done any computer programming since the late 1980s with FORTRAN77, getting that going within Python on my MacBook Air to replace VisibleTesla has been a massive achievement for me, having to both figure out the Tesla API but also learn Python to a level that I can even follow/understand the code blocks that others have posted on places like GitHub.

So again, for all of you that continue indulge 'rookie' questions from folks like me, THANKS!
 
  • Like
Reactions: goRt
@PCMc would you mind sharing your Python code for steps 1-4? I’ve been looking at the source code for teslapy but that script is not very readable.
@apacheguy - The base code block I'm using is from enode-engineering/tesla-oauth2

Not sure if that the same telsapy your referring to or not. I'll admit it took me a bit to figure out how to adapt it.

My base Tesla API core originated from the TeslaAPI function from Vega-daniel/Tesla_API

My use of the new Step 1-4 from enode-engineering has been inserted back into that to replace the base authorization process. Big thing to add to this logic is saving the response token information from Step 3 if you then want to be able to do the refresh process. That tripped me up for a bit.

I'll admit as someone that had not used Python or even object oriented programming languages, it took me quite a bit to figure out how to cut and paste it in. I think the challenge with trying to adapt any other's scripts is understanding how data values are being transferred between the various methods / functions. I won't pretend to say I understand all of what's going on inside Steps 1 and 2, but it works, and I'm not about to try and figure it out more for risk of breaking it!

I'm not opposed to sharing my code, but how I've customized much of this around my own data structures, none of which I'll claim as elegant, not sure if it would help or just further confuse.
 
  • Like
Reactions: apacheguy