How to call Azure Devops REST API from PowerShell

Posted on 09th April 2020

Azure DevOps REST API allows you to programmatically access, create, update and delete Azure DevOps resources such as Projects, Teams, Git repositories, Test plan, Test cases, Pipelines. REST API stands for REpresentational State Transfer Application Programmers Interface. It allows clients to get information about resources or to take actions on resources. A resource is any object such as Project, Team, Repository, commit, files, test case, test plan, pipeline, release, etc., and an action can be to create, update or delete a resource.

Every resource has a unique identifier which is an URL, also known as a service endpoint. A client makes request to Azure DevOps server to fetch a resource by providing its endpoint. The request is in the form of an HTTP method - GET, PUT, POST, PATCH, DELETE and HEAD, also known as a verb.

The server sends a response back to the client which is in JSON format and contains the state of the resource. For example, an application (client) makes a HTTP GET request to get a list of projects and Azure DevOps service returns a JSON object that contains projects names, descriptions, project state, visibility and other information related to the projects in the organization.

You can build a client application in any programming language that allows you to call HTTP methods. In this tutorial we use PowerShell to demonstrate how to use Azure DevOps REST API to

  • Get the list all projects.
  • Create a new project.
  • Get project properties.
  • Change a project's description.
  • Delete a project

The first step in working with Azure DevOps REST API is to authenticate to an Azure DevOps organization. There are two ways of doing this.

  1. Using Azure Active Directory
  2. Using a Personal Access Token

In this tutorial we will use a PAT.

Creating a Personal Access Token (PAT)

To create a PAT,

  • Login to your organization in Azure DevOps.{yourorganization}
  • Click User settings icon from your home page and select Personal access tokens.

    Personal Access Tokens
  • Click + New Token, then enter a name for the token.
    Create new PAT
  • Select your organization.
  • Set Expiration to the default 30 days.
  • Select Full Access for this token.
  • Click Create.
  • Token Successfully added message will be displayed. Copy the token to clipboard and paste it on a text file and save to a secure location. We will use this token on our PowerShell script.
    Save Token

PowerShell Script to call REST API

Now that you have created the token, you can use that token to call the Azure DevOps REST API. The following script use Invoke-RestMethod cmdlet to send HTTPS request to Azure DevOps REST service which then returns data in JSON format. This script uses REST API version 5.1 and tested on PowerShell version 7.0

# Define organization base url, PAT and API version variables
$orgUrl = ""
$pat = "va4fw7wjeziwynzmubx3hiughcrgdu4q74u36z2ymasfcqndq"
$queryString = "api-version=5.1"

# Create header with PAT
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($pat)"))
$header = @{authorization = "Basic $token"}

# Get the list of all projects in the organization
$projectsUrl = "$orgUrl/_apis/projects?$queryString"
$projects = Invoke-RestMethod -Uri $projectsUrl -Method Get -ContentType "application/json" -Headers $header
$projects.value | ForEach-Object {
   Write-Host $ $

# Create new project named OTGRESTDemo
$projectName = "OTGRESTDemo"
$createProjectURL = "$orgUrl/_apis/projects?$queryString"
$projectJSON = @{name = "$($projectName)"
               description = "OTG Azure DevOps REST API Demo"
               capabilities = @{
                  versioncontrol = @{
                     sourceControlType = "Git"
                  processTemplate = @{
                     # Basic Project
                     templateTypeId = "b8a3a935-7e91-48b8-a94c-606d37c3e9f2"
            } | ConvertTo-Json
$response = Invoke-RestMethod -Uri $createProjectURL -Method Post -ContentType "application/json" -Headers $header -Body ($projectJSON )

# Wait for 5 seconds
Start-Sleep -s 5

# Get Operation Status for Create Project
$operationStatusUrl = "$orgUrl/_apis/operations/$($$queryString"
$response = Invoke-RestMethod -Uri $operationStatusUrl -Method Get -ContentType "application/json" -Headers $header
Write-Host "Create Project Status: $response.status"

# Get detailed project information
$projectDetailsUrl = "$orgUrl/_apis/projects/$($projectName)?includeCapabilities=True&$queryString"
$projectDetails = Invoke-RestMethod -Uri $projectDetailsURL -Method Get -ContentType "application/json" -Headers $header
$projectId = $
Write-Host ($projectDetails | ConvertTo-Json | ConvertFrom-Json)

# Update Project description of OTGRESTDemo project
$jsonData = @{description = "This is the updated project description for OTGRESTDemo"
         } | ConvertTo-Json
$projectUpdateURL = "$orgUrl/_apis/projects/$($projectId)?$queryString"
$response = Invoke-RestMethod -Uri $projectUpdateURL -Method PATCH -ContentType "application/json" -Headers $header -Body ($jsonData)

# Wait for 5 seconds
Start-Sleep -s 5

# Get Update Operation Status
$operationStatusUrl = "$orgUrl/_apis/operations/$($$queryString"
$response = Invoke-RestMethod -Uri $operationStatusUrl -Method Get -ContentType "application/json" -Headers $header
Write-Host "Update Project Status:" $response.status

$confirmation = Read-Host "Are you sure you want to delete the project $($projectName) (y/n)"
if ($confirmation.ToLower() -eq 'y') {
	# Delete a project
	$deleteURL = "$orgUrl/_apis/projects/$($projectId)?$queryString"
	$response = Invoke-RestMethod -Uri $deleteURL -Method Delete -ContentType "application/json" -Headers $header
	# Wait for 5 seconds
	Start-Sleep -s 5
	# Get Update Operation Status
	$operationStatusUrl = "$orgUrl/_apis/operations/$($$queryString"
	$response = Invoke-RestMethod -Uri $operationStatusUrl -Method Get -ContentType "application/json" -Headers $header
	Write-Host "Delete Project Status:" $response.status
} else {
    Write-Host "Project not deleted. Scipt completed."

For more information about REST API resources and endpoints, see Azure DevOps REST API Reference

Post a comment


Nothing the first to share wisdom.