{"id":231250,"date":"2023-10-19T17:30:00","date_gmt":"2023-10-19T16:30:00","guid":{"rendered":"https:\/\/www.virtualworlduk.co.uk\/wordp\/?p=231250"},"modified":"2023-10-19T11:54:24","modified_gmt":"2023-10-19T10:54:24","slug":"vmware-skyline-an-adventure-with-api-and-powerbi-part-3","status":"publish","type":"post","link":"https:\/\/www.virtualworlduk.co.uk\/wordp\/vmware-skyline-an-adventure-with-api-and-powerbi-part-3\/","title":{"rendered":"VMware Skyline \u2013 An Adventure with API and PowerBI \u2013 Part 3"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-post\" data-elementor-id=\"231250\" class=\"elementor elementor-231250\">\n\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-f62aa6f elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"f62aa6f\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-70b6735\" data-id=\"70b6735\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-94d45cc elementor-widget elementor-widget-text-editor\" data-id=\"94d45cc\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>This is part 3 of this little blog series on my adventure with getting data out of the VMware Skyline API and into PowerBI.<\/p><p>In the first part of this series, we went through the process of gaining access to the VMware Skyline API and testing access.<\/p><p>The second part of this series concentrated on how to gather the data from VMware Skyline directly into PowerBI&#8230; but with one drawback, because we had no way to auto generate our access token, we would need to regenerate the access token prior to refreshing our data in PowerBI.<\/p><p>This blog post looks to overcome the drawback experienced in the last part and create a method in PowerBI that will automatically regenerate the access token every time we refresh the report and utilize that refreshed token to gather the latest data.<\/p><p>Part 1 of this series can be found here:<\/p><p><a href=\"https:\/\/www.virtualworlduk.co.uk\/wordp\/2023\/10\/12\/vmware-skyline-an-adventure-with-api-and-powerbi-part-1\/\">https:\/\/www.virtualworlduk.co.uk\/wordp\/2023\/10\/12\/vmware-skyline-an-adventure-with-api-and-powerbi-part-1\/<\/a><\/p><p>Part 2 of this series can be found here:<\/p><p><a href=\"https:\/\/www.virtualworlduk.co.uk\/wordp\/2023\/10\/13\/vmware-skyline-an-adventure-with-api-and-powerbi-part-2\/\">https:\/\/www.virtualworlduk.co.uk\/wordp\/2023\/10\/13\/vmware-skyline-an-adventure-with-api-and-powerbi-part-2\/<\/a><\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-dab5917 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"dab5917\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-55ab98f\" data-id=\"55ab98f\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-3682cdf elementor-widget elementor-widget-heading\" data-id=\"3682cdf\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h4 class=\"elementor-heading-title elementor-size-default\">GetAccessToken Function<\/h4>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-33d4fa6 elementor-widget elementor-widget-text-editor\" data-id=\"33d4fa6\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>We&#8217;re going to create a function in PowerBI that will handle the work of performing the refresh of the access token and then call that function as part of the query created in part 2.\u00a0 The function will be called &#8216;GetAccessToken&#8217;.<\/p><p>Our function is going to start off as a normal query in PowerBI and therefore you should open up the PowerBI file you were working on before and click the &#8216;Transform Data&#8217; button at the top of the screen to open the Power Query editor.<\/p><p>With the power query editor open, you should click the down arrow on the &#8216;New Source&#8217; entry and then select the &#8216;Blank Query&#8217; option<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-0b45ef5 elementor-widget elementor-widget-image\" data-id=\"0b45ef5\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" width=\"103\" height=\"300\" src=\"https:\/\/www.virtualworlduk.co.uk\/wordp\/wp-content\/uploads\/2023\/10\/2023-10-19-10_34_07--103x300.png\" class=\"attachment-medium size-medium wp-image-231252\" alt=\"\" srcset=\"https:\/\/www.virtualworlduk.co.uk\/wordp\/wp-content\/uploads\/2023\/10\/2023-10-19-10_34_07--103x300.png 103w, https:\/\/www.virtualworlduk.co.uk\/wordp\/wp-content\/uploads\/2023\/10\/2023-10-19-10_34_07-.png 143w\" sizes=\"(max-width: 103px) 100vw, 103px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-6dabf22 elementor-widget elementor-widget-text-editor\" data-id=\"6dabf22\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>You will now see &#8216;Query1&#8217; listed as a new query.\u00a0 The first thing to do is to right mouse click on this new query and select the option to &#8216;Rename&#8217;.\u00a0 You should rename this query to be:\u00a0 GetAccessToken<\/p><p>Right mouse click on the query again and this time select the &#8216;Advanced Editor&#8217; option.<\/p><p>We&#8217;re going to build up the PowerBI query in a similar way to how we did in the previous part, with the full query provided at the end of this blog post.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-d539f4b elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"d539f4b\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-574124c\" data-id=\"574124c\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-3d45d5a elementor-widget elementor-widget-heading\" data-id=\"3d45d5a\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h5 class=\"elementor-heading-title elementor-size-default\">token_url<\/h5>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-c218e02 elementor-widget elementor-widget-text-editor\" data-id=\"c218e02\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>The first part that we will add to the query is the token_url.<\/p><p>Underneath the &#8216;let&#8217; entry, we will replace the &#8216;Source = &#8220;&#8221;&#8216; text with the following code:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-81ca0f5 elementor-widget elementor-widget-code-block-for-elementor\" data-id=\"81ca0f5\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"code-block-for-elementor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<pre class='line-numbers theme-okaidia' data-show-toolbar='yes'><code class='language-javascript'>token_url = &quot;https:\/\/console.cloud.vmware.com\/csp\/gateway\/am\/api\/auth\/api-tokens\/authorize&quot;, <\/code><\/pre>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-9c57239 elementor-widget elementor-widget-text-editor\" data-id=\"9c57239\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>This code is creating the variable token_url and assigning the web address that will be required to create the access token.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-3be15f2 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"3be15f2\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-23b1a65\" data-id=\"23b1a65\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-b5c84b4 elementor-widget elementor-widget-heading\" data-id=\"b5c84b4\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h5 class=\"elementor-heading-title elementor-size-default\">body<\/h5>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-66b12e2 elementor-widget elementor-widget-text-editor\" data-id=\"66b12e2\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>The next part of the query is to create the body of the request we are going to send across to generate the token.\u00a0 This is where we will enter our API token that will be used to authorize us against the web address used in token_url, which will then generate the access token.\u00a0 As you may recall, the API token does not change and therefore this can be statically entered in this query.\u00a0 From a security point of view, please remember that the API token can be used to generate an access token and therefore should not be shared with anyone.<\/p><p>Enter the following code in the &#8216;Advanced Editor&#8217;, remembering to replace the &#8216;YOUR-API-TOKEN&#8217; entry with the API token you generated in part 1 of this series:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-4d4fcc9 elementor-widget elementor-widget-code-block-for-elementor\" data-id=\"4d4fcc9\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"code-block-for-elementor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<pre class='line-numbers theme-okaidia' data-show-toolbar='yes'><code class='language-javascript'>body=&quot;grant_type=refresh_token&amp;refresh_token=YOUR-API-TOKEN&quot;,<\/code><\/pre>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-ce3ba3c elementor-widget elementor-widget-text-editor\" data-id=\"ce3ba3c\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>So far you should have something similar to below.\u00a0 As mentioned in previous parts, do not worry about the error in the query at the moment, as the query builds up this will correct itself:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-03a2905 elementor-widget elementor-widget-image\" data-id=\"03a2905\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img fetchpriority=\"high\" decoding=\"async\" width=\"640\" height=\"309\" src=\"https:\/\/www.virtualworlduk.co.uk\/wordp\/wp-content\/uploads\/2023\/10\/2023-10-19-11_04_18-Advanced-Editor.png\" class=\"attachment-large size-large wp-image-231253\" alt=\"\" srcset=\"https:\/\/www.virtualworlduk.co.uk\/wordp\/wp-content\/uploads\/2023\/10\/2023-10-19-11_04_18-Advanced-Editor.png 808w, https:\/\/www.virtualworlduk.co.uk\/wordp\/wp-content\/uploads\/2023\/10\/2023-10-19-11_04_18-Advanced-Editor-300x145.png 300w, https:\/\/www.virtualworlduk.co.uk\/wordp\/wp-content\/uploads\/2023\/10\/2023-10-19-11_04_18-Advanced-Editor-768x371.png 768w\" sizes=\"(max-width: 640px) 100vw, 640px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-72ce754 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"72ce754\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-b0da74d\" data-id=\"b0da74d\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-225ecbd elementor-widget elementor-widget-heading\" data-id=\"225ecbd\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h5 class=\"elementor-heading-title elementor-size-default\">Source<\/h5>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-13a95c0 elementor-widget elementor-widget-text-editor\" data-id=\"13a95c0\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Now we come onto creating the Source.\u00a0 This is where we are going to say what type of response we want, we will provide the token_url, some header information and then the all important body including our API token.<\/p><p>We&#8217;ll then assign the result of Source (and more importantly the access_token value) to the token variable.<\/p><p>The code that needs to be entered should look like this:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-daf0f42 elementor-widget elementor-widget-code-block-for-elementor\" data-id=\"daf0f42\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"code-block-for-elementor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<pre class='line-numbers theme-okaidia' data-show-toolbar='yes'><code class='language-javascript'>Source  = Json.Document(Web.Contents(token_url,\r\n   [ \r\n     Headers = [#&quot;Content-Type&quot;=&quot;application\/x-www-form-urlencoded&quot;,#&quot;Accept&quot;=&quot;application\/json&quot;],\r\n     Content=Text.ToBinary(body)\r\n   ]\r\n   )\r\n   ),\r\n    token = Source[access_token]<\/code><\/pre>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-ae51ec2 elementor-widget elementor-widget-text-editor\" data-id=\"ae51ec2\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>The final element is to change Source after in to read &#8216;token&#8217;.\u00a0 This should mean that your query should be as follows:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-0309be4 elementor-widget elementor-widget-code-block-for-elementor\" data-id=\"0309be4\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"code-block-for-elementor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<pre class='line-numbers theme-okaidia' data-show-toolbar='yes'><code class='language-javascript'>let\r\n    token_url = &quot;https:\/\/console.cloud.vmware.com\/csp\/gateway\/am\/api\/auth\/api-tokens\/authorize&quot;,    \r\n\r\n   body=&quot;grant_type=refresh_token&amp;refresh_token=YOUR-API-TOKEN&quot;,\r\nSource  = Json.Document(Web.Contents(token_url,\r\n   [ \r\n     Headers = [#&quot;Content-Type&quot;=&quot;application\/x-www-form-urlencoded&quot;,#&quot;Accept&quot;=&quot;application\/json&quot;],\r\n     Content=Text.ToBinary(body)\r\n   ]\r\n   )\r\n   ),\r\n    token = Source[access_token]\r\nin\r\ntoken<\/code><\/pre>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-21c1cc2 elementor-widget elementor-widget-text-editor\" data-id=\"21c1cc2\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>After everything is entered correctly (and you have changed the &#8216;YOUR-API-TOKEN&#8217; item to your API token value, then when you click &#8216;Done&#8217;, you should see a long series of letters and numbers which is actually your latest access token.<\/p><p>So now we have a process to get an access token into PowerBI and we have a method to use the access token to get data from Skyline into PowerBI&#8230; but at the moment, they aren&#8217;t working together to allow us to refresh the PowerBI report and have it work seamlessly.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-82a50ac elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"82a50ac\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-24c708c\" data-id=\"24c708c\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-9613a3c elementor-widget elementor-widget-heading\" data-id=\"9613a3c\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h4 class=\"elementor-heading-title elementor-size-default\">Convert GetAccessToken into a Function<\/h4>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-3eefdaa elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"3eefdaa\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-47afa50\" data-id=\"47afa50\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-74b0010 elementor-widget elementor-widget-text-editor\" data-id=\"74b0010\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>As we want to call the GetAccessToken query from within another query, we want to convert this into a function.\u00a0 With this as a function, we can simply enter the name of the function into our &#8216;Skyline_Finding_Data&#8217; query and when the query gets to that part, it will initiate the GetAccessToken function.\u00a0 Also, with the GetAccessToken query converted to a function, it will not show as entries in the PowerBI report designer view, meaning that you are less likely to have a field on the report that shows your current access token (which could be a security risk).<\/p><p>The process to convert our GetAccessToken query to a function is simple a case of adding the following to the beginning of that query:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-e7addc2 elementor-widget elementor-widget-code-block-for-elementor\" data-id=\"e7addc2\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"code-block-for-elementor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<pre class='line-numbers theme-okaidia' data-show-toolbar='yes'><code class='language-javascript'>() =&gt;<\/code><\/pre>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-6f86fa1 elementor-widget elementor-widget-text-editor\" data-id=\"6f86fa1\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Before you click &#8216;Done&#8217; the full GetAccessToken function should now look like this:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-fac5881 elementor-widget elementor-widget-code-block-for-elementor\" data-id=\"fac5881\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"code-block-for-elementor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<pre class='line-numbers theme-okaidia' data-show-toolbar='yes'><code class='language-javascript'>() =&gt;\r\n\r\nlet\r\n    token_url = &quot;https:\/\/console.cloud.vmware.com\/csp\/gateway\/am\/api\/auth\/api-tokens\/authorize&quot;,    \r\n\r\n   body=&quot;grant_type=refresh_token&amp;refresh_token=YOUR-API-TOKEN&quot;,\r\nSource  = Json.Document(Web.Contents(token_url,\r\n   [ \r\n     Headers = [#&quot;Content-Type&quot;=&quot;application\/x-www-form-urlencoded&quot;,#&quot;Accept&quot;=&quot;application\/json&quot;],\r\n     Content=Text.ToBinary(body)\r\n   ]\r\n   )\r\n   ),\r\n    token = Source[access_token]\r\nin\r\ntoken<\/code><\/pre>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-674c6f4 elementor-widget elementor-widget-text-editor\" data-id=\"674c6f4\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Once you click &#8216;Done&#8217;, the query will be converted to a function.\u00a0 The logo next to the query name will change to a function log and the text will now appear in Italics to indicate that it will no longer be part of the &#8216;Load&#8217; capability that shows the data fields in the PowerBI designer page.\u00a0 It should look similar to below:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-2236ea2 elementor-widget elementor-widget-image\" data-id=\"2236ea2\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" width=\"127\" height=\"32\" src=\"https:\/\/www.virtualworlduk.co.uk\/wordp\/wp-content\/uploads\/2023\/10\/2023-10-19-11_28_00-Testing-using-API-Power-Query-Editor.png\" class=\"attachment-large size-large wp-image-231254\" alt=\"\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-71fc8ea elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"71fc8ea\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-2a7e5d0\" data-id=\"2a7e5d0\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-2636046 elementor-widget elementor-widget-heading\" data-id=\"2636046\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h4 class=\"elementor-heading-title elementor-size-default\">The Final Part of Joining<\/h4>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-81c5a0b elementor-widget elementor-widget-text-editor\" data-id=\"81c5a0b\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>And now we come to the final part of joining the newly created function to our existing query.\u00a0 This takes our query from utilizing a static access token to utilizing the GetAccessToken function we&#8217;ve just been working on.<\/p><p>For this we are going to open our Skyline_Finding_Data query in the &#8216;Advanced Editor&#8217; and we will modify part of this code.<\/p><p>The line that we are going to edit is the &#8216;Data&#8217; line.\u00a0 We will remove our static access token information from that line (the item after Bearer) and will replace it with the details of the function we&#8217;ve just created.\u00a0 This means that the new Data line should read as follows:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-7aecbf5 elementor-widget elementor-widget-code-block-for-elementor\" data-id=\"7aecbf5\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"code-block-for-elementor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<pre class='line-numbers theme-okaidia' data-show-toolbar='yes'><code class='language-javascript'>      Data= Web.Contents(&quot;https:\/\/skyline.vmware.com\/public\/api\/data&quot;,[Content=Text.ToBinary(body),Headers=[#&quot;Content-Type&quot;=&quot;application\/json&quot;,#&quot;Authorization&quot;=&quot;Bearer &quot; &amp; GetAccessToken(),#&quot;accept&quot; = &quot;text\/plain&quot;]]),<\/code><\/pre>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-50baac0 elementor-widget elementor-widget-text-editor\" data-id=\"50baac0\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>One you click &#8216;Done&#8217;, you should be able to &#8216;Refresh Preview&#8217; to get an updated table showing the current findings.\u00a0 If you were to wait 5 minutes or so and then refresh again, the access token will be refreshed and the table would be updated based on the data collected using the new access token.<\/p><p>When you now click &#8216;Close &amp; Apply&#8217; you will have the capability to &#8216;Refresh&#8217; the whole report without needing to adjust the access token each time.<\/p><p>Now you can get on with designing your report to show the information you want it to show.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-54999e7 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"54999e7\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-f8d6b51\" data-id=\"f8d6b51\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-775b9dd elementor-widget-divider--view-line elementor-widget elementor-widget-divider\" data-id=\"775b9dd\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"divider.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-divider\">\n\t\t\t<span class=\"elementor-divider-separator\">\n\t\t\t\t\t\t<\/span>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-89cd355 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"89cd355\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-5a1f930\" data-id=\"5a1f930\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-c4f40da elementor-widget elementor-widget-text-editor\" data-id=\"c4f40da\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>For reference, this is the source I used to help with the creation of the access token function:<\/p><p><a href=\"https:\/\/community.fabric.microsoft.com\/t5\/Desktop\/Power-Query-Open-ID-and-OAuth-2-0-Rest-API\/m-p\/694264\">https:\/\/community.fabric.microsoft.com\/t5\/Desktop\/Power-Query-Open-ID-and-OAuth-2-0-Rest-API\/m-p\/694264<\/a><\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>This is part 3 of this little blog series on my adventure with getting data out of the VMware Skyline API and into PowerBI. In the first part of this series, we went through the process of gaining access to the VMware Skyline API and testing access. The second part of this series concentrated on how to gather the data [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":231248,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"Final part of my blog series on taking VMware Skyline API data into Power BI.","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[49,9],"tags":[],"class_list":["post-231250","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-skyline","category-vmware"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/www.virtualworlduk.co.uk\/wordp\/wp-content\/uploads\/2023\/10\/tn-skyline-animated-overview.jpg","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.virtualworlduk.co.uk\/wordp\/wp-json\/wp\/v2\/posts\/231250","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.virtualworlduk.co.uk\/wordp\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.virtualworlduk.co.uk\/wordp\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.virtualworlduk.co.uk\/wordp\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.virtualworlduk.co.uk\/wordp\/wp-json\/wp\/v2\/comments?post=231250"}],"version-history":[{"count":8,"href":"https:\/\/www.virtualworlduk.co.uk\/wordp\/wp-json\/wp\/v2\/posts\/231250\/revisions"}],"predecessor-version":[{"id":231261,"href":"https:\/\/www.virtualworlduk.co.uk\/wordp\/wp-json\/wp\/v2\/posts\/231250\/revisions\/231261"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.virtualworlduk.co.uk\/wordp\/wp-json\/wp\/v2\/media\/231248"}],"wp:attachment":[{"href":"https:\/\/www.virtualworlduk.co.uk\/wordp\/wp-json\/wp\/v2\/media?parent=231250"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.virtualworlduk.co.uk\/wordp\/wp-json\/wp\/v2\/categories?post=231250"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.virtualworlduk.co.uk\/wordp\/wp-json\/wp\/v2\/tags?post=231250"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}