Getting started with Azure DevOps API with PowerShell

omiossec profile image Olivier Miossec ・5 min read

I use Azure DevOps every day for different kinds of clients, teams, and projects. I need to set up access, whenever I need Boards, Test Plans or other Azure DevOps services. I also need to decide how to configure the repository or the board. Sometimes I may have to import work items or initialize the wiki.
For some organization or some project, I also need to verify user configuration for compliance, security and license management.
These tasks are manual, time-consuming and I always forget to do one thing or another.

But there is a way to automate Azure DevOps Services set up, the Azure DevOps Rest API. This API lets you perform actions I mentioned and more. This short blog post will explain how.

Note, I will use PowerShell to operate, but you can choose the language of your choice. I use API version 5.1. The documentation can be found here

First, we need a way to authenticate to an Azure DevOps organization. There is two way to authenticate to Azure DevOps, using Azure Active Directory or using a Personal Access Token. It depends on the situation and on what you will need to build. For Azure Active Directory access you will need a client library (for .NET and PowerShell) or you can use Personal Access Token (PAT).

First, we need a way to authenticate to an Azure DevOps organization. There is two way to authenticate to Azure DevOps, using Azure Active Directory or using a Personal Access Token. It depends on the situation and on what you will need to build. For Azure Active Directory access you will need a client library (for .NET and PowerShell) or you can use Personal Access Token (PAT).

To create a Personal Access Token, login to Azure DevOps in this organization. On the right top corner click on the user icon.

PAT Icon

Select "Personal access tokens"

Then Click on "New Token". You will be asked to provide a name for the token, the expiration date, Organization Access, and the scope you want to apply, either all scopes or specify access for Work items, code (git repository), Build, Release, test and packaging.


Defining scope is important for your application; it defines how the application associated with the token will interact with Azure DevOps Services. Unless you are testing the API, never choose full access, review your needs and select the appropriate scopes.

After pushing the "Create" button, the token is displayed. Make sure to save the token securely, there is no way to retrieve it later!

To access Azure DevOps Service Rest API, we need to send a basic authentication header with every http request to the service. The basic authentication HTTP header look like

Authorization: basic

The credential needs to be Base64 encoded. In PowerShell you can do it like this.

$AzureDevOpsAuthenicationHeader = @{Authorization = 'Basic ' + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$($AzureDevOpsPAT)")) }

Do not forget the extra white space between Basic and the “:”

Now that we know how to authenticate to Azure DevOps API, let’s see what we can do with the API.

We need first to build our URI. Using the API you will soon notice the different URI like https://dev.azure.com or https://vssps.dev.azure.com and many more. Most of the time, to be valid the URI needs to include, at least the organization name.

https://dev.azure.com/ or https://vssps.dev.azure.com/

Now, we can start to dig into the API. First, let's try to get a list of all projects within the organization.

Finally, we need to add "_apis"

https://dev.azure.com//_apis or https://vssps.dev.azure.com//_apis

This will be our base URI for most operations.

Let’s start by getting the list of projects inside an organization.

$AzureDevOpsPAT = "ocd2rrtds7bj6mff6jcxjllmaaXXXXXXXXXXXXXXXXXXXXXXXX"

$AzureDevOpsAuthenicationHeader = @{Authorization = 'Basic ' + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$($AzureDevOpsPAT)")) }

$UriOrga = "https://dev.azure.com/$($OrganizationName)/" 
$uriAccount = $UriOrga + "_apis/projects?api-version=5.1"

Invoke-RestMethod -Uri $uriAccount -Method get -Headers $AzureDevOpsAuthenicationHeader 

The API will return two elements. Count, the number of projects in the current organization and value, an array with the name, ID, visibility, revision, URI and last update time for each project.

Now how can we add a new project by using the rest API?

To create a project we need to provide a name, an optional description, visibility (private or public), a source control (Git or TFS) and the process model.
We need the process model ID and not only the name. This is because you can create your process model.

To get the process module ID, we must use another request to the API to get these ID.

$uriProcess = $UriOrga + "_apis/process/processes?api-version=5.1"
Invoke-RestMethod -Uri $uriProcess -Method get -Headers $AzureDevOpsAuthenicationHeader

Now we can start to build the request body to add a project. For the process template I choose the Basic Process, b8a3a935-7e91-48b8-a94c-606d37c3e9f2.

$projectConfiguration = @{
        "name" = "TestProject"
        "description" = "Test Project"
        "ProjectVisibility" = "private"
        "capabilities" = @{
            "versioncontrol" = @{
                "sourceControlType" = "Git"
            "processTemplate" = @{
                "templateTypeId" = "b8a3a935-7e91-48b8-a94c-606d37c3e9f2"
}  | ConvertTo-Json -Depth 5

Invoke-RestMethod -Uri $uriProject -Method Post -Headers $AzureDevOpsAuthenicationHeader -Body $projectConfiguration -ContentType "application/json"

The API does not create the project right away. Instead, it queues de request and response with a 202 Accepted HTTP code and 3 values, an ID on the request, a status (not set or queue most of the time) and a URI.

The last URI can be used to monitor the project creation.

We can now add users to this project. But we need first to list users currently in the organization. There are 3 kinds of users in an Azure DevOps organization, Azure Active Directory user, Microsoft Account user and build user (services). This is what you see in the organization settings.

$uriOrgaUsers = "https://vsaex.dev.azure.com/$($OrganizationName)/_apis/userentitlements?api-version=5.1-preview.2"

(Invoke-RestMethod -Uri $uriOrgaUsers  -Method get -Headers $AzureDevOpsAuthenicationHeader).members

With our user list, we can add them to the project we created in the last steps. We can not add members directly to the project. By default, when we created the project the Azure DevOps service create a default team, named after project name.

We can get the default Team ID by query the Project properties.

$UriOrga = "https://dev.azure.com/$($OrganizationName)/" 
$ProjectID = "576e2e9d-c7ee-4fd5-XXXXXXXXXX"

$uriProject = $UriOrga + "_apis/projects/$($ProjectID)/properties?api-version=5.1-preview.1"

(Invoke-RestMethod -Uri $uriProject -Method get -Headers $AzureDevOpsAuthenicationHeader).value

We can add the user to this team by using the Team ID and one of the user IDs we collected.

$TeamID = "5a18ffd6-1f25-44b0XXXXXXXXXX"
$userID = "3fa53ee0-XXXXXXXXx"

$AddUserUri = "https://vsaex.dev.azure.com/$($OrganizationName)/_apis/GroupEntitlements/$($TeamID)/members/$($userID)?api-version=5.1-preview.1"

Invoke-RestMethod -Uri $AddUserUri -Method put -Headers $AzureDevOpsAuthenicationHeader

With the Azure DevOps Services Rest API, you can automate Projects, Teams creation, and onboarding. You can also create a git branch, a pull request or work items, and many other things.

The difficult part, as you may notice, the URL is not unified, and you may have to deal with API version and URI. You will need to follow the documentation and the internal logic of the product. But after a few tries, you will be able to what you need.

Posted on by:

omiossec profile

Olivier Miossec


Microsoft Azure MVP, Passionate about Cloud and DevOps. Co-organizers of the French PowerShell UG and Paris PowerShell & WinOps UG. I live in Paris.


markdown guide

Hi Olivier Miossec,
I have followed the above things and it works well. But my case is - Delete the bulk set of test cases through PowerShell. I have also checked MS Doc reg this - docs.microsoft.com/en-us/azure/dev... . Bulk deletion is not supported at present from a query results page. So, I have to do it by using either .net or powershell. By reading the above article, i am little bit good and familiar with powershell. but it throws error for me when i tried bulk delete test case. Can you help me reg this. i have posted this as question here - stackoverflow.com/questions/620202...


Hi Olivier,
I am getting error after executing below Invoke-restMethod,
Invoke-RestMethod -Uri $uriProject -Method Post -Headers $AzureDevOpsAuthenicationHeader -Body $projectConfiguration -ContentType "application/json"

Below is the error mesaage:
Invoke-RestMethod : Invalid URI: The hostname could not be parsed.
At line:1 char:1

  • Invoke-RestMethod -Uri $uriProject -Method Post -Headers $AzureDevOps ...
  • ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    • CategoryInfo : NotSpecified: (:) [Invoke-RestMethod], UriFormatException
    • FullyQualifiedErrorId : System.UriFormatException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

Please help me resolve this error so I can try to create a Project and go-ahead.


Using API, How to get the latest code from TFVC repo in Azure Devops ? Example
Thanks in advance!


Hi, I had this error in the step when creating project Configuration

Invoke-RestMethod : {"count":1,"value":{"Message":"The requested resource does not support http method 'POST'."}}