tesla_api 3.0.3 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 36800b87fde594b317de4423717ddddde20b02a89a29dcc3030da421c857961d
4
- data.tar.gz: a7578ddecc3e79faaf4b91eec431196fdd42cc6b2697d8a47c115a9839beb13d
3
+ metadata.gz: 5b774bab2f43b76262fa9c4ab04ae250f9f325955f028d3c8bd44416f5a015f5
4
+ data.tar.gz: 157c7c913712cd7bc3e7412aead4225c5502b26399f7dcf2243a3f522c72cec9
5
5
  SHA512:
6
- metadata.gz: 4cefac51f88134ddb5cf93567046c63249c48aac76c19ea95006f7a8f98e97ad2258c1d4969be3cedc3dd8e3ec8ad21513cc1b29913982f11b2263ca44e2bc2e
7
- data.tar.gz: 3724b8215a83bd514ab27ddc02165793052f54dfb1bfc45cfe3f90c18fd50395dcedadd4e7070c3469d2f5557fb3354c02e97a3850e33c2d1ed8c397b4e8cef9
6
+ metadata.gz: 1354ad7bf60037cf9e09541d7122aed4448946262177e0c6a535f303fde5e5a479f15b2bda193102e305ec2f0743e9d4499aff27cbc2a452add543d64ee1157c
7
+ data.tar.gz: 980f1b1d752b674ab29ab82982c4ff687f3f22b62dc0c1d5aa138ef5fdd458393a7cea7177f67ae15ae64635154cd45eb7b70cf1bab12affa2c33ad9e622b32e
@@ -0,0 +1,36 @@
1
+ name: Tests
2
+
3
+ on:
4
+ push:
5
+ branches: [master]
6
+ pull_request:
7
+ branches: [master]
8
+
9
+ jobs:
10
+ test:
11
+ name: Test Suite
12
+ runs-on: ubuntu-latest
13
+
14
+ env:
15
+ TESLA_EMAIL: elon.musk@teslamotors.com
16
+ TESLA_PASS: oilLOL
17
+ TESLA_CLIENT_ID: 1
18
+ TESLA_CLIENT_SECRET: 2
19
+ TESLA_ACCESS_TOKEN: 3
20
+ TESLA_REFRESH_TOKEN: 4
21
+
22
+ strategy:
23
+ matrix:
24
+ ruby-version: ['2.7', '3.0']
25
+
26
+ steps:
27
+ - uses: actions/checkout@v2
28
+
29
+ - name: Set up Ruby
30
+ uses: ruby/setup-ruby@v1
31
+ with:
32
+ ruby-version: ${{ matrix.ruby-version }}
33
+ bundler-cache: true
34
+
35
+ - name: Run test suite
36
+ run: bundle exec rake
@@ -1 +1 @@
1
- ruby 2.6.4
1
+ ruby 2.7.2
@@ -1,6 +1,6 @@
1
1
  # Introduction
2
2
 
3
- This is unofficial documentation of the Tesla JSON API used by their iOS and Android apps. It features functionality to monitor and control their vehicle (Model S, Model X, and Model 3) and power (Powerwall) products. We currently have documentation for their vehicles, but always accept [pull requests](https://github.com/timdorr/tesla-api/pulls) for improvements and additions.
3
+ This is unofficial documentation of the Tesla JSON API used by their iOS and Android apps. It features functionality to monitor and control their vehicle (Models S, 3, X, Y) and power (Powerwall) products. We currently have documentation for their vehicles, but always accept [pull requests](https://github.com/timdorr/tesla-api/pulls) for improvements and additions.
4
4
 
5
5
  ## Before You Begin
6
6
 
@@ -4,9 +4,129 @@ description: The authentication process for the Tesla API
4
4
 
5
5
  # Authentication
6
6
 
7
- ## POST `/oauth/token?grant_type=password`
7
+ > ## This is a work in progress ⚠
8
+ >
9
+ > Tesla has deprecated the `/oauth/token` endpoint in favor of using `auth.tesla.com`. I'm working on updating the documentation as soon as possible. This documentation is still missing handling for MFA users. Feel free to discuss this in [issue #260](https://github.com/timdorr/tesla-api/issues/260).
8
10
 
9
- The initial authentication process is via [an OAuth 2.0 Password Grant](https://oauth.net/2/grant-types/password/) with the same credentials used for tesla.com and the mobile apps.
11
+ Tesla uses a separate SSO service (auth.tesla.com) for authentication across their app and website. This service is designed around a browser-based flow using OAuth 2.0, but also appears to have support for Open ID Connect. This supports both obtaining an access token and refreshing it as it expires.
12
+
13
+ ## Logging in
14
+
15
+ ### Step 1: Obtain the login page
16
+
17
+ Subsequent requests to the SSO service will require a "code challenge" and "code verifier". These are just a random 86-character string and its SHA-256 hash. Both must be encoded in base64 with url-safe encoding (base64url). Here is an example of generating them in Ruby, but you can apply this same process to other languages.
18
+
19
+ ```ruby
20
+ code_verifier = random_string(86)
21
+ code_challenge = Base64.urlsafe_encode64(Digest::SHA256.hexdigest(code_verifier))
22
+ code_verifier = Base64.urlsafe_encode64(code_verifier)
23
+ ```
24
+
25
+ You will also need a stable `state` value for requests, which is a random string of any length.
26
+
27
+ #### GET `https://auth.tesla.com/oauth2/v3/authorize`
28
+
29
+ The first request returns HTML intended for display in the browser. You will need to parse this HTML for hidden input fields.
30
+
31
+ The request is made with a `redirect_url` of "https://auth.tesla.com/void/callback", which is a non-existent page. The Tesla app intercepts the request to this page to capture the authorization code.
32
+
33
+ ##### Request parameters
34
+
35
+ | Field | Type | Example | Description |
36
+ | :---------------------- | :--------------- | :------------------------------------- | :-------------------------------------------------------------- |
37
+ | `client_id` | String, required | `ownerapi` | The OAuth client ID. Always "ownerapi" |
38
+ | `code_challenge` | String, required | `123` | The "code challenge" |
39
+ | `code_challenge_method` | String, required | `S256` | The code challenge hash method. Always "S256" (SHA-256) |
40
+ | `redirect_uri` | String, required | `https://auth.tesla.com/void/callback` | The redirect URL. Always "https://auth.tesla.com/void/callback" |
41
+ | `response_type` | String, required | `code` | The type of expected response. Always "code" |
42
+ | `scope` | String, required | `openid email offline_access` | The authentication scope. Always "openid email offline_access" |
43
+ | `state` | String, required | `123` | The OAuth state value. Any random string. |
44
+
45
+ ##### Response
46
+
47
+ This returns an HTML response body. There will be a `<form>` with hidden `<input>` elements that contain session-based information to prevent CSRF attacks. At the moment, they appear to be `_csrf`, `_phase`, `_process`, `transaction_id`, and `cancel`, but they may change due to server-side changes by Tesla. These must be provided in the POST body to validate the following request.
48
+
49
+ The response will also include a `set-cookie` header that includes a session ID cookie. This should be provided to the following request as a `Cookie` header so that the SSO service can match up your request with private data it has in that session.
50
+
51
+ ### Step 2: Obtain an authorization code
52
+
53
+ This will simulate a user submitting the form from the previous request in their browser. Ensure that the hidden `<input>`s are provided as POST body parameters and the `Cookie` header is set.
54
+
55
+ #### POST `https://auth.tesla.com/oauth2/v3/authorize`
56
+
57
+ ```http
58
+ Cookie: {cookie value from set-cookie header}
59
+ ```
60
+
61
+ ##### Request parameters
62
+
63
+ > Note: These are query parameters, not part of the POST body
64
+
65
+ | Field | Type | Example | Description |
66
+ | :---------------------- | :--------------- | :------------------------------------- | :-------------------------------------------------------------- |
67
+ | `client_id` | String, required | `ownerapi` | The OAuth client ID. Always "ownerapi" |
68
+ | `code_challenge` | String, required | `123` | The "code challenge" |
69
+ | `code_challenge_method` | String, required | `S256` | The code challenge hash method. Always "S256" (SHA-256) |
70
+ | `redirect_uri` | String, required | `https://auth.tesla.com/void/callback` | The redirect URL. Always "https://auth.tesla.com/void/callback" |
71
+ | `response_type` | String, required | `code` | The type of expected response. Always "code" |
72
+ | `scope` | String, required | `openid email offline_access` | The authentication scope. Always "openid email offline_access" |
73
+ | `state` | String, required | `123` | The OAuth state value. Any random string. |
74
+
75
+ > Note: This is the contents of the POST body. These should be form encoded (`application/x-www-form-urlencoded`).
76
+
77
+ | Field | Type | Example | Description |
78
+ | :----------------- | :----------------- | :------------------ | :------------------------------------------------ |
79
+ | hidden input names | String[], required | hidden input values | The fields from the HTML's hidden `<input>`s |
80
+ | `identity` | String, required | `elon@tesla.com` | The email for the authenticating Tesla account |
81
+ | `credential` | String, required | `brbgoingtomars` | The password for the authenticating Tesla account |
82
+
83
+ ##### Response
84
+
85
+ This will respond with a 302 HTTP response code, which will attempt to redirect to the redirect_uri with additional query parameters added. This new URL is located in the `location` header. You should not follow it, as it is non-existent. Instead, you should parse this URL and extract the `code` query parameter, which is your authorization code.
86
+
87
+ ### Step 3: Exchange authorization code for bearer token
88
+
89
+ #### POST `https://auth.tesla.com/oauth2/v3/token`
90
+
91
+ This is a standard [OAuth 2.0 Authorization Code exchange](https://oauth.net/2/grant-types/authorization-code/). This endpoint uses JSON for the request and response bodies.
92
+
93
+ ##### Request parameters
94
+
95
+ | Field | Type | Example | Description |
96
+ | :-------------- | :--------------- | :------------------------------------- | :-------------------------------------------------------------- |
97
+ | `grant_type` | String, required | `authorization_code` | TThe type of OAuth grant. Always "authorization_code" |
98
+ | `client_id` | String, required | `ownerapi` | The OAuth client ID. Always "ownerapi" |
99
+ | `code` | String, required | `123` | The authorization code from the last request. |
100
+ | `code_verifier` | String, required | `123` | The code verifier string generated previously. |
101
+ | `redirect_uri` | String, required | `https://auth.tesla.com/void/callback` | The redirect URL. Always "https://auth.tesla.com/void/callback" |
102
+
103
+ ```json
104
+ {
105
+ "grant_type": "authorization_code",
106
+ "client_id": "ownerapi",
107
+ "code": "123",
108
+ "code_verifier": "123",
109
+ "redirect_uri": "https://auth.tesla.com/void/callback"
110
+ }
111
+ ```
112
+
113
+ ##### Response
114
+
115
+ ```json
116
+ {
117
+ "access_token": "eyJaccess",
118
+ "refresh_token": "eyJrefresh",
119
+ "expires_in": 300,
120
+ "state": "of the union",
121
+ "token_type": "Bearer"
122
+ }
123
+ ```
124
+
125
+ ### Step 4: Exchange bearer token for access token
126
+
127
+ #### POST `https://owner-api.teslamotors.com/oauth/token`
128
+
129
+ This endpoint follows [RFC 7523](https://tools.ietf.org/html/rfc7523) to exchange a JWT access token from the SSO service for an access token usable by the Owner API.
10
130
 
11
131
  The current client ID and secret are [available here](https://pastebin.com/pS7Z6yyP).
12
132
 
@@ -18,29 +138,30 @@ Authorization: Bearer {access_token}
18
138
 
19
139
  The access token has a 45 day expiration.
20
140
 
21
- ### Request parameters
141
+ ##### Request parameters
22
142
 
23
- | Field | Type | Example | Description |
24
- | :-------------- | :--------------- | :--------------------- | :------------------------------------------------ |
25
- | `grant_type` | String, required | `password` | The type of OAuth grant. Always "password" |
26
- | `client_id` | String, required | `abc` | The OAuth client ID |
27
- | `client_secret` | String, required | `123` | The OAuth client secret |
28
- | `email` | String, required | `elon@teslamotors.com` | The email for the authenticating Tesla account |
29
- | `password` | String, required | `edisonsux` | The password for the authenticating Tesla account |
143
+ > Important: Ensure you are using the `access_token` from the SSO service here. The returned access_token is for all other requests to the Owner API.
30
144
 
31
- ### Request
145
+ ```http
146
+ Authorization: Bearer {access_token}
147
+ ```
148
+
149
+ | Field | Type | Example | Description |
150
+ | :-------------- | :--------------- | :-------------------------------------------- | :---------------------------------------------------------------------------- |
151
+ | `grant_type` | String, required | `urn:ietf:params:oauth:grant-type:jwt-bearer` | The type of OAuth grant. Always "urn:ietf:params:oauth:grant-type:jwt-bearer" |
152
+ | `client_id` | String, required | `abc` | The OAuth client ID |
153
+ | `client_secret` | String, required | `123` | The OAuth client secret |
154
+
155
+ ##### Request
32
156
 
33
157
  ```json
34
158
  {
35
- "grant_type": "password",
159
+ "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
36
160
  "client_id": "abc",
37
- "client_secret": "123",
38
- "email": "elon@teslamotors.com",
39
- "password": "edisonsux"
40
- }
161
+ "client_secret": "123"
41
162
  ```
42
163
 
43
- ### Response
164
+ ##### Response
44
165
 
45
166
  ```json
46
167
  {
@@ -52,38 +173,44 @@ The access token has a 45 day expiration.
52
173
  }
53
174
  ```
54
175
 
55
- ## POST `/oauth/token?grant_type=refresh_token`
176
+ ## Refreshing an access token
177
+
178
+ #### POST `https://auth.tesla.com/oauth2/v3/token`
56
179
 
57
- You can use the `refresh_token` from the Password Grant to do [an OAuth 2.0 Refresh Token Grant](https://oauth.net/2/grant-types/refresh-token/) and obtain a new access token. Note: This will invalidate the previous access token.
180
+ This uses the SSO `refresh_token` from Step 3 above to do an [OAuth 2.0 Refresh Token Grant](https://oauth.net/2/grant-types/refresh-token/). _This does not work with the `refresh_token` provided by the Owner API._ Those have no use currently and should be discarded.
58
181
 
59
- ### Request parameters
182
+ This refreshed access token can be used with the Owner API to obtain a new access token for that service using the exact same request as Step 4 above.
60
183
 
61
- | Field | Type | Example | Description |
62
- | :-------------- | :--------------- | :-------------- | :-------------------------------------------------------- |
63
- | `grant_type` | String, required | `refresh_token` | The type of OAuth grant. Always "refresh_token" |
64
- | `client_id` | String, required | `abc` | The OAuth client ID |
65
- | `client_secret` | String, required | `123` | The OAuth client secret |
66
- | `refresh_token` | String, required | `cba321` | The refresh token returned from a previous token request. |
184
+ This endpoint uses JSON for the request and response bodies.
67
185
 
68
- ### Request
186
+ ##### Request parameters
187
+
188
+ | Field | Type | Example | Description |
189
+ | :-------------- | :--------------- | :---------------------------- | :------------------------------------------------------------- |
190
+ | `grant_type` | String, required | `refresh_token` | TThe type of OAuth grant. Always "refresh_token" |
191
+ | `client_id` | String, required | `ownerapi` | The OAuth client ID. Always "ownerapi" |
192
+ | `client_secret` | String, required | `123` | The OAuth client ID. |
193
+ | `refresh_token` | String, required | `123` | The refresh token from a prior authentication. |
194
+ | `scope` | String, required | `openid email offline_access` | The authentication scope. Always "openid email offline_access" |
69
195
 
70
196
  ```json
71
197
  {
72
- "grant_type": "refresh_token",
73
- "client_id": "abc",
198
+ "grant_type": "authorization_code",
199
+ "client_id": "ownerapi",
74
200
  "client_secret": "123",
75
- "refresh_token": "cba321"
201
+ "refresh_token": "eyJrefresh",
202
+ "scope": "openid email offline_access"
76
203
  }
77
204
  ```
78
205
 
79
- ### Response
206
+ ##### Response
80
207
 
81
208
  ```json
82
209
  {
83
- "access_token": "abc123",
84
- "token_type": "bearer",
85
- "expires_in": 3888000,
86
- "refresh_token": "cba321",
87
- "created_at": 1538359034
210
+ "access_token": "eyJaccess",
211
+ "refresh_token": "eyJrefresh",
212
+ "id_token": "id",
213
+ "expires_in": 300,
214
+ "token_type": "Bearer"
88
215
  }
89
216
  ```
@@ -35,7 +35,7 @@ Retrieve a list of your owned vehicles (includes vehicles not yet shipped!)
35
35
  "in_service": false,
36
36
  "id_s": "12345678901234567",
37
37
  "calendar_enabled": true,
38
- "api_version": 4,
38
+ "api_version": 7,
39
39
  "backseat_token": null,
40
40
  "backseat_token_updated_at": null
41
41
  }
@@ -50,9 +50,9 @@ These resources are read-only and determine the state of the vehicle's various s
50
50
 
51
51
  ### URL parameters
52
52
 
53
- | Field | Example | Description |
54
- | :--- | :--- | :--- |
55
- | `id` | `12345678901234567` | The `id` of the car. (Not the `vehicle_id`!) |
53
+ | Field | Example | Description |
54
+ | :---- | :------------------ | :------------------------------------------- |
55
+ | `id` | `12345678901234567` | The `id` of the car. (Not the `vehicle_id`!) |
56
56
 
57
57
  ### Response
58
58
 
@@ -70,10 +70,9 @@ These resources are read-only and determine the state of the vehicle's various s
70
70
  "in_service": false,
71
71
  "id_s": "12345678901234567",
72
72
  "calendar_enabled": true,
73
- "api_version": 4,
73
+ "api_version": 7,
74
74
  "backseat_token": null,
75
75
  "backseat_token_updated_at": null
76
76
  }
77
77
  }
78
78
  ```
79
-
@@ -1,6 +1,6 @@
1
1
  # Endpoints File
2
2
 
3
- This the latest contents of the ownerapi_endpoints.json file from the 3.10.0 version of the app.
3
+ This the latest contents of the ownerapi_endpoints.json file from the 3.10.8 version of the app.
4
4
 
5
5
  ```json
6
6
  {
@@ -329,10 +329,11 @@ This the latest contents of the ownerapi_endpoints.json file from the 3.10.0 ver
329
329
  "URI": "api/1/vehicles/{vehicle_id}/eligible_upgrades",
330
330
  "AUTH": true
331
331
  },
332
- "AUTOPILOT_UPGRADE_URL": {
332
+ "UPGRADES_PAGE": {
333
333
  "TYPE": "GET",
334
- "URI": "api/1/vehicles/{vehicle_id}/purchase_url",
335
- "AUTH": true
334
+ "URI": "upgrades_page",
335
+ "AUTH": true,
336
+ "CONTENT": "HTML"
336
337
  },
337
338
  "MESSAGE_CENTER_MESSAGE_LIST": {
338
339
  "TYPE": "GET",
@@ -430,6 +431,12 @@ This the latest contents of the ownerapi_endpoints.json file from the 3.10.0 ver
430
431
  "URI": "api/1/energy_sites/{site_id}/site_info",
431
432
  "AUTH": true
432
433
  },
434
+ "ENERGY_SERVICE_SCHEDULING_PAGE": {
435
+ "TYPE": "GET",
436
+ "URI": "energy_service_scheduling_page",
437
+ "AUTH": true,
438
+ "CONTENT": "HTML"
439
+ },
433
440
  "HISTORY_DATA": {
434
441
  "TYPE": "GET",
435
442
  "URI": "api/1/energy_sites/{site_id}/history",
@@ -440,11 +447,26 @@ This the latest contents of the ownerapi_endpoints.json file from the 3.10.0 ver
440
447
  "URI": "api/1/energy_sites/{site_id}/calendar_history",
441
448
  "AUTH": true
442
449
  },
450
+ "SAVINGS_FORECAST": {
451
+ "TYPE": "GET",
452
+ "URI": "api/1/energy_sites/{site_id}/savings_forecast",
453
+ "AUTH": true
454
+ },
455
+ "TARIFF_RATES": {
456
+ "TYPE": "GET",
457
+ "URI": "api/1/energy_sites/{site_id}/tariff_rates",
458
+ "AUTH": true
459
+ },
443
460
  "BACKUP_RESERVE": {
444
461
  "TYPE": "POST",
445
462
  "URI": "api/1/energy_sites/{site_id}/backup",
446
463
  "AUTH": true
447
464
  },
465
+ "OFF_GRID_VEHICLE_CHARGING_RESERVE": {
466
+ "TYPE": "POST",
467
+ "URI": "api/1/energy_sites/{site_id}/off_grid_vehicle_charging_reserve",
468
+ "AUTH": true
469
+ },
448
470
  "SITE_NAME": {
449
471
  "TYPE": "POST",
450
472
  "URI": "api/1/energy_sites/{site_id}/site_name",
@@ -30,6 +30,8 @@ Stop the climate control (HVAC) system.
30
30
 
31
31
  Sets the target temperature for the climate control (HVAC) system.
32
32
 
33
+ Note: Despite accepting two parameters, only the `driver_temp` will be used to set the target temperature.
34
+
33
35
  Note: The parameters are always in celsius, regardless of the region the car is in or the display settings of the car.
34
36
 
35
37
  ### Parameters
@@ -8,7 +8,7 @@ Opens or closes the primary Homelink device. The provided location must be in pr
8
8
 
9
9
  | Parameter | Example | Description |
10
10
  | :-------- | :----------------- | :----------------- |
11
- | lat | 36.98765432109876 | Current lattitude. |
11
+ | lat | 36.98765432109876 | Current latitude. |
12
12
  | lon | -77.12345678901234 | Current longitude. |
13
13
 
14
14
  ### Response
@@ -4,7 +4,7 @@
4
4
 
5
5
  Sends a location for the car to start navigation or play a video in theatre mode.
6
6
 
7
- These docs take from the Android app, which sends the data in JSON form. However, a urlencoded POST body will work as well. The basic format to a request looks like this:
7
+ These docs take from the Android app, which sends the data in JSON form. However, a [URL-encoded](https://en.wikipedia.org/wiki/Percent-encoding) POST body will work as well. The basic format to a request looks like this:
8
8
 
9
9
  ```json
10
10
  {
@@ -24,7 +24,7 @@ Note: This API was previously `navigation_request`, but has been updated to supp
24
24
  | Parameter | Example | Description |
25
25
  | :------------------------------- | :-------------------------- | :------------------------------------------------------------- |
26
26
  | type | share_ext_content_raw | Must be `share_ext_content_raw`. |
27
- | locale | en-US | The locale for the navigation request. |
27
+ | locale | en-US | The locale for the navigation request. [ISO 639-1 standard language codes](https://www.andiamo.co.uk/resources/iso-language-codes/) |
28
28
  | timestamp_ms | 1539465730 | The current UNIX timestamp. |
29
29
  | value[android.intent.extra.TEXT] | 123 Main St, City, ST 12345 | The address or video URL to set as the navigation destination. |
30
30
 
@@ -4,16 +4,18 @@ Valet Mode limits the car's top speed to 70MPH and 80kW of acceleration power. I
4
4
  Wifi settings, and the ability to disable mobile access to the car. It also hides your favorites, home, and work
5
5
  locations in navigation.
6
6
 
7
+ Note: the `password` parameter isn't required to turn on or off Valet Mode, even with a previous PIN set. If you clear the PIN and activate Valet Mode without the parameter, you will only be able to deactivate it from your car's screen by signing into your Tesla account.
8
+
7
9
  ## POST `/api/1/vehicles/{id}/command/set_valet_mode`
8
10
 
9
11
  Activates or deactivates Valet Mode.
10
12
 
11
13
  ### Parameters
12
14
 
13
- | Parameter | Example | Description |
14
- | :-------- | :------ | :-------------------------------------------------------------------------------- |
15
- | on | true | true to activate, false to deactivate. Must include previous PIN if deactivating. |
16
- | password | 1234 | A PIN to deactivate Valet Mode. Can be blank if activating with a previous PIN. |
15
+ | Parameter | Example | Description |
16
+ | :-------- | :------ | :------------------------------------------------------------------------------ |
17
+ | on | true | true to activate, false to deactivate. |
18
+ | password | 1234 | A PIN to deactivate Valet Mode. Please see note about the `password` parameter. |
17
19
 
18
20
  ### Response
19
21
 
@@ -26,7 +28,7 @@ Activates or deactivates Valet Mode.
26
28
 
27
29
  ## POST `/api/1/vehicles/{id}/command/reset_valet_pin`
28
30
 
29
- Clears the currently set PIN for Valet Mode when deactivated. A new PIN will be required when activating again.
31
+ Clears the currently set PIN for Valet Mode when deactivated. A new PIN will be required when activating from the car screen. See the note above about activating via the API without a PIN set.
30
32
 
31
33
  ### Response
32
34