How To Map and Sync Statuses and Correlation Details Between Azure DevOps and ServiceNow

Published: Feb 09, 2024 | Last updated: Feb 24, 2026

ServiceNow Azure DevOps integration
Table of Contents

In this blog, we are going to discuss a commonly asked Azure DevOps ServiceNow integration use case. The primary objective of this use case is to sync statuses and exchange correlation details between Azure DevOps and ServiceNow using a third-party integration tool. For this integration, I have used a tool called Exalate.

Here are the requirements and challenges:

The Use Case Requirements

When a user opens an incident on ServiceNow, the description, attachment, and status should be automatically synced over to the corresponding work item in Azure DevOps.

In addition to these primary requirements, we want to sync the following:

  • Map statuses bi-directionally between Azure DevOps and ServiceNow. For instance, “Active” is mapped to “In Progress”.
  • Sync these statuses bi-directionally between Azure DevOps and ServiceNow.
  • When a status is marked as “Closed” in Azure DevOps, a corresponding close code and close note is added in the ServiceNow instance and the status is changed to “Resolved”.
  • Display the Azure DevOps work item ID in the Correlation ID field in ServiceNow.

Potential Challenges

  • Avoiding errors when writing sync rules for the incoming and outgoing data.
  • Setting up the right triggers to update the fields on both sides automatically.
  • Mapping the correct fields and entities.
  • Fetching the correct work item ID and populating the ServiceNow Correlation ID field.
  • Handling possible network timeouts.

Why This Use Case Matters

Status mapping between Azure DevOps and ServiceNow is one of the most requested integration scenarios for teams running ITSM alongside DevOps workflows. Without it, support teams in ServiceNow have no visibility into development progress, and developers in Azure DevOps lack context about incident severity or resolution urgency. Automating this sync removes manual handoffs, reduces resolution time, and keeps both teams aligned in real time.

Solution to the Problem: Exalate

Exalate is a bi-directional integration solution that works with Jira, Jira Service Management, ServiceNow, Azure DevOps Cloud, Azure DevOps Server, Salesforce, Zendesk, Freshservice, Freshdesk, Asana, GitHub, and custom connectors.

It has a Groovy scripting engine that allows developers and scripting enthusiasts to write sync rules for each connection. You also get access to Aida, the AI-assisted configuration feature, which can generate sync scripts from plain language prompts, saving you time if you are not comfortable with Groovy.

How to Set Up Exalate for Automatic Data Syncs

To get started, go to the Exalate app at exalate.app and log in or create an account. New users can sign up using their email or Google account.

Configuration Options

After creating your connection, you have two configuration options: “Quick Sync” and “Edit & Test”.

Quick Sync applies a default set of sync rules so you can start syncing right away with common field mappings in place.

Edit & Test lets you customize the sync rules using the script editor. This is the option you want for the status mapping use case described here.

Edit & Test: Open Draft Editor

To start making changes to your sync configuration, click “Create a new version” or select “Open latest draft”. This ensures you do not accidentally modify the existing configuration. Changes in the draft are saved automatically.

Click the “Edit” button to open the editor and modify the sync rules.

Understanding Sync Rules

The scripts are divided into incoming and outgoing scripts:

  • Outgoing script: If the sync direction is from ServiceNow to Azure DevOps, the outgoing script will hold the values passed from ServiceNow to Azure DevOps.
  • Incoming script: The incoming script defines how the values coming from ServiceNow are mapped in Azure DevOps.

These scripts will be reversed if the direction changes.

Configuring Status Mapping Rules

Under the “Rules” tab, enter the following code snippet into the “Outgoing sync” text area on the ServiceNow side.

if(entity.tableName == "incident") {
    replica.key            = entity.key
    replica.summary        = entity.short_description
    replica.description    = entity.description
    replica.attachments    = entity.attachments
    replica.comments       = entity.comments
    replica.state          = entity.state
    replica.entityType = "incident"
}Code language: JavaScript (javascript)

Note: The expression above establishes the mappings for every ServiceNow entity type. For this use case, we sync an “incident” within the ServiceNow environment. You can add additional ServiceNow entities in the Outgoing sync. The sync rules in the console allow you to sync statuses, comments, attachments, descriptions, keys, and short descriptions.

Scroll down to the incoming sync and enter the following code:

if(firstSync){

    if (replica.type.name == "Task")
        entity.tableName = "incident"
    syncHelper.syncBackAfterProcessing()
}

if(entity.tableName == "incident") {

    entity.short_description = replica.summary
    entity.description = replica.description
    entity.attachments += replica.addedAttachments
    entity.comments += replica.addedComments

    def statusMapping = ["Active":"In Progress", "Closed":"Resolved"]
    def remoteStatusName = replica.status.name
    if (remoteStatusName == "Closed"){
        entity.close_code = "Known Error"
        entity.close_notes = "Closed by Azure DevOps"
    }

    entity.state = statusMapping[remoteStatusName] ?: remoteStatusName
    entity.correlation_id = replica.key
}

if(entity.tableName == "cmdb_ci_business_app") {
    entity.short_description = replica.summary
    entity.description = replica.description
}Code language: JavaScript (javascript)

Note: The code snippet above establishes the status mappings and the Correlation ID details. You can also display the remote entity URL in the Correlation Display field. In ServiceNow, close notes and close code are mandatory fields. So you need to add them when the work item status on Azure DevOps is closed.

Testing Before Publishing

Once your sync scripts are ready, use the Test Run feature to validate them before going live. Select the work items you want to test against, click “Start Test Run”, and review the incoming and outgoing replicas for each item. This lets you preview how the synced items will look and catch any errors before they affect production data.

Once done, click “Publish” to save the changes.

On the Azure DevOps side, enter the code in the “Incoming sync” text area.

if(firstSync){
   // Set type name from source entity, if not found set a default
   workItem.projectKey  =  "Test Project"
   if (replica.entityType == "incident")
        workItem.typeName = "Task";
    syncHelper.syncBackAfterProcessing()
}

workItem.summary      = replica.summary
workItem.description  = replica.description
workItem.attachments  = attachmentHelper.mergeAttachments(workItem, replica)
workItem.comments     = commentHelper.mergeComments(workItem, replica)
workItem.labels       = replica.labels
workItem.priority     = replica.priority

def statusMapping = ["In Progress":"Doing", "New":"To Do", "Resolved":"Done"]
def remoteStatusName = replica.state
workItem.setStatus(statusMapping[remoteStatusName])Code language: JavaScript (javascript)

The code snippet defines the mapping rules for states and statuses. So if the incident is “In Progress,” it will appear as “Doing” in the corresponding work item. “New” becomes “To Do,” and “Resolved” becomes “Done”.

Scroll down to the outgoing sync field and enter the following code:

replica.key            = workItem.key
replica.assignee       = workItem.assignee
replica.summary        = workItem.summary
replica.description    = nodeHelper.stripHtml(workItem.description)
replica.type           = workItem.type
replica.status         = workItem.status
replica.labels         = workItem.labels
replica.priority       = workItem.priority
replica.comments       = nodeHelper.stripHtmlFromComments(workItem.comments)
replica.attachments    = workItem.attachments
replica.project        = workItem.project
replica.areaPath       = workItem.areaPath
replica.iterationPath  = workItem.iterationPath

Note: The code snippet above sends work item-related information (summary, assignee, etc.) to the other side (ServiceNow).

Once done, click “Publish” to save the changes.

You have now set rules for syncing data between Azure DevOps and ServiceNow. You can adjust the rules according to the demands of specific projects and work items.

How It Works in Practice

When you sync an incident and a work item, the work item ID gets reflected in the Correlation ID field in ServiceNow. Enter the description and add a comment to the incident.

Go over to the Azure DevOps side. You will see that the same comment has come over, as well as the description. Also, since the incident’s state is “New”, the task status will reflect “To Do” as well.

Next, upload an attachment and respond to the comment. Then change the incident state to “In Progress” and then to “Resolved”.

Back on Azure DevOps, you can review the task history to see all the changes that have taken place on the incident.

And that is all you need to get this use case working.

Common Status Mapping Scenarios

Here are a few additional status mapping patterns you can adapt for your own workflows:

ServiceNow Incident StateAzure DevOps Work Item Status
NewTo Do
In ProgressDoing / Active
On HoldBlocked
ResolvedDone
ClosedClosed

You can customize these mappings in the statusMapping variable within your sync scripts. If your Azure DevOps project uses a custom process template with different statuses, just update the mapping values to match.

Conclusion

Exalate allows you to sync data between ServiceNow incidents and Azure DevOps work items with full control over field mappings, status transitions, and correlation details. You can specify the rules according to each use case, test them safely with Test Run before publishing, and use Aida to generate scripts faster. If you still have questions or want to see how Exalate fits your specific use case, book a demo with one of our experts.

Recommended Reading:

Subscribe to the Newsletter

Join +5.000 companies and get monthly integration content straight into your inbox

Shopping Basket