Home / Guides / Let customers create Azure DevOps work items
Let customers create Azure DevOps work items without an Azure DevOps license
Your team tracks everything in Azure Boards, but customers report problems by email, and someone copies each one into a work item by hand. Can customers raise the work item themselves without you paying for a license for each of them? Yes, in two free ways. This guide covers both, gives you a script for the second one, and explains where each one stops.
Short answer.
Azure DevOps gives unlimited users Stakeholder access for free, and Stakeholders can create and edit work items. But each customer then becomes a member of your organization and can see the project. The other free way is a web form that creates the work item for the customer through the REST API, under an identity of your own. The customer never touches Azure DevOps, but they also never see what happens to their request. A customer portal such as BoardwalkDesk covers both halves.
Option 1: give customers free Stakeholder access
Stakeholder is an access level, like Basic. It costs nothing, and there is no limit to how many Stakeholders an organization can have. In a private project a Stakeholder can create and modify work items, save their own queries, view boards and dashboards, and follow work items to get email when they change. They cannot use Azure Repos, cannot author pipelines, and can only assign tags that already exist. To add one, open Organization settings > Users > Add users, choose Stakeholder as the access level and add them to the project.
That works well for people inside your company. For outside customers, think about what else comes with it:
- They join your directory. If your organization is connected to Microsoft Entra ID, every external customer must be added to your Entra tenant as a guest, and the organization's External guest access policy must be on. Microsoft notes that this also gives those users access to more organization-level resources.
- They can see the whole project by default. Members of the project's Contributors group can view every work item in it, including those raised by other customers, and every comment your team writes on them. To hide work, put customers in their own group and set View work items in this node to Deny on each area path they must not see. Remember this every time you add an area.
- Stakeholder is not a restriction. A user who has a Visual Studio subscription or a GitHub Enterprise license is upgraded from Stakeholder when they sign in. Microsoft's own advice is not to use Stakeholder access in place of tighter permissions.
- It is Azure DevOps. Customers learn your area paths, states and work item forms, which is a lot to ask of someone who wants to report a bug.
Option 2: a form that creates the work item for them
The customer fills in a form on your website or intranet, and your code creates the work item with the REST API under an identity you
own. The call is POST https://dev.azure.com/{organization}/{project}/_apis/wit/workitems/${type}?api-version=7.1 with a
JSON Patch body (content type application/json-patch+json). This PowerShell script is the core of such a form: it
creates one work item from a title, a description and the customer's email address.
# New-CustomerWorkItem.ps1: creates one Azure DevOps work item from a customer's request.
# Uses a Microsoft Entra token from the Azure CLI (az login, az login --identity or --service-principal).
param(
[Parameter(Mandatory)][string]$Organization,
[Parameter(Mandatory)][string]$Project,
[Parameter(Mandatory)][string]$Title,
[Parameter(Mandatory)][string]$Description,
[Parameter(Mandatory)][string]$CustomerEmail,
[string]$Type = 'Issue',
[string]$AreaPath,
[string]$Tags = 'Customer request'
)
# 499b84ac-1321-427f-aa17-267ca6975798 is the resource ID of Azure DevOps.
$token = az account get-access-token --resource 499b84ac-1321-427f-aa17-267ca6975798 --query accessToken -o tsv
if (-not $token) { throw 'No Azure DevOps token. Sign in with az login first.' }
# The Description field is HTML: encode what the customer typed.
$enc = [System.Net.WebUtility]
$html = '<p>' + ($enc::HtmlEncode($Description) -replace "`r?`n", '<br>') + '</p>' +
'<p><em>Raised by ' + $enc::HtmlEncode($CustomerEmail) + ' through the support form.</em></p>'
$patch = @(
@{ op = 'add'; path = '/fields/System.Title'; value = $Title }
@{ op = 'add'; path = '/fields/System.Description'; value = $html }
@{ op = 'add'; path = '/fields/System.Tags'; value = $Tags }
)
if ($AreaPath) { $patch += @{ op = 'add'; path = '/fields/System.AreaPath'; value = $AreaPath } }
$uri = 'https://dev.azure.com/{0}/{1}/_apis/wit/workitems/${2}?api-version=7.1' -f
$Organization, [uri]::EscapeDataString($Project), [uri]::EscapeDataString($Type)
$body = [System.Text.Encoding]::UTF8.GetBytes((ConvertTo-Json -InputObject $patch -Depth 3))
$wi = Invoke-RestMethod -Method Post -Uri $uri -Body $body `
-ContentType 'application/json-patch+json; charset=utf-8' `
-Headers @{ Authorization = "Bearer $token" }
"Created work item $($wi.id): $($wi.fields.'System.Title')"
Run it like this, after az login with an account that may create work items in the project:
.\New-CustomerWorkItem.ps1 -Organization contoso -Project Support `
-Title 'Export to Excel fails' -Description 'Clicking Export shows an error since this morning.' `
-CustomerEmail 'pat@example.com' -Type Bug -AreaPath 'Support\Web app'
A few details that trip people up:
- The work item type depends on the process. Use a type your project has: Issue or Task in Basic, Bug or Issue in Agile and CMMI, Bug or Product Backlog Item in Scrum.
- The body must be a JSON array, even with one field in it. The script passes the list to
ConvertTo-Jsonwith-InputObject, which keeps it an array in Windows PowerShell 5.1 as well. It also sends the body as UTF-8 bytes, so names with accents arrive intact. - Customer text is HTML-encoded. The Description field holds HTML. Encoding what the customer typed stops a form post from adding its own markup to your work item.
- Tags must exist if the identity has Stakeholder access, because Stakeholders can only assign existing tags. Create the tag once by hand.
Which identity should create the work items?
Not a person's personal access token (PAT) pasted into a web server. For a form that runs as a service, use a Microsoft Entra
service principal or, on Azure, a managed identity. Add it to the organization under
Organization settings > Users like any member, give it the lowest access level that works
(Stakeholder can create work items), and add it to the project. It asks Entra for short-lived tokens, so there is no PAT to expire or
leak. On a server where it is signed in with az login --service-principal or az login --identity, the script above
works unchanged.
If you must use a PAT, create it for one organization only, with only the Work Items (Read & write) scope and the shortest lifetime you can live with, store it in a secret store, and send it as basic authentication instead of the bearer token. Microsoft recommends Entra tokens over PATs and is retiring global (all-organization) PATs.
Where the do-it-yourself form stops
Creating the work item is the easy part. A support process also needs everything that happens after it:
- The customer hears nothing back. They cannot see the state, the answer or the fix. Sending updates means subscribing to work item updated service hooks, deciding which changes are worth an email, and sending it.
- They cannot reply. Replies to your questions come back by email and get copied in by hand again.
- Anyone can post. The form does not know who the customer is. Without sign-in, anyone who finds it can create work items in your backlog under any email address.
- Internal comments need rules. Once customers can see a ticket, you need a way to keep notes, agent names and links into Azure DevOps away from them.
- Attachments mean uploads, size limits and scanning before anything reaches the work item.
- You maintain it. The form, the identity, the hooks and the mail are all code and credentials someone has to look after.
Questions
Can people without an Azure DevOps license create work items?
Yes. Stakeholder access is free for an unlimited number of users and lets them create and modify work items. They still need an account in your organization (for an organization connected to Microsoft Entra ID, external people are added as guests). Without any account, people can only raise work items through something that creates them on their behalf, such as a form that calls the REST API or a customer portal.
Is Stakeholder access really free?
Yes. Stakeholder access costs nothing and has no user limit. The first five users with Basic access are also free; after that, Basic is paid per user. Users with a Visual Studio subscription or GitHub Enterprise license get their higher access automatically.
Can a Stakeholder see other customers' work items?
By default, yes: project members can view every work item in the project. You can hide work by setting the area path permission View work items in this node to Deny for the customers' group, on every area they must not see.
Does a service principal that creates work items need a paid license?
No, not for this. An application identity gets an access level like any user, and Stakeholder access is enough to create work items. It needs Basic only for features such as Azure Repos.
Do BoardwalkDesk customers need an Azure DevOps account?
No. Customers open the desk's web address, enter their email and sign in with a one-time code sent to them. Their tickets are work items in your own Azure DevOps project; BoardwalkDesk supports organizations connected to Microsoft Entra ID.
Related
- BoardwalkDesk: a customer service desk for Azure DevOps
- Which projects use a NuGet package, and the build order
- All guides
Sources (Microsoft Learn): About access levels, Stakeholder access quick reference, Add organization users and manage access, Add external users to your organization, Set work tracking permissions, Work Items - Create (REST API 7.1), Use service principals and managed identities in Azure DevOps, Issue Entra tokens with Azure CLI, Use personal access tokens.