Skip to content

thomasesmith/vw-car-net-api

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 

Repository files navigation

Connecting to 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.

I noticed that the other projects on GitHub tackling this subject have had some breaking changes occur that the authors couldn't control, and were no longer working or being updated.

This README will attempt to stay code-agnostic and simply detail each http request.

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. So 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. I have no control over this API or its behavior, but I will try and assist you.

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 account 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. Here's how:

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 date/time 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, your requests will then produce token expiry errors.

If any of your requests suddenly begin responding 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 charging 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. I don't know why they made some PUT and some PATCH, so 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 the JSON to "lights": false, or you can JUST flash the lights by changing the JSON to "horn": 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 depending on your vehicle, but I happen to know that for 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

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

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 with the API.

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": false 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

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

If you issued that request as "active": false the "command" value would've been returned as "stop_climate".

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. I don't know 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": false to turn off the defroster.

Response

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

If you issued that request as "active": false the "command" value would've been returned as "stop_defrost".

Enabling/Disabling Unplugged Climate Control

** TO-DO **