Connect Azure DevOps Boards so Escape can create work items from issues, attach request evidence, and keep status in sync both ways.

> [!IMPORTANT]
>
> **Workflow Required for Work Item Creation**
>
> A workflow must include an Azure Boards export action before Escape can create work items. After you connect the integration, [create a workflow](<https://docs.escape.tech/documentation/automate/workflows/index.md>) with that export action.

## Configuration

### Create an Azure Boards Integration

1. Go to the [Integrations page](<https://app.escape.tech/integrations-next/>) from the left navigation menu.
2. Open the [Azure Boards](<https://app.escape.tech/integrations-next/azure-boards>) card in the **Ticketing** section.
3. Click **\+Create new integration**.
4. Set **Enter your integration's name**.
5. Choose **Authentication**: **PAT** or **Entra**.
6. Set **Azure DevOps organization URL** to the org base URL, for example `https://dev.azure.com/my-organization`.
7. Fill the fields for the selected method, then save.
8. Under **Network Configuration**, pick the location Escape should use to connect to Azure Boards. Use a private location when the instance isn't reachable from the public internet.
9. Click **Test Integration**. Validation lists projects visible to the credentials.

#### PAT

Use an Azure DevOps [personal access token](<https://learn.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate>) with both of these scopes, on at least one project:

- **Work Items**: Read &amp; write (`vso.work_write`)
- **Project and team**: Read (`vso.project`)

#### Entra

##### Entra Setup

On the Entra app, add this redirect URI (your Escape app host, path unchanged):

```text
https://app.escape.tech/integrations-next/azure-boards/oauth/callback
```

On the Entra app, add [Azure DevOps delegated permissions](<https://learn.microsoft.com/en-us/azure/devops/integrate/get-started/authentication/entra-oauth>). Escape requests `offline_access` plus the Azure DevOps resource `.default` (`499b84ac-1321-427f-aa17-267ca6975798/.default`), so the app registration must include the Azure DevOps delegated permission you need (typically `user_impersonation`, or granular Work Items and Project scopes). Grant user or administrator consent for those permissions.

The Azure DevOps organization policy **Third-party application access via OAuth** applies only to legacy Azure DevOps OAuth apps. It doesn't grant this Entra app access.

##### Azure Boards Setup

Register a Microsoft Entra application, then in Escape fill:

- **Entra tenant ID**
- **Application (client) ID**
- **Client secret**

Save the integration before you **Connect** to Azure Boards.

Click **Connect**. Escape opens Microsoft's authorize endpoint for that tenant (`oauth2/v2.0/authorize`) with `response_type=code` and those scopes. After consent, Escape stores the access token and refresh token on the integration.

If **Test Integration** succeeds but lists zero projects, confirm consent succeeded and that the signed-in user can see at least one project with Work Items access.

Click **Connect** again later to refresh consent. Auth method stays Entra; you can't switch a saved integration to PAT.

> [!WARNING]
>
> **Never share your PAT or client secret**
>
> Create a dedicated PAT or Entra app for Escape. Don't reuse a personal token you also use in a browser.

### Edit an Azure Boards Integration

1. Go to the [Integrations page](<https://app.escape.tech/integrations-next/>).
2. Open the [Azure Boards](<https://app.escape.tech/integrations-next/azure-boards>) card.
3. Click **Edit** next to the integration.
4. Update the URL, credentials, or network location. Auth method stays locked.
5. For Entra, click **Connect** again if you need a new consent.
6. Save, then **Test Integration**.

### Delete an Azure Boards Integration

1. Go to the [Integrations page](<https://app.escape.tech/integrations-next/>).
2. Open the [Azure Boards](<https://app.escape.tech/integrations-next/azure-boards>) card.
3. Click **Delete** next to the integration.

> [!WARNING]
>
> **Consequences of Deleting an Integration**
>
> Deleting the integration stops workflows that export with it, and you can no longer create work items from those workflows or the Ticketing sidepanel using that connection.
>
> Update or remove those workflows first, or create a replacement integration.

## Using Azure Boards in Workflows

Add an **Export** action and select **Azure Boards**, then pick the integration.

Supported workflow triggers:

| Trigger | What the export does |
| --- | --- |
| **New Issue** | Creates and links a work item |
| **Manual** | Creates and links a work item (used from the Ticketing sidepanel) |
| **Issue Updated** | Moves the linked work item state when the Escape issue is `OPEN` or `RESOLVED` |

### Project, Type, and Parent

- **Azure Boards project**: project where work items are created. Changing project clears type and parent.
- **Work item type**: type in that project (for example Bug, Issue, User Story).
- **Parent work item** (optional, create triggers only): Escape adds a `System.LinkTypes.Hierarchy-Reverse` relation to that work item id.

### Default Title and Description

Unless you enable **Disable default mappings**, Escape sets:

- `System.Title`: the issue’s full display name
- `System.Description`: issue context and remediation. To include an Escape link, explicitly map a link property, such as **Link in All Issues**, to an Azure field.

If you enable **Disable default mappings**, map title and description yourself with property or static mappings.

After creation, Escape attaches HTTP exchanges for the issue from the workflow’s scan, or the issue’s last-seen scan when no scan is specified. The work item attachments use filenames such as `exchange-{id}.json`. A failed upload is logged as a warning; the work item still exists.

### Property Mappings

Map Escape properties onto Azure field **reference names** (`System.Title`, `Microsoft.VSTS.Common.Priority`). The field picker loads fields from the selected project via the Azure DevOps Work Item Tracking API (`api-version=7.1`).

These Escape properties support **option mapping** (one Escape value to one Azure allowed value): Severity, Category, Status, Asset Class, Asset Tags, Asset Type.

Available Escape properties:

**Issue:** Severity, Created At, Name, Category, Context, Status, Full Remediation, Targets, Link in All Issues, Link in Asset, Link in Scan, Link in Profile

**Profile:** Profile Name, Profile Scanner Kind

**Asset:** Asset Name, Asset URL, Asset Tags, Asset External URL, Asset Type, Asset Class

**Custom rule:** Custom Rule Name, Custom Rule Link

### Static Properties

Set a fixed value on every created work item (team, area path, iteration, and similar). Pick the Azure field, then set the value. Allowed values are loaded from the work item type field definition when Azure exposes them.

## Usage

### Creating Work Items From Workflows

When a **New Issue** workflow fires, Escape creates one work item per matching issue, then stores the work item id and HTML URL on the Escape ticket.

Creation skips **Ignored** and **False Positive** issues. An export with only Ignored or False Positive issues fails. Existing tickets are skipped, including tickets from other workflows. **Manual** can recreate a work item only when its ticket belongs to that workflow and Escape confirms it no longer exists in Azure DevOps.

### Creating Work Items Manually

1. Open an issue sidepanel.
2. Open the **Ticketing** tab.
3. Select a workflow whose export action uses Azure Boards.
4. Click **Create Ticket**.

The workflow's project, type, parent, and mappings are used.

## Bi-Directional Status Sync

### Azure Boards to Escape

No extra workflow is required.

Escape runs a built-in pull for each Azure Boards integration at least once per day (the scheduler also runs after you create or update the integration). Pull loads linked work items in batches and reads `System.State` plus the process template **state category**.

| Work item state category | Escape issue |
| --- | --- |
| `Completed` or `Resolved` | Set to **Resolved** if it was not already |
| Any other category | Set to **Open** if it was **Resolved** |

Pull only updates tickets whose workflow export is bound to that integration.

### Escape to Azure Boards

Use a workflow with trigger **Issue Updated** and an Azure Boards export.

| Action in Escape | Effect on the linked work item |
| --- | --- |
| Issue set to **Resolved** | `System.State` is set to the first state in category `Completed`, or `Resolved` if there is no `Completed` state |
| Issue set to **Open** | `System.State` is set to the first state in category `Proposed` |
| **Ignored**, **False positive**, **Accepted risk**, and similar | Manage the work item directly in Azure Boards. These statuses leave it unchanged; sync maps `OPEN` and `RESOLVED`. |

If the type has no matching category, Escape logs a warning and leaves the work item unchanged.

To close a work item after a finding disappears from a regular scan, either close it in Azure Boards (the next pull resolves the Escape issue) or mark the issue **Resolved** in Escape with an **Issue Updated** export configured. Regular scan resolution leaves the work item unchanged because it doesn’t fire **Issue Updated**.

## Related

- [Ticketing Integrations](<https://docs.escape.tech/documentation/automate/notifications-ticketing/index.md>)
- [Workflows](<https://docs.escape.tech/documentation/automate/workflows/index.md>)
- [Workflow Actions](<https://docs.escape.tech/documentation/automate/workflows/actions/index.md>)
- [Jira Integration](<https://docs.escape.tech/documentation/automate/notifications-ticketing/jira/index.md>)
- [Testing in Azure DevOps](<https://docs.escape.tech/documentation/automate/ci-cd/azure/index.md>) (CI scans, not Boards ticketing)
