11"""Tesla Fleet API for Python."""
22
33from json import dumps
4- from typing import Any , Awaitable
4+ from typing import Any , Awaitable , Callable
55import aiohttp
66
77from tesla_fleet_api .tesla .tesla import Tesla
88from tesla_fleet_api .exceptions import raise_for_status , InvalidRegion , LibraryError , ResponseError
9- from tesla_fleet_api .const import SERVERS , Method , LOGGER
9+ from tesla_fleet_api .const import SERVERS , Method , LOGGER , Scope
1010from tesla_fleet_api import __version__ as VERSION
1111
1212# Based on https://developer.tesla.com/docs/fleet-api
@@ -18,7 +18,7 @@ class TeslaFleetApi(Tesla):
1818 server : str | None = None
1919 session : aiohttp .ClientSession
2020 headers : dict [str , str ]
21- refresh_hook : Awaitable | None = None
21+ refresh_hook : Callable [[], Awaitable [ str | None ]] | None = None
2222
2323 def __init__ (
2424 self ,
@@ -31,7 +31,7 @@ def __init__(
3131 partner_scope : bool = True ,
3232 user_scope : bool = True ,
3333 vehicle_scope : bool = True ,
34- refresh_hook : Awaitable | None = None ,
34+ refresh_hook : Callable [[], Awaitable [ str | None ]] | None = None ,
3535 ):
3636 """Initialize the Tesla Fleet API."""
3737
@@ -149,3 +149,46 @@ async def products(self) -> dict[str, Any]:
149149 Method .GET ,
150150 "api/1/products" ,
151151 )
152+
153+ async def partner_login (
154+ self ,
155+ client_id : str ,
156+ client_secret : str ,
157+ scopes : list [Scope ] = [Scope .VEHICLE_DEVICE_DATA ],
158+ ) -> dict [str , Any ]:
159+ """Generate a partner token using client credentials authentication.
160+
161+ Args:
162+ client_id: Partner application client ID
163+ client_secret: Partner application client secret
164+ scopes: Optional list of scopes to request
165+
166+ Returns:
167+ Dictionary containing access token and token metadata
168+ """
169+
170+ # Throw if there is no server set
171+ if not self .server :
172+ raise ValueError ("Server was not set at init. Call find_server() first." )
173+
174+ data = {
175+ "grant_type" : "client_credentials" ,
176+ "client_id" : client_id ,
177+ "client_secret" : client_secret ,
178+ "audience" : self .server ,
179+ "scope" : " " .join (scopes ),
180+ }
181+
182+ async with self .session .post (
183+ "https://fleet-auth.prd.vn.cloud.tesla.com/oauth2/v3/token" ,
184+ headers = {"Content-Type" : "application/x-www-form-urlencoded" },
185+ data = data ,
186+ ) as resp :
187+ if resp .ok :
188+ token_data = await resp .json ()
189+ # Set the access token for subsequent API calls
190+ self .access_token = token_data ["access_token" ]
191+ return token_data
192+ else :
193+ error_data = await resp .json ()
194+ raise ValueError (f"Partner login failed: { error_data } " )
0 commit comments