tesla-api icon indicating copy to clipboard operation
tesla-api copied to clipboard

Invoices

Open wannesdemaeght opened this issue 3 years ago • 32 comments

in the endpoints file there is some documentation about invoices. I would like to automatically download my supercharging invoices, but can not get it to work.

"DOWNLOAD_CHARGING_INVOICE": {
    "TYPE": "GET",
    "URI": "bff/v2/mobile-app/charging/invoice/{uuid}",
    "AUTH": true
  },
  "DOWNLOAD_CHARGING_SUBSCRIPTION_INVOICE": {
    "TYPE": "GET",
    "URI": "bff/v2/mobile-app/charging/subscription/invoice/{invoiceId}",
    "AUTH": true
  },

using these endpoints needs a uuid or invoiceId, which I am trying to obtain with this endpoint:

  "MANAGE_GET_SUBSCRIPTION_INVOICES": {
    "TYPE": "GET",
    "URI": "bff/v2/mobile-app/subscriptions/invoices",
    "AUTH": true
  },

I am using this url: https://owner-api.teslamotors.com/bff/v2/mobile-app/subscriptions/invoices

I am using GET, with requestheader application/json params is: {"vehicle_id":"xxxxxxxxxxxx"} (id is correct, and works for all other api requests)

response is: {"response":null,"error":"param is missing or the value is empty: vehicle_id","error_description":""}

I tried attaching the vehicle_id in the url, as needs to be done for other calls, but then I get a 404 error. Any help?

wannesdemaeght avatar Mar 04 '22 05:03 wannesdemaeght

Curious about this too. I've tried for days to get supercharging costs from the API but have not gotten anywhere.

jamesdeck avatar May 16 '22 15:05 jamesdeck

What headers are you sending?

idriskhenchil avatar May 18 '22 09:05 idriskhenchil

The BFF (backend-for-frontend) endpoints don't appear to authenticate the same way as the other vehicle endpoints do. I'd love to figure out what's going on here. Since they started obfuscating the JavaScript bundle in the app, it's gotten a little more difficult to figure out what the app is up to with these endpoints. I either need to packet sniff or just de-obfuscate the JS bundle, but we should probably focus a bit on figuring out how to call these endpoints.

timdorr avatar May 21 '22 18:05 timdorr

The BFF (backend-for-frontend) endpoints don't appear to authenticate the same way as the other vehicle endpoints do. I'd love to figure out what's going on here. Since they started obfuscating the JavaScript bundle in the app, it's gotten a little more difficult to figure out what the app is up to with these endpoints. I either need to packet sniff or just de-obfuscate the JS bundle, but we should probably focus a bit on figuring out how to call these endpoints.

I've been able to packet sniff the app and I'll post that information here when I get a chance. Currently trying to packet sniff the actual car as well, but that's proving to be a little tricky so far.

idriskhenchil avatar May 22 '22 01:05 idriskhenchil

Through checking the HTTP requests on the app, I've been able to get Invoice data through:

POST https://ownership.tesla.com/graphql?deviceLanguage=en&deviceCountry=US&vin={vin}&operationName=getChargingHistoryV2

The request is as follows:

POST /graphql?deviceLanguage=en&deviceCountry=US&vin={VIN}&operationName=getChargingHistoryV2 HTTP/1.1
Host: ownership.tesla.com
Accept: */*
Authorization: Bearer {token}
Accept-Encoding: gzip, deflate, br
Accept-Language: en
Cache-Control: no-cache
charset: utf-8
Content-Length: 1376
User-Agent: Tesla/1032 CFNetwork/1331.0.7 Darwin/21.4.0
Connection: keep-alive
x-tesla-user-agent: TeslaApp/4.8.1/5e1bfb8d0d/ios/15.4.1
Content-Type: application/json
x-txid: {x-txid}
Cookie: bm_sv={value}; ak_bmsc={value}

Which in turn will return roughly the following response

"charging": {
        "historyV2": {
          "data": [{
            "countryCode": "US",
            "programType": "PTSCH",
            "billingType": "IMMEDIATE",
            "vin": "{VIN}",
            "credit": null,
            "invoices": null,
            "chargeSessionId": "1234565-0-12345566",
            "siteLocationName": "LOCATION",
            "chargeStartDateTime": "2022-05-21T21:06:18-04:00",
            "chargeStopDateTime": "2022-05-21T21:46:20-04:00",
            "unlatchDateTime": "2022-05-21T21:46:21-04:00",
            "fees": [{
              "sessionFeeId": 1234566,
              "feeType": "CHARGING",
              "payorUid": null,
              "amountDue": null,
              "currencyCode": "USD",
              "pricingType": "PAYMENT",
              "usageBase": 61,
              "usageTier1": 10,
              "usageTier2": 12,
              "usageTier3": 17,
              "usageTier4": 0,
              "rateBase": 0.17,
              "rateTier1": 0,
              "rateTier2": 0,
              "rateTier3": null,
              "rateTier4": null,
              "totalTier1": 0,
              "totalTier2": 0,
              "totalTier3": 0,
              "totalTier4": 0,
              "uom": "kwh",
              "isPaid": true,
              "uid": 1234567,
              "totalBase": 10.37,
              "totalDue": 10.37,
              "netDue": 10.37,
              "status": "PAID"
            }],
            "vehicleMakeType": "TESLA",
            "sessionId": 1234567,
            "surveyCompleted": null,
            "surveyType": null,
            "postId": "0",
            "cabinetId": "vehicleMakeType",
            "din": ""
          }

I've only been able to view the request on the Tesla app. I'm still trying to figure out the header situation since I believe the x-txid or the cookies are single use.

If you are trying to get the actual PDF invoice instead, you can try:

GET https://ownership.tesla.com/mobile-app/charging/invoice/{INVOICE_ID}?deviceCountry=US&deviceLanguage=en&vin={VIN}

Which takes the same headers as above.

I do get a 401 when trying to make the request through a REST client, which I think may be related to this

idriskhenchil avatar May 22 '22 02:05 idriskhenchil

Any update on this? As there is no way to get my invoices (premium connectivity and supercharging) via mail, I’d like to access them via api…

wannesdemaeght avatar Jun 30 '22 07:06 wannesdemaeght

I'm also curious if you found anything here. If i were to guess, the secret is in the cookies.

davidhodge avatar Jul 26 '22 20:07 davidhodge

PDF invoices can be accessed with

GET https://ownership.tesla.com/mobile-app/charging/invoice/{INVOICE_ID}?deviceCountry=US&deviceLanguage=en&vin={VIN}

The inconvenience is that you'd need to know the INVOICE_ID.

idriskhenchil avatar Jul 26 '22 21:07 idriskhenchil

thanks @idriskhenchil, we're still a bit stuck on getting the list of invoices. Presently getting back "Bad Request". Perhaps missing some headers.

davidhodge avatar Jul 26 '22 21:07 davidhodge

@davidhodge Also the same error I get back when trying to access the request outside of the app. I used the same headers present in the mobile request as the headers I used in the client.

My wild guess is that I think the app may generate a client-side token that is used to validate where the request is coming from, in order to prevent the request from being made elsewhere. In a sense each request would only be single-use which could be why it works once when analyzing the request in the app, and doesn't work elsewhere.

idriskhenchil avatar Jul 26 '22 21:07 idriskhenchil

@idriskhenchil @wannesdemaeght I was able to get invoice history response off the app without cookies with this endpoint: POST https://akamai-apigateway-charging-ownership.tesla.com/graphql?deviceLanguage=en&deviceCountry=US&ttpLocale=en_US&vin={vin}&operationName=getChargingHistoryV2

I've seen other "akamai-apigateway-" host prefixes but I searched a while and couldn't find "akamai-apigateway-charging-ownership.tesla.com".

I did not need to add the "x-txid" key to the header (or even the bm_sv cookies).

I hope I'm on the right track and this is helping.

chadhurin avatar Aug 05 '22 19:08 chadhurin

hi @chadhurin unfortunately it's not working for me. responsestatus is 400 - Bad Request. accompanying text: {"errors":[{"message":"Oops! Something went wrong. 387be28a-4046-4479-9d86-61bebf6a10cf","txId":"387be28a-4046-4479-9d86-61bebf6a10cf"}]}

I used both POST and GET, with the url you provided, and a working bearer-token...

wannesdemaeght avatar Aug 05 '22 20:08 wannesdemaeght

Hey, @wannesdemaeght Try this in your body

{ "query": "\n query getChargingHistoryV2($pageNumber: Int!, $sortBy: String, $sortOrder: SortByEnum) {\n me {\n charging {\n historyV2(pageNumber: $pageNumber, sortBy: $sortBy, sortOrder: $sortOrder) {\n data {\n ...SparkHistoryItemFragment\n }\n totalResults\n hasMoreData\n pageNumber\n }\n }\n }\n}\n \n fragment SparkHistoryItemFragment on SparkHistoryItem {\n countryCode\n programType\n billingType\n vin\n credit {\n distance\n distanceUnit\n }\n chargingPackage {\n distance\n distanceUnit\n energyApplied\n }\n invoices {\n fileName\n contentId\n invoiceType\n }\n chargeSessionId\n siteLocationName\n chargeStartDateTime\n chargeStopDateTime\n unlatchDateTime\n fees {\n ...SparkHistoryFeeFragment\n }\n vehicleMakeType\n sessionId\n surveyCompleted\n surveyType\n postId\n cabinetId\n din\n}\n \n fragment SparkHistoryFeeFragment on SparkHistoryFee {\n sessionFeeId\n feeType\n payorUid\n amountDue\n currencyCode\n pricingType\n usageBase\n usageTier1\n usageTier2\n usageTier3\n usageTier4\n rateBase\n rateTier1\n rateTier2\n rateTier3\n rateTier4\n totalTier1\n totalTier2\n totalTier3\n totalTier4\n uom\n isPaid\n uid\n totalBase\n totalDue\n netDue\n status\n}\n ", "variables": { "sortBy": "start_datetime", "sortOrder": "DESC", "pageNumber": 1 }, "operationName": "getChargingHistoryV2" }

with these headers:

--header 'User-Agent: Tesla/1195 CFNetwork/1388 Darwin/22.0.0' --header 'x-tesla-user-agent: TeslaApp/4.11.1/12ad93c62a/ios/16.0' --header 'Content-Type: application/json' --header 'Authorization: Bearer {token}

chadhurin avatar Aug 05 '22 20:08 chadhurin

@wannesdemaeght Did that work?

chadhurin avatar Aug 08 '22 15:08 chadhurin

Hi @chadhurin, thanks for your help! I got everything working exactly as I wanted.

could you maybe help me along with the correct body to get a list of the premium connectivity invoices?

wannesdemaeght avatar Sep 05 '22 16:09 wannesdemaeght

@chadhurin do you know what endpoint I could use for the premium connectivity invoices, as well as what to put in the body? Would be a great help!

wannesdemaeght avatar Sep 24 '22 02:09 wannesdemaeght

@chadhurin Hey, do you know if it is possible to get the supercharger location's latitude and longitude from the graphql query from your comment:

https://github.com/timdorr/tesla-api/issues/539#issuecomment-1206834760

If so, can you let me know what needs to be added to that query? Thank you.

andrewdevelopz avatar Nov 25 '22 23:11 andrewdevelopz

@idriskhenchil @wannesdemaeght I was able to get invoice history response off the app without cookies with this endpoint: POST https://akamai-apigateway-charging-ownership.tesla.com/graphql?deviceLanguage=en&deviceCountry=US&ttpLocale=en_US&vin={vin}&operationName=getChargingHistoryV2

I've seen other "akamai-apigateway-" host prefixes but I searched a while and couldn't find "akamai-apigateway-charging-ownership.tesla.com".

I did not need to add the "x-txid" key to the header (or even the bm_sv cookies).

I hope I'm on the right track and this is helping.

So this is still working in 2023, but I noticed it no longer returns the invoices for each VIN. It'll instead send a list of the most recent invoices regardless of VIN, but you still need to provide a VIN query parameter or it'll return an error 400.

Is that your experience or am I sending my request incorrectly?

I also noticed invoice.invoices.contentId is null for some invoices. Does this just mean a PDF isn't available to download yet?

komposer-aml avatar May 12 '23 05:05 komposer-aml

I wonder, what is the query that feeds the graph located in the Charge Stats section in the app? image

I want to create a periodic charging report (monthly), to include data such as “charge start time”, “charge end time”, “energy consumed”, “location” (home, supercharge, work, other) and the cost, for each vehicle.

Sadly, Tesla do not provide charging data export, so I wonder if it’s possible to retrieve it using the GraphQL query or the REST API? Because, all the data I need does exist in the app.

Thanks!

P.S: I am JS developer. I would appreciate if someone can send me the obfuscated JS files from the app. I want to try to read them in order to extract as much information as possible.

slavikme avatar May 16 '23 04:05 slavikme

getChargingHistoryV2 and GetNearbyChargingSites return http 403 since approx 24h

does it still work for you?

superfloh247 avatar May 24 '23 23:05 superfloh247

@superfloh247 I was getting the same error for getChargingHistoryV2, so I found the invoices from this uri.

https://ownership.tesla.com/mobile-app/charging/history?

Query Params:
vin=%
deviceLanguage=en
deviceCountry=US

Headers:
Authorization: Bearer %

It only returns the 5 most recent invoices and I am not sure how to query for more pages. Would you or anyone else know how?

andrewdevelopz avatar May 24 '23 23:05 andrewdevelopz

getChargingHistoryV2 and GetNearbyChargingSites return http 403 since approx 24h

does it still work for you?

Just checked and I too am getting error 403 now ://

komposer-aml avatar May 25 '23 02:05 komposer-aml

@superfloh247 I was getting the same error for getChargingHistoryV2, so I found the invoices from this uri.

https://ownership.tesla.com/mobile-app/charging/history?

Query Params:
vin=%
deviceLanguage=en
deviceCountry=US

Headers:
Authorization: Bearer %

It only returns the 5 most recent invoices and I am not sure how to query for more pages. Would you or anyone else know how?

Thank you for the solution! I implemented it and I got ALL of my invoices since late November of 2022

komposer-aml avatar May 25 '23 07:05 komposer-aml

@superfloh247 I was getting the same error for getChargingHistoryV2, so I found the invoices from this uri.

https://ownership.tesla.com/mobile-app/charging/history?

Query Params:
vin=%
deviceLanguage=en
deviceCountry=US

Headers:
Authorization: Bearer %

It only returns the 5 most recent invoices and I am not sure how to query for more pages. Would you or anyone else know how?

Thank you for the solution! I implemented it and I got ALL of my invoices since late November of 2022

No problem. Did you add any extra query params?

andrewdevelopz avatar May 25 '23 07:05 andrewdevelopz

@superfloh247 I was getting the same error for getChargingHistoryV2, so I found the invoices from this uri.

https://ownership.tesla.com/mobile-app/charging/history?

Query Params:
vin=%
deviceLanguage=en
deviceCountry=US

Headers:
Authorization: Bearer %

It only returns the 5 most recent invoices and I am not sure how to query for more pages. Would you or anyone else know how?

Thank you for the solution! I implemented it and I got ALL of my invoices since late November of 2022

No problem. Did you add any extra query params?

No, this is how I make the request: image

komposer-aml avatar May 25 '23 07:05 komposer-aml

No, this is how I make the request: image

works for me, but it's incomplete

https://akamai-apigateway-charging-ownership.tesla.com/graphql?deviceLanguage=en&deviceCountry=US&ttpLocale=en_US&vin=" + car.Vin + "&operationName=getChargingHistoryV2" was paginated and I could poll all supercharger sessions since 2019

the App also loads paginated, I'll play around with URL params :)

superfloh247 avatar May 25 '23 14:05 superfloh247

What'd you find? @superfloh247

stevemer avatar Jun 01 '23 23:06 stevemer

It was a combination of HTTP headers to make it work again

https://github.com/superfloh247/TeslaLogger/commit/f403495c95f76761d3a1c18aeae930dc29498f3a

superfloh247 avatar Jun 02 '23 07:06 superfloh247

and by "it works" I mean the GraphQL queries, not the GET request

superfloh247 avatar Jun 02 '23 07:06 superfloh247

this endpoint works, and is a lot cleaner to implement. Too bad that there are only 5 invoices generated...

Anyone have an idea on how to get the premium connectivity invoices? I tried url https://ownership.tesla.com/mobile-app/premium-connectivity/history?vin=5YJ3E7EB9KF48520&deviceLanguage=en&deviceCountry=US but no dice... (VIN spoofed).

wannesdemaeght avatar Jul 03 '23 17:07 wannesdemaeght