Skip to content

thomasesmith/vw-car-net-api

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 

Repository files navigation

Using the Volkswagen Car-Net API

I used mitmproxy to discover/reverse-engineer some of the endpoints and general behavior of how the Volkswagen Car-Net mobile app consumes its RESTful API. This document is intended to be instructions on how to use some of its functions for your own projects related to your car, untethered from the official Car-Net app, and without relying on html scrapers.

Disclaimer (Kind Of)

The responses you receive from your own requests to the Car-Net API may look a little different than the examples given here, depending on your vehicle, its features, and the status of your Car-Net account. The account I am testing with is my own paid account, and the car attached to it is a 2016 eGolf. Furthermore, these instructions might possibly only work for VW Car-Net users in North America, or it may even be limited to just customers in the United States. I don't actually know for sure. I can only test these details out with my own personal use-case. If these details seem overly EV-centric, that's why.

It's worth mentioning also that I have no idea if using the API in this manner violates your terms of service with VW Car-Net. So assume the worst, and proceed at your own risk.

Please contact me @varwwwhtml with any questions, ideas, or thoughts regarding this subject. I'd love to know that this document helped someone start something.

Like Everything, You Start by Logging In

You have to first log in in order to receive a token to use for the rest of your requests. But logging in is actually two steps, just like it is in the app: first to log in to your account with your email address and password, then a second level to authorize with your account number and PIN.

Request

First, send a request like this one:

POST https://cns.vw.com/mps/v1/login
Content-Type:application/json

{
    "email": "{YOUR CAR-NET ACCOUNT EMAIL ADDRESS}",
    "password": "{YOUR PASSWORD}"
}

The "Content-Type:application/json" header is required in every POST, PATCH, and PUT request that is made to this server. I've found that if you don't include it, you'll just get back 415 errors. The GETs don't require it however.

Response

Upon a successful login, you will receive back a JSON object containing your details that will look something like this:

{
  "value": {
    "needs_password_reset": false,
    "token": {
      "value": "{YOUR TOKEN, USUALLY 48 BYTES}",
      "expiration_date": "2019-10-31T17:09:09.932Z"
    },
    "account": {
      "vehicles": [
        {
          "id": "{YOUR CAR-NET ACCOUNT NUMBER}",
          "vin": "WVWKP7AU123456789",
          "make": "VW",
          "model": {
            "type": "egolf_2016",
            "name": "e-Golf"
          },
          "year": 2016,
          "color": "Night Blue Metallic",
          "subscription": {
            "state": "ok",
            "message": "Your subscription will end on `10/10/2020.",
            "active_features": [
              "battery",
              "climate",
              "departure_timers",
              "remote",
              "navigation",
              "alerts",
              "health_report"
            ]
          },
          "vehicle_features": [
            "door_lock",
            "battery",
            "climate"
          ],
          "dealership": {
            "name": "Sim City Volkswagen",
            "phone": "8185551212",
            "location": {
              "latitude": 12.1234,
              "longitude": -123.123
            },
            "address": {
              "countryOnly": false,
              "street": "123 Fake St.",
              "city": "Sim City",
              "state": "CA",
              "zip_code": "91001",
              "country": "USA"
            }
          }
        }
      ]
    }
  }
}

TAKE NOTE of the "token" and "id" values (your "id" is also your Car-Net account number), you will need both of these in order to complete all the other API requests detailed in this document.

...then you must authorize your Car-Net account number and PIN. This secondary account/pin authorization process must be performed in order for your token to successfully be used in any the other API requests. Trying to make API requests without doing so will result in errors. So do it like this:

Request

POST https://cns.vw.com/mps/v1/vehicles/{YOUR ACCOUNT NUMBER}/auth
Content-Type:application/json
X-CarNet-Token:{THE TOKEN GIVEN TO YOU BY THE PREVIOUS RESPONSE}

{
    "id": "{YOUR ACCOUNT NUMBER}",
    "pin": "{YOUR PIN}"
}

Response

The response will be simply the expiration datetime of your token.

{
  "value": {
    "token_expiration_date": "2019-09-16T16:46:55.039Z"
  }
}

This token expiry is set for about 15 minutes in to the future, but I have found that it's not a "firm" expiration time for your token. It seems more to be the expiration time if you were to then stop making requests. Each request you make with your token seems to lengthen your tokens expiry time to 15 more minutes in to the future. But if you wait 15 minutes between your last and next request using your token, you will start getting token expiry errors.

If any of your requests respond with a 500 error ("Something went wrong"), or a 403 response with "Vehicle session expired" message, simply re-perform the account/pin authorization request, using the same token you were first issued. This will "refresh" the token, and issue it a new expiry time of 15 minutes in the future. You can then continue to use it for requests. In this instance, you don't have to repeat the first email/password log in request and get a new token.


View Your Vehicle's "Status"

Now that you're all logged in and authorized, you can begin poking around. Start by getting your cars current "status."" The status is a summary of your vehicle that includes a lot of stuff: your car's GPS coordinates, its odometer reading, its charge status and approximate driving range, etc..

Request

GET https://cns.vw.com/mps/v1/vehicles/{YOUR ACCOUNT NUMBER}/status
X-CarNet-Token:{YOUR TOKEN}

Response

The API will respond with a JSON object summarizing your vehicle's status:

{
  "value": {
    "timestamp": "2019-09-16T16:23:29.000Z",
    "current_mileage": 27283,
    "next_maintenance_milestone": {
      "mileage_interval": 0,
      "absolute_mileage": 12600,
      "date": "2019-11-09T17:26:18.623Z"
    },
    "exterior": {
      "entry": {
        "secure": true,
        "doors": {
          "front_left_open": false,
          "front_right_open": false,
          "rear_left_open": false,
          "rear_right_open": false,
          "rear_open": false
        },
        "windows": {
          "front_left_open": false,
          "front_right_open": false,
          "rear_left_open": false,
          "rear_right_open": false,
          "engine_hood_open": false
        }
      },
      "lights": {
        "left_on": false,
        "right_on": false
      }
    },
    "power": {
      "cruise_range": 87,
      "cruise_range_units": "MILES",
      "battery": {
        "charge_percent_remaining": 76,
        "minutes_until_full_charge": 15,
        "charge_plug": "unplugged",
        "triggered_by_timer": false
      }
    },
    "climate": {
      "outdoor_temperature": 73,
      "target_temperature": 64,
      "climate_on": false,
      "defrost_on": false,
      "unplugged_climate_control_enabled": true,
      "triggered_by_timer": false
    },
    "location": {
      "latitude": 123.123456,
      "longitude": -123.123456
    },
    "address": {
      "countryOnly": false,
      "street": "123 CurrentStreetAddress Drive",
      "city": "Sim City",
      "state": "CA",
      "zip_code": "91001",
      "country": "USA"
    }
  }
}

View Your Vehicle's Settings

In addition to "status," you can also get a summary of the current values of each setting in your vehicle:

Request

GET https://cns.vw.com/mps/v1/vehicles/{ACCOUNT NUMBER}/settings
X-CarNet-Token:{YOUR TOKEN}

It will respond with a JSON object containing your car's setting values:

Response

{
  "value": {
    "primary_notification_methods": {
      "email": [
        "[email protected]"
      ],
      "phone": [
        "8055551213"
      ]
    },
    "boundaries": [],
    "departure_timers": [
      {
        "id": 1,
        "enabled": false,
        "profile": {
          "name": "Name of Timer 1",
          "charging": true,
          "climate_on": false
        },
        "expired": false,
        "recurring_schedule": {
          "days_of_week": [
            "monday",
            "tuesday",
            "wednesday",
            "friday"
          ],
          "time": {
            "hours_minutes": "11:00",
            "time_zone": "America/New_York"
          }
        }
      },
      {
        "id": 2,
        "enabled": false,
        "profile": {
          "name": "Name of Timer 2",
          "charging": true,
          "climate_on": false
        },
        "expired": false,
        "recurring_schedule": {
          "days_of_week": [
            "thursday"
          ],
          "time": {
            "hours_minutes": "11:00",
            "time_zone": "America/New_York"
          }
        }
      },
      {
        "id": 3,
        "enabled": false,
        "profile": {
          "name": "Name of Timer 3",
          "charging": true,
          "climate_on": false
        },
        "expired": false,
        "recurring_schedule": {
          "days_of_week": [
            "monday",
            "tuesday",
            "wednesday",
            "thursday",
            "friday",
            "saturday",
            "sunday"
          ],
          "time": {
            "hours_minutes": "11:00",
            "time_zone": "America/New_York"
          }
        }
      }
    ],
    "max_charge_current": "max",
    "unplugged_climate_control_enabled": true
  }
}

Various Functions I've Been Able to Map So Far

Both PUT and PATCH requests are used to adjust the status and settings of your vehicle. Keep a keen eye on which is used for which request.

Here are the functions I've mapped out so far...

Locking/Unlocking The Doors

Lock Doors Request

PUT https://cns.vw.com/mps/v1/vehicles/{ACCOUNT NUMBER}/status/exterior/doors
X-CarNet-Token:{YOUR TOKEN}
Content-Type:application/json

{
  "lock": true
}

Lock Doors Response

{
  "value": {
    "transaction_id": "...",
    "command": "lock_doors"
  }
}

Just a note about all of these functions: getting a response doesn't mean your request has already been fulfilled in the real world. In fact, if you were to run this request, then immediately following it request the "status" of the car, you will not see in the status response that the car's doors are now locked. It takes me about 30 seconds for that to actually happen. The API server itself responds quickly, but it seems to take some time for the vehicle to actually lock, and then even more time for the "status" summary request to reflect that has been locked. This is the case with all of the PUT and PATCH requests made to the API. I assume this is a limitation of the speed of the data connection to the vehicle itself, and the speed at which the vehicle can process directives sent to it from VWs servers (it's not like these API requests communicate directly with the vehicle itself). Perhaps this explains somewhat the excruciating slowness of the Car-Net app?

And then to unlock...

Unlock Doors Request

PUT https://cns.vw.com/mps/v1/vehicles/{ACCOUNT NUMBER}/status/exterior/doors
X-CarNet-Token:{YOUR TOKEN}
Content-Type:application/json

{
  "lock": false
}

Unlock Doors Response

{
  "value": {
    "transaction_id": "...",
    "command": "unlock_doors"
  }
}

Flashing Headlights \ Honking Horn

Request

PUT https://cns.vw.com/mps/v1/vehicles/{YOUR ACCOUNT NUMBER}/status/exterior/horn_and_lights
X-CarNet-Token:{YOUR TOKEN}
Content-Type:application/json
{
  "horn": true,
  "lights": true
}

Response

{
  "value": {
    "transaction_id": "...",
    "command": "flash_lights_and_honk_horn"
  }
}

You can also JUST honk the horn, by changing "lights" to "false" in your submitted JSON payload, or you can JUST flash the lights, by changing "horn" to "false".

Stop Charging

Request

PATCH https://cns.vw.com/mps/v1/vehicles/{YOUR ACCOUNT NUMBER}/status/charging
X-CarNet-Token:{YOUR TOKEN}
Content-Type:application/json
{
  "active": false
}

Watch out! Unlike the others, charging related requests are of type PATCH.

Response

{
  "value": {
    "transaction_id": "...",
    "command": "stop_charge"
  }
}

Start Charging

Request

PATCH https://cns.vw.com/mps/v1/vehicles/{YOUR ACCOUNT NUMBER}/status/charging
X-CarNet-Token:{YOUR TOKEN}
Content-Type:application/json
{
  "active": true
}

Watch out! Unlike the others, charging related requests are of type PATCH.

Response

{
  "value": {
    "transaction_id": "...",
    "command": "start_charge"
  }
}

Setting the Maximum Charging Current

Request

PATCH https://cns.vw.com/mps/v1/vehicles/{YOUR ACCOUNT NUMBER}/settings/max_charge_current
X-CarNet-Token:{YOUR TOKEN}
Content-Type:application/json
{
  "max_charge_current": "max"
}

The values that the API will accept for "max_charge_current" probably differ for everyone depending on your vehicle, but I happen to know that with the 2016 eGolf SE (w/ the optional DC Fast Charging package) the acceptable values of "max_charge_current" are "5", "10", "13", and "max"

Response

(TODO)

Turning On/Off Climate Control and Adjusting Target Temperature

If your vehicle is plugged in, or if you have "unplugged_climate_control_enabled" set to "true" you can adjust the climate control too.

Request

PUT https://cns.vw.com/mps/v1/vehicles/{YOUR ACCOUNT NUMBER}/status/climate
X-CarNet-Token:{YOUR TOKEN}
Content-Type:application/json
{
  "active": true,
  "target_temperature": 72
}

Issue the same request but with "active" set to "false" (no quotation marks) to turn off climate control.

"target_temperature" is the number (in fahrenheit, at least for me) that one would set as the temperature they want the interior of the car to be. I have not tested the limits of what is an acceptable range of values for "target_temperature".

Response

** TO-DO **

Turning On/Off Defroster

You can remotely turn off or on the defroster.

I am not totally sure if you must be plugged in, or "unplugged_climate_control_enabled" set to "true", in order to do this. Not sure if those have any consequence here. I will test further.

Request

PUT https://cns.vw.com/mps/v1/vehicles/{YOUR ACCOUNT NUMBER}/status/defrost
X-CarNet-Token:{YOUR TOKEN}
Content-Type:application/json
{
  "active": true
}

Issue the same request but with "active" set to "false" (no quotation marks) to turn off the defroster.

Response

** TO-DO **

Enabling/Disabling Unplugged Climate Control

** TO-DO **