Using Power Query to get data from an API that uses a Username and Password combination
In the blog post I am going to show you the steps that I took to get data from the XE.COM API which uses a username and password to log into the API
You might be thinking that I could put in the username and password when I used the Web Connector.
My challenge is that I wanted to create a function that I could pass through multiple currencies to the API. And in order to do that I wanted to store the details within the function.
Creating the encoded values to pass through in the headers
In order to pass through the authentication this had to be done in the API call in the headers section.
Something that took me a while to figure out was that I had to encode the username and password in Base64 and in a particular format in order for this to work.
-
The format required to encode my username and password was “username:password”
- For example my Username was: GilbertQ
- And my password was: Password1234
- The format to encode would be “GilbertQ:Password1234”
-
I then went to the following site: https://www.base64encode.org/
- I then put in my details above and clicked on Encode
-
I then copied the output
- a2FtYWxhdGVjaDM4OTEwMTAxMTphcWtvdmdlcDN2OTk1a3VvazFtajQzZDZkdQ==
Changing the Web Connector to use the Authentication in the Headers
I then needed to update the Web.Contents to include the headers
-
This is what my Web.Contents looked like initially
// My Function to extract the Exchange Rates fx_MyExchangeRate = (FromCurrencyISO as text, StartDate as text) => let Source = Json.Document(Web.Contents("https://xecdapi.xe.com/v1/historic_rate.json/?from=" & FromCurrencyISO & "&date=" & StartDate & "&to=USD,GBP,EUR&amount=1" )),
-
I had to then change the connector from Basic to Anonymous, this is because I am embedding the authentication as part of the headers.
- I then updated it and the trick was I had to put in the Headers section in the right area.
-
I also had to then put in the authorization of Basic and then put in the Encoded value as shown below.
-
// My Function to extract the Exchange Rates fx_MyExchangeRate = (FromCurrencyISO as text, StartDate as text) => let Source = Json.Document(Web.Contents("https://xecdapi.xe.com/v1/historic_rate.json/?from=" & FromCurrencyISO & "&date=" & StartDate & "&to=USD,GBP,EUR&amount=1", [Headers = [#"Authorization"="Basic a2FtYWxhdGVjaDM4OTEwMTAxMTphcWtvdmdlcDN2OTk1a3VvazFtajQzZDZkdQ=="]] )),
- As you can see above in line 6 is where I added the value
-
This is what it looked like in Power Query
-
Finally, when I then ran my query, I could then successfully see the values
Summary
As shown in this blog post I have embedded my username and password for my API within the headers section of the API call. I also explained and showed how to create the encoding value and then where to put it within Power Query.
Thanks for reading I hope you found this interesting and useful.
Great stuff, does this work in scheduled refreshes through the gateway?
Hi there
It should work because it is using the Web.Contents.
I wish using Web.Contents was enough to make it work for scheduled refresh but searching “Power BI API Scheduled Refresh” reveals the pain so many of us have felt when getting something working in Power BI Desktop only to have it not work in the service. I haven’t tried it yet but my suspicion is your URL will be deemed “dynamic” and the gateway will refuse to refresh due to “unsupported functions”
http://blog.datainspirations.com/2018/02/17/dynamic-web-contents-and-power-bi-refresh-errors/
https://blog.crossjoin.co.uk/2016/08/23/web-contents-m-functions-and-dataset-refresh-errors-in-power-bi/
Hi there
I have not tested it myself that might happen.
The issue is the Power BI service wants to validate the URI before it commits to refreshing the data source. Because the URI isn’t static, there is no URI to validate”
I’ve only got web.contents working in the service refresh for an API data-source by using the relative path and query options for this function.
Chris Webb helped me with this and talks about this on his blog.
https://blog.crossjoin.co.uk/2016/08/16/using-the-relativepath-and-query-options-with-web-contents-in-power-query-and-power-bi-m-code/
Also again here is useful info too http://blog.datainspirations.com/2018/02/17/dynamic-web-contents-and-power-bi-refresh-errors/
[…] Gilbert Quevauvilliers has a challenge: […]