The Web.Contents() function in M is the key to getting data from web pages and web services, and has a number of useful – but badly documented – options that make it easier to construct urls for your web service calls.
Consider the following url:
It is a call to the metadata api (documentation here) for https://data.gov.uk/, the UK government’s open data portal, and returns a JSON document listing all the datasets found for a search on the keyword “cows”. You can make this call using Web.Contents() quite easily like so:
Web.Contents( "https://data.gov.uk/api/3/action/package_search?q=cows" )
However, instead of having one long string for your url (which will probably need to be constructed in a separate step) you can use the RelativePath and Query options with Web.Contents(). They are given in the second parameter of the function and passed through as fields in a record. RelativePath adds some extra text to the base url given in the first parameter for the function, while Query allows you to add query parameters to the url, and is itself a record.
So, taking the example above, if the base url for the api is https://data.gov.uk/api we can use these options like so:
Web.Contents( "https://data.gov.uk/api", [ RelativePath="3/action/package_search", Query=[q="cows"] ] )
RelativePath is just the string “3/action/package_search” and is added to the base url. There is just one query parameter “q”, the search query, and the search term is “cows”, so Query takes a record with one field: [q=”cows”]. If you want to specify multiple query parameters you just need to add more fields to the Query record; for example:
Web.Contents( "https://data.gov.uk/api", [ RelativePath="3/action/package_search", Query= [ q="cows", rows="20" ] ] )
Generates a call that returns 20 results, rather than the default 10:
Obviously these options make it easier to construct urls and the code is much clearer, but there are also other benefits to using these options which I’ll cover in another blog post soon.
Note: at the time of writing there is a bug that causes the value given in RelativePath to be appended twice when the Web.Page() function is also used. Hopefully this will be fixed soon.
UPDATE January 2021: This blog post has more details on using the Query option: https://blog.crossjoin.co.uk/2021/01/10/handling-multiple-url-query-parameters-with-the-same-name-using-web-contents-in-power-query-power-bi/