Skip to content

Instantly share code, notes, and snippets.

@BenWoodford BenWoodford/LeafAPI.md
Last active Jul 9, 2019

Embed
What would you like to do?
New Nissan Connect EV API

Late 2018 Update

I am no longer working on this as the new API is US-only as I'm in the UK, so cannot even use it or the new app. Please don't ask me questions about it as I honestly can't remember anything.

Nissan Connect EV 2018 API

This is a work in progress, just jotting down my findings from the APK decompile so far. As I can only read the decompiled Java and not MITM the app due it not working in the UK, getting the payload info may take a while. There's loads of API calls so this may not be thorough for a while.

Base URL: https://icm.infinitiusa.com/NissanLeafProd/rest

Battery

GET /battery/vehicles/:vin/getChargingStatusRequest

POST /battery/vehicles/:vin/remoteChargingRequest

POST /battery/vehicles/:vin/cancelRemoteChargingRequest

HVAC

POST /hvac/vehicles/:vin/activateHVAC

POST /hvacSchedule/vehicles/:vin/cancelHVACSchedule

POST /hvacSchedule/vehicles/:vin/createHVACSchedule

POST /hvac/vehicles/:vin/deactivateHVAC

GET /hvacSchedule/vehicles/:vin/getHvacSchedule

POST /hvacSchedule/vehicles/:vin/updateHVACSchedule

Find My Car

POST /vehicleLocator/vehicles/:vin/refreshVehicleLocator

POST /vehicleLocator/vehicles/:vin/getNotificationHistory

Security

POST /remote/vehicles/:vin/accounts/:accountId/rdl/createRDL

POST /remote/vehicles/:vin/accounts/:accountId/rdl/createRUDL

Horn and Lights

POST /remote/vehicles/:vin/accounts:accountId/rhl/createRHL

Misc

GET /remote/securityQuestions

PUT /remote/vehicles/:vin/accounts/:accountId/authorizationInformation

Account Stuff

POST /auth/softLoginforAAS

Can take a query string of ?vin=<vinHere>&subscription=<true/false>

POST Body:

{
	"userid": <username>,
    "password": <password>,
    "country": "US", // Others to come?
    "brand-s": "N", // N for Nissan?
    "language-s": "en"
}

@sewi-cpan

This comment has been minimized.

Copy link

commented Apr 24, 2018

curl -d @t.json -vvv 'https://icm.infinitiusa.com/NissanLeafProd/rest/auth/softLoginforAAS' replies:

HTTP/1.1 401 Unauthorized

<title>JBoss Web/7.4.10.Final-redhat-1 - JBWEB000064: Error report</title>[...]

JBWEB000065: HTTP Status 401 - Invalid API Key


JBWEB000309: type JBWEB000067: Status report

JBWEB000068: message Invalid API Key

JBWEB000069: description JBWEB000121: This request requires HTTP authentication.

Looks like some HTTP Basic Auth data is missing.

MITM won't work as the URL is HTTPS.

@matt

This comment has been minimized.

Copy link

commented May 9, 2018

I purchased a used 2015 leaf last week and it was delivered today! I am excited to begin working on an [iOS] app to interface with the vehicle. Thank you for beginning the effort with the new API.

I began looking into the authorization request. It's very straight forward:

POST https://icm.infinitiusa.com/NissanLeafProd/rest/auth/authenticationForAAS

Headers

Content-Type: application/json; charset=utf-8
API-Key: f950a00e-73a5-11e7-8cf7-a6006ad3dba0

Body

{
  "authenticate": {
    "userid": "first.last@example.com",
    "brand-s": "N",
    "language-s": "en_US",
    "password": "ILoveMyLeaf!",
    "country": "US"
  }
}

200 OK

{
  "vehicles": [
    {
      "uvi": "xxxxxxxxxxxxxxxxx",
      "brands": "N",
      "modelcode": "xxxxx",
      "modelname": "LEAF",
      "modelyear": "2015",
      "extcolor": "",
      "nickname": "LEAF",
      "pinAndPassword": null,
      "batteryRecords": {
        "operationResult": "START",
        "lastUpdatedDateAndTime": "2018-01-01T11:22:33Z",
        "batteryStatus": {
          "batteryChargingStatus": "NO",
          "batteryCapacity": 100,
          "batteryRemainingAmount": 90,
          "soc": null
        },
        "pluginState": "NOT_CONNECTED",
        "cruisingRangeAcOn": 012345,
        "cruisingRangeAcOff": 123456,
        "timeRequired": {
        "hourRequiredToFull": 2,
        "minutesRequiredToFull": 30
      },
      "timeRequired200": {
        "hourRequiredToFull": 1,
        "minutesRequiredToFull": 30
      },
      "timeRequired200_6kW": {
        "hourRequiredToFull": 1,
        "minutesRequiredToFull": 30
      },
      "notificationDateAndTime": null
    },
    "interiorTempRecords": null,
    "subcriptionList": null,
    "genType": null,
    "deviceId": null,
    "svlStatus": null,
    "accountId": null,
    "contactId": null,
    "subscriberType": null,
    "subscriptionId": null,
    "firstName": null,
    "lastName": null,
    "rdlRequestId": null,
    "rdulRequestId": null,
    "accountStatus": null,
    "productSpecificationCode": null,
    "remoteStartReqId": null,
    "remoteStopReqId": null,
    "enrollmentCompleted": false
    }
  ],
  "authenticationInfo": {
    "pinConfigured": false,
    "securityQuestions": null
  },
  "displayMessage": null,
  "displayNoTemperatureMessage": null,
  "accountID": "niscust:nis:xxxxxxxxx",
  "authToken": "xxxxx..."
}

Things to note:

  1. The auth request returns a Cookie header. This needs to be sent with follow-up requests.
  2. API key may [or may not] be specific to the iOS app, but this shouldn't matter aside from skewing analytics.
  3. One of the employees/contractors indeed published a typo (subcriptionList) and it was deployed to production. Either QE/QA doesn't exist, or someone should be reprimanded.

I plan to continue playing around with the API. Let me know if there's anything I can help with. My limitations are access to a 2015 Nissan Leaf. Thanks!

@matt

This comment has been minimized.

Copy link

commented May 11, 2018

Additional endpoints:

POST /electricusage/vehicles/:vin/detailpriceSimulatordata
POST /ecoDrive/vehicles/:vin/driveHistoryRecords
POST /ecoDrive/vehicles/:vin/driveAnalysisBasicRecords
POST /ecoDrive/vehicles/:vin/driveAnalysisDetail
POST /eco/vehicles/:vin/nationalRankingBasicScreenChampionData
POST /eco/vehicles/:vin/detailNationalRankingData
POST /worldEco/vehicles/:vin/worldEcoForestBasicScreenData
POST /worldEco/vehicles/:vin/worldEcoForestAllInfo
GET /auth/getUserProfile
POST /enrollment/getpinandpassword/language/:lang

@gtlambert

This comment has been minimized.

Copy link

commented May 21, 2018

Matt - do you know if it is possible to connect to this API using UK Nissan Leaf credentials?

@jeremyakers

This comment has been minimized.

Copy link

commented May 29, 2018

@matt - What tool did you use to intercept that request? The new NissanConnectEV app doesn't appear to honor proxy settings on Android, so I'm not able to intercept traffic using mitmproxy anymore.

@iceydee

This comment has been minimized.

Copy link

commented May 31, 2018

@jeremyakers I believe they're SSL-pinning, if that's the case that'll be why your mitmproxy isn't working. I have no evidence, it's just a guess from what I saw in my own experiments.

@jeremyakers

This comment has been minimized.

Copy link

commented May 31, 2018

@iceydee So I've been researching this and that's what I initially thought but: Actually they (Nissan) are not SSL pinning. It's actually much worse: Google is the one doing it. Android 8.x and up no longer allows apps to "trust" User Installed Certificates by default. Apps can be re-written to"opt in" but what are the chances any app is going to do that?

I pulled out an older tablet and mitmproxy is working fine on the NissanConnect EV app on Android 6.0. Sounds like iOS should also be fine as based on my research only Google/Android decided to take this drastic step to keep users from sniffing the data their device is sending back to the mothership about them.

@jeremyakers

This comment has been minimized.

Copy link

commented May 31, 2018

So now that I have mitmworking on my older tablet: I'm seeing a very odd behavior. The new API is refusing to give me updated battery status. It was working fine in the old API but I'm now realizing it doesn't even work in the app. When I press refresh this is what it sends to Nissan's API:

GET https://icm.infinitiusa.com/NissanLeafProd/rest/battery/vehicles/1N4BZ0CPXGC304460/getChargingStatusRequest
                        ← 200 text/plain [no content] 9.94s
Content-Type:     application/json                                                                                                                                                                                
Authorization:    <Auth-Key>
API-Key:          b6623f3c-73a5-11e7-8cf7-a6006ad3dba0                                                                                                                                                            
User-Agent:       Dalvik/2.1.0 (Linux; U; Android 6.0; Aquaris M10 FHD Build/MRA58K)                                                                                                                              
host:             icm.infinitiusa.com                                                                                                                                                                             
Connection:       Keep-Alive                                                                                                                                                                                      
Accept-Encoding:  gzip                                                                                                                                                                                            
Cookie:           JSESSIONID=<session cookie>

And the response is No Content:

Date:                           Thu, 31 May 2018 14:22:16 GMT                                                                                                                                                     
Cache-Control:                  no-cache, no-store, max-age=0, must-revalidate                                                                                                                                    
Pragma:                         no-cache                                                                                                                                                                          
Expires:                        0                                                                                                                                                                                 
X-XSS-Protection:               1; mode=block                                                                                                                                                                     
X-Frame-Options:                DENY                                                                                                                                                                              
X-Content-Type-Options:         nosniff                                                                                                                                                                           
Access-Control-Allow-Credentia  true                                                                                                                                                                              
ls:                                                                                                                                                                                                               
content-length:                 0                                                                                                                                                                                 
Connection:                     close                                                                                                                                                                             
Content-Type:                   text/plain; charset=UTF-8                                                                                                                                                         
No content

This is specifically what I captured from the app itself. And I cannot get the app to load refreshed battery data. Everything else in the app works, I can activate and cancel the HVAC, see driving/electricity records, etc. Everything works but battery status.

Does anyone have any idea why the new API would be failing to update the battery status? I also checked on the Nissan Owners Portal and battery status is refreshing fine there.

@jeremyakers

This comment has been minimized.

Copy link

commented May 31, 2018

Here's the JSON response from authenticateForAAS when I first sign into the app:

{
    "accountID": "niscust:nis:<AccountID>", 
    "authToken": "<AuthToken>", 
    "authenticationInfo": {
        "pinConfigured": false, 
        "securityQuestions": null
    }, 
    "displayMessage": "BatteryStatusRecords not available for the user",
    "displayNoTemperatureMessage": "InteriorTemperature Records are  not available for the VIN", 
    "vehicles": [
        {
            "accountId": null, 
            "accountStatus": null, 
            "batteryRecords": null, 
            "brands": "N", 
            "contactId": null, 
            "deviceId": null, 
            "enrollmentCompleted": true, 
            "extcolor": "PEARL WHITE", 
            "firstName": null, 
            "genType": null, 
            "interiorTempRecords": null, 
            "lastName": null, 
            "modelcode": "17216", 
            "modelname": "LEAF", 
            "modelyear": "2016", 
            "nickname": "2016 Leaf", 
            "pinAndPassword": null, 
            "productSpecificationCode": null, 
            "rdlRequestId": null, 
            "rdulRequestId": null, 
            "remoteStartReqId": null, 
            "remoteStopReqId": null, 
            "subcriptionList": null, 
            "subscriberType": null, 
            "subscriptionId": null, 
            "svlStatus": null, 
            "uvi": "<MyVIN>"
        }
    ]
}

Notice the "DisplayMessage"?

"displayMessage": "BatteryStatusRecords not available for the user",

This doesn't actually get displayed anywhere in the App that I can see...

@matt

This comment has been minimized.

Copy link

commented Jun 6, 2018

Apologies for stepping away from this conversation briefly.

@gtlambert I live in the US and have not tested whether other regional credentials are compatible with this API.

@jeremyakers I used Charles Proxy to sniff the traffic on iOS. The app is not using ssl-pinning.

@matt

This comment has been minimized.

Copy link

commented Jun 6, 2018

@jeremyakers I have also noticed intermittent hiccups when retrieving battery records. I haven't had a chance to dig in, but have noticed the app not refreshing battery percentage and/or range appropriately.

@FrancoSabadini

This comment has been minimized.

Copy link

commented Aug 29, 2018

@BenWoodford are these APIs still not working in the UK?

@FrancoSabadini

This comment has been minimized.

Copy link

commented Aug 29, 2018

Hey @matt, when trying to authenticate with this API I'm getting this error:

{
    "errorMessage": "Authentication Failure",
    "errorCode": 910
}

Do you have any idea why that can be?

@paultanner

This comment has been minimized.

Copy link

commented Sep 11, 2018

Thx for your working in putting this together.
FYI. I tried /auth/softLoginforAAS in the UK with my You+Nissan account credentials.
I have a 2018 LEAF and the app works OK with these creds (set up a couple of months ago)
Got back a 401 with "Invalid API key" which is odd because I was hoping to get an API key back.
Maybe they have not yet enabled this here?

@colleenfeng

This comment has been minimized.

Copy link

commented Sep 14, 2018

I tried to authenticate my Canadian account using the API key and stuff posted above, and got a 401 back with invalid API key as well. Anyone know if it works for Canada?

@brianflex

This comment has been minimized.

Copy link

commented Sep 17, 2018

The V2 API's use a different set of country codes than the previous V1 API's. But, it's not clear to me what's supported. Colleen, try changing this line:
"country": "US"
Maybe you can put in CA or CN or CD and it would work? If you find a solution, please share.

@sirfergy

This comment has been minimized.

Copy link

commented Oct 9, 2018

Anyone able to figure out if the AC is on or off? I want to integrate with HomeKit but not being able to get the status will make things less than ideal. From the app it doesn't appear to be possible to get either.

@mckooper

This comment has been minimized.

Copy link

commented Oct 14, 2018

@sirfergy - I haven't seen anything yet that lets you query the state of the HVAC, or the state of the door locks for that matter. It's as if the API was written by someone right out of school whose intentions were good, but they had no experience with what they were doing.

I've just started playing around with this and my 2018 Leaf - I'll follow up with a few POST body definitions...

@mckooper

This comment has been minimized.

Copy link

commented Oct 14, 2018

POST /hvac/vehicles/:vin/deactivateHVAC

Headers

  Content-Type:  application/json; charset=utf-8
  API-Key:       f950a00e-73a5-11e7-8cf7-a6006ad3dba0
  Authorization: <authToken>
  Cookie:        <Set-Cookie>

Body


(empty string)

200 OK

{
    "messageDeliveryStatus": "Success"
}

Notes

"messageDeliveryStatus : Success" - so the message was successfully delivered, but technically we still don't know anything about the state of the HVAC. Lovely.

@mckooper

This comment has been minimized.

Copy link

commented Oct 14, 2018

POST /hvac/vehicles/:vin/activateHVAC

Headers

  Content-Type:  application/json; charset=utf-8
  API-Key:       f950a00e-73a5-11e7-8cf7-a6006ad3dba0
  Authorization: <authToken>
  Cookie:        <Set-Cookie>

Body

{
  "executionTime" : "2018-10-14T21:08:00Z"
}

or

{
  "preACunit" : "F",
  "executionTime" : "2018-10-14T05:49:53Z",
  "preACtemp" : "72"
}

200 OK

{
    "messageDeliveryStatus": "Success"
}

Notes

  • Again, the response doesn't actually tell us that the HVAC is now active.
  • I don't know if the value of "executionTime" matters
  • I suppose "preACunit" could also be "C", but I haven't tried it (don't want to set my car on fire because my feeble US brain can't handle the Metric system)
@dernotte

This comment has been minimized.

Copy link

commented Oct 21, 2018

I am curious to know where you get the URL and different endpoint from. Is there an official documentation about Nissan API.
I have a Nissan Leaf 2014 and I am currently using this base URL : https://gdcportalgw.its-mo.com/api_v180117_NE/gdc/, not the https://icm.infinitiusa.com/NissanLeafProd/rest. I am very interested finding an endpoint to stop charging. I saw the infinitiusa.com has the endpoint, but it does not work for me. Is it something that works on the 2018/2019 and not on the 2014 ? The getChargingStatusRequest endpoint works fine for me.

@mckooper

This comment has been minimized.

Copy link

commented Oct 23, 2018

@dernotte - The infinitiusa URL is what my iPhone app is using, and it would not surprise me if that was specific to both the US and 2018 model years.

@Raiden38

This comment has been minimized.

Copy link

commented Feb 6, 2019

Did you find the way to make de remote door lock work?

I used the path above /remote/vehicles/:vin/accounts/:accountId/rdl/createRDL, I get a status 200 but it does not work. I also tried adding parameters Command, Lock and Delay like the nissan website but no success.

@jfarinhote

This comment has been minimized.

Copy link

commented Feb 11, 2019

Any news on this thread? I am not sure what is the API-key and the credentials json body to send. I am trying to make a simple authentication for starting

@Tobiaswk

This comment has been minimized.

Copy link

commented Jun 17, 2019

Hello I'm the developer of the My Leaf app on Android and iOS. It seems the NissanConnect EV app for US users is beginning to use this new API. I want to implement support for the new US-based API. I'm stuck though because I do not have an API Key.

@jfarinhote I'm in the same boat. @matt where did you get your API-Key?

@matt

This comment has been minimized.

Copy link

commented Jun 17, 2019

@jfarinhote, @Tobiaswk

A sample authentication request is available near the beginning of this thread. The original request was performed over a year ago, but the API-Key was valid on May 8, 2018. I used Charles Proxy to sniff the traffic from the iOS Nissan Connect EV application.

@Tobiaswk

This comment has been minimized.

Copy link

commented Jun 20, 2019

@matt Sorry. I did not notice that. Thanks for the information! The API-Key still works!

On another note has anyone gotten anything succesful from these calls;
POST /electricusage/vehicles/:vin/detailpriceSimulatordata
POST /ecoDrive/vehicles/:vin/driveHistoryRecords
POST /ecoDrive/vehicles/:vin/driveAnalysisBasicRecords
POST /ecoDrive/vehicles/:vin/driveAnalysisDetail

For everyone one of these the request goes through with HTTP 200. Nothing other than error messages or empty values are returned though.
Examples;
{"errorMessage":"An error occurred while retrieving price simulator information.","errorCode":934}

{"errorMessage":"An error occurred while retrieving Car Karte Detail Info","errorCode":977}

{"dateSummary":{"targetDate":"2019-06-20","electricMileage":null,"electricMileageLevel":null,"powerConsumptMoter":null,"powerConsumptMoterLevel":null,"powerConsumpt$ inus":null,"powerConsumptMinusLevel":null,"powerConsumptAUX":null,"powerConsumptAUXLevel":null},"electricCostScale":"miles/kWh"}}

@mrtaormina

This comment has been minimized.

Copy link

commented Jul 9, 2019

I was able to get the price simulator data successfully.

POST /electricusage/vehicles/:vin/detailpriceSimulatordata

BODY:
{
"Targetmonth": ""
}

RESPONSE:
{'priceSimulatorDetailInfoResponsePersonalData': {'targetMonth': '201906', 'totalPowerConsumptTotal': '157861.86', 'totalPowerConsumptMoter': '213934.26', 'totalPowerConsumptMinus': '56072.4', 'electricPrice': '0.11', 'electricBill': '17.3648046', 'electricCostScale': 'miles/kWh', 'mainRateFlg': 'USER', 'existFlg': 'EXIST', 'priceSimulatorTotalInfo': {'totalNumberOfTrips': '106', 'totalPowerConsumptTotal': '157861.86', 'totalPowerConsumptMoter': '213934.26', 'totalPowerConsumptMinus': '56072.4', 'totalTravelDistance': '1276707', 'totalElectricMileage': '5.0', 'totalCO2Reductiont': '232'}, 'priceSimulatorDetailInfoDateList': {'priceSimulatorDetailInfoDate': [{'priceSimulatorDetailInfoTripList': {'priceSimulatorDetailInfoTrip': [{'tripId': '1', 'powerConsumptTotal': '491.14', 'powerConsumptMoter': '709.34', 'powerConsumptMinus': '218.2', 'travelDistance': '4700', 'electricMileage': '5.9', 'cO2Reduction': '1', 'mapDisplayFlg': 'ACTIVE', 'gpsDatetime': '2019-06-01T18:02:19'}, {'tripId': '2'..........}

@Tobiaswk

This comment has been minimized.

Copy link

commented Jul 9, 2019

Thanks for writing! I've created a Dart client library for this new North American API. It supports most of the features the API offers but not all yet; https://github.com/Tobiaswk/dartnissanconnectna
I suppose someone can use it as a reference.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.