Azure DevOps Python API Client
The `azure-devops` library provides a Pythonic wrapper around the Azure DevOps REST APIs, enabling programmatic interaction with Azure DevOps Services and Azure DevOps Server. It allows developers to automate tasks, manage resources like work items, repositories, pipelines, and more. The library has a frequent release cadence, often releasing beta versions to align with the latest Azure DevOps API versions, currently focusing on 7.x APIs.
Common errors
-
ModuleNotFoundError: No module named 'azure.devops'
cause The `azure-devops` package or its dependencies are not installed, or the Python environment running the script does not have access to the installed packages.fixEnsure the `azure-devops` library is installed in the active Python environment. If using Azure Pipelines, verify `requirements.txt` includes `azure-devops` and `pip install -r requirements.txt` is run, or explicitly install it using `pip install azure-devops`. -
vsts.exceptions.VstsClientRequestError: Operation returned an invalid status code of 405
cause This error typically indicates that the HTTP method used (e.g., POST, GET) is not allowed for the requested resource, or the URL used to access the Azure DevOps API is incorrect, often due to using HTTP instead of HTTPS.fixVerify that the base URL for the `VssConnection` uses `https://` (e.g., `https://dev.azure.com/{organization}`) and that the API endpoint and HTTP method are correct for the intended operation. For example, creating a work item usually requires a POST request to a specific endpoint. -
TypeError: get_work_items() got an unexpected keyword argument 'query'
cause The `get_work_items` method of the `WorkItemTrackingClient` does not accept a direct `query` keyword argument. Instead, it expects a list of work item IDs or requires a separate WIQL (Work Item Query Language) client to execute queries.fixTo retrieve work items using a WIQL query, use the `query_by_wiql` method of the `WorkItemTrackingClient` with a `Wiql` object, then use the returned work item references to fetch the full work items. To get work items by ID, pass a list of IDs to `get_work_items(ids=desired_ids)`. -
AzureDevopsServiceError: Failed to authenticate using the supplied token.
cause The Personal Access Token (PAT) used for authentication is expired, revoked, has insufficient permissions, or is incorrectly provided.fixGenerate a new Personal Access Token in Azure DevOps with the necessary scopes (e.g., Work Items, Code, Build, Release), ensuring it has not expired. Update the PAT in your script or environment variables. Also, confirm the PAT is being passed correctly to `BasicAuthentication` or `PersonalAccessToken`. -
AttributeError: 'VssConnection' object has no attribute 'build_client'
cause Specific clients like `build_client` are not directly attributes of the `VssConnection` object. Instead, they must be retrieved using the `get_client()` method with the appropriate client class from the `azure-devops` SDK.fixAccess the client using `connection.get_client(BuildClient)` (or the respective client for your desired service, e.g., `WorkItemTrackingClient`, `GitClient`) after importing it from the correct versioned module (e.g., `from azure.devops.v7_1.build.build_client import BuildClient`).
Warnings
- breaking The library closely tracks Azure DevOps REST API versions. Upgrading to a new major library version (e.g., from 6.x to 7.x) may introduce breaking changes in API client method signatures, return types, or data shapes, requiring code adjustments to align with the new underlying REST API version.
- gotcha When using Personal Access Tokens (PATs) with `BasicAuthentication`, ensure the username is an empty string and the PAT is passed as the password. Issues can arise if PATs are not correctly formatted or if underlying HTTP clients in redirects strip authentication headers, leading to 401/403 errors.
- gotcha The library might encounter deserialization errors (e.g., incorrect type casting from `int` to `float` or unexpected JSON structures) when processing API responses, especially with new or evolving API endpoints or specific data fields.
- gotcha Running against Azure DevOps Server (on-premises) might lead to compatibility issues if the client library utilizes preview API versions (e.g., `7.1-preview.1`) that are not yet supported by your specific server installation, potentially causing unexpected errors or missing functionality.
- gotcha Certain functionalities (e.g., working with Excel files for migration, advanced work item field manipulation) may require additional, implicitly optional dependencies (e.g., `openpyxl`). A `ModuleNotFoundError` or `ImportError` typically indicates a missing optional package for your specific use case.
Install
-
pip install azure-devops
Imports
- Connection
from azure.devops import Connection
from azure.devops.connection import Connection
- BasicAuthentication
from azure.devops.authentication import BasicAuthentication
from msrest.authentication import BasicAuthentication
Quickstart
import os
from azure.devops.connection import Connection
from msrest.authentication import BasicAuthentication
import pprint
# Retrieve organization URL and Personal Access Token from environment variables
organization_url = os.environ.get('AZURE_DEVOPS_ORG_URL', 'https://dev.azure.com/YOUR_ORGANIZATION')
personal_access_token = os.environ.get('AZURE_DEVOPS_PAT', 'YOUR_PERSONAL_ACCESS_TOKEN')
if not organization_url or organization_url == 'https://dev.azure.com/YOUR_ORGANIZATION':
print("Please set the AZURE_DEVOPS_ORG_URL environment variable or update the placeholder.")
exit(1)
if not personal_access_token or personal_access_token == 'YOUR_PERSONAL_ACCESS_TOKEN':
print("Please set the AZURE_DEVOPS_PAT environment variable or update the placeholder.")
exit(1)
# Create a connection to the organization
credentials = BasicAuthentication('', personal_access_token)
connection = Connection(base_url=organization_url, creds=credentials)
# Get a client (the 'core' client provides access to projects, teams, etc.)
core_client = connection.clients.get_core_client()
try:
# Get the first page of projects
get_projects_response = core_client.get_projects()
print("Successfully connected to Azure DevOps. Projects:")
index = 0
while get_projects_response is not None:
for project in get_projects_response.value:
pprint.pprint(f"[{index}] {project.name}")
index += 1
if get_projects_response.continuation_token:
get_projects_response = core_client.get_projects(continuation_token=get_projects_response.continuation_token)
else:
get_projects_response = None
except Exception as e:
print(f"An error occurred: {e}")