All too often I have seen people have multiple copies of the same file, all with a different version and all local on their machines. This goes against everything that Source Control is intended for. This blog will outline the VSTS Git API and give an example of how to download a file from Source Control using PowerShell. I personally use this to download ARM templates when programatically deploying Azure Resources. This ensures the template is always up to date and resolves the issue of having multiple copies locally.


The full API documentation can be found on Visual Studio here. For this blog we will be focusing on the Items API which is used to interact with items within Source Control. From the API documentation we can see that the required URL is


which will provide us with an application/octet-stream response of the file which we can then store in memory or output to a file. This API requires the minimum parameters for the URL which are:

  • Instance – the website where VSTS is hosted. Referred to in my examples as VSTS Site
  • Project – the name of the team project. Referred to in my examples as Project
  • Repository – the Repository where the files are located. Referred to in my examples as Repository
  • File Path – the full path to the file including any directories and slashes. Referred to in my examples as File Name

As soon as we have this information we can build the URL and send the GET request to the API.
$url = "https://{0}/DefaultCollection/{1}/_apis/git/repositories/{2}/items?api-version=1.0&scopePath={3}" -f $VSTSSite, $project, $repository, $filepath

However, this gives a HTTP 203 response and did not stream my file like it was supposed to. Why? Authentication! There are multiple ways to authenticate the VSTS Git API but the simplest, and what I am using here, is a Personal Access Token. Documentation on that can be found here . Once we have our token we can continue to add the authentication to our request and get the response we require.

The authentication needs to go into the headers of the request. There are 2 keys required:

  • Authorization – Base 64 authentication information based off the Personal Access Token
  • Accept – The content type to return, usually application/octet-stream

$VSTSPat = 'demoToken'
$VSTSSite = 'company.visualstudio.com'
$project = 'Demo'
$repository = 'Demo'
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f ' ', $VSTSPat)))
$filepath = '/AzureRM/AzureAutomation/WindowsVM.json'
$headers = @{
"Authorization" = ("Basic {0}" -f $base64AuthInfo)
"Accept" = "application/octet-stream"

Now that we have our headers we can authenticate the API and get a HTTP 200 response.
$invoke = Invoke-WebRequest -Uri $url -Method Get -Headers $headers -UseBasicParsing
The response is in the .content property of the object and, as expected, is a series of Bytes which is of no use to us. These Bytes can be converted back into a String using the ASCII.GetString method of the System.Text.Encoding class.

$file = [System.Text.Encoding]::ASCII.GetString($invoke.Content)

We now have our file from Source Control in memory and can do with it as we wish. We could have also specified the -OutFile parameter on the Invoke-WebRequest Cmdlet which would have taken care of the conversion for us.

This blog covered how to download files from Source Control using the VSTS Git API. Hopefully this was helpful. Feel free to leave any comments or questions. 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.