Jira and Azure DevOps Integration

    Most software organizations end up with Jira and Azure DevOps running side by side. Product and support teams gravitate toward Jira for backlog management, customer tickets, and roadmap planning, while engineers stay in Azure DevOps for pipelines, repos, and the rest of the Microsoft toolchain. Both tools earn their place, but the wall between them is where productivity quietly leaks out.

    A Jira Azure DevOps integration knocks that wall down. Instead of devs copying ticket details into Azure Boards or PMs pinging engineering for status updates, work items, comments, attachments, and state changes flow between the two systems automatically.

    Exalate is built for bidirectional sync between Jira (Cloud, Server, Service Management, Software, Product Discovery, Work Management) and Azure DevOps (Cloud and Server), runs on-premise or in Docker if you need it to, and gives each side full control over what data leaves and how incoming data is applied.

    Exalate Ramp-up and Configuration Steps

    Here's a quick walkthrough of how to wire up an integration between Azure DevOps and Jira.

    Create an Account or Log In to Existing Account

    1. Navigate to the Exalate app.
    2. You can sign up using Google (SSO) with a company email or create your own account.
    3. Click Create an account to submit your information (business email address, first name, last name, strong password).
    4. Confirm your password and click on Create an account to proceed.
    5. Verify Your Email: Check your email inbox for a verification message from New Exalate. Note: The verification link expires after 2 hours.
    6. Click the verification link in the email. You'll be redirected to complete your account setup.
    7. Log in to New Exalate with your email and password. 

    Create a Connection Between Jira and Azure DevOps

    1. Log in to your account.
    2. Click Add Connections > Create New Connection.
    3. The connection creation wizard opens, guiding you through a step-by-step process.
    4. To connect System A (Jira):
    5. Enter the system URL [https://example.atlassian.net]
      1. A console status check runs automatically.
      2. If the system is already part of your workspace, you'll see a confirmation message and can skip authentication.
      3. If the system is registered but in a different workspace, you'll see: "System registered, but not yet part of Workspace."
      4. If the system is new, authentication fields appear automatically.
    6. To authenticate System A (Jira):
      1. Go through Jira Cloud OAuth authentication.
      2. Click Check Authentication and wait for validation. If you have multiple Jira sites, choose the one you want to use for this connection. Once successful, the Next button becomes active.
    7. Click Next to proceed to System B. To connect System B (Azure DevOps), follow the same steps as System A:
      1. Enter the system URL for your Azure DevOps organization
      2. Wait for automatic system type detection.
      3. Provide authentication credentials (a Personal Access Token (PAT) with read/write permissions for work items).
      4. Click Check Authentication to verify.
      5. Click Next to continue.
    8. Name your connection using a unique, descriptive name. E.g., "Jira-ADO-DevTeam".
      If the name already exists, you'll see an error message prompting you to choose a different name.
    9. Add a brief description to help identify the connection's purpose, such as "Sync development work items between Jira and Azure DevOps."
    10. Click Next to review your configuration.
    11. Review the details of your connection. Confirm the connection name and description.
    12. Click Create Connection to begin the setup process.
    13. New Exalate automatically registers your systems and establishes the connection. You'll see real-time updates as the process completes.
    14. When the process completes, you'll see a success message, and your connection status will change to "Ready to configure."
    15. Once your connection is created, choose which projects to sync between your systems.

    Note: If the concept of a project does not exist in the given system, this modal will not be shown.

    Configure Your Bidirectional Jira to Azure DevOps Connection

    You've got two paths from here: Quick Sync or Edit & Test.

    Quick Sync is the fastest way to push a single work item across and confirm the connection actually works.

    1. Under the "Item sync monitor," enter the work item key and click on the "Sync Now" option.
    2. To link 2 existing items, click "Link with existing".

    After the sync runs, both work items open in a new window so you can compare them side by side.

    For anything beyond a one-off sync, use the Edit & Test Sync option.

    1. Navigate to your connection in the Connections list.
    2. Click on the connection name or the Edit button to open the configuration page.
    3. Once on the connection configuration page, you'll see the current sync rules.
    4. To make changes, create a new version or select Open latest draft. This keeps your live configuration safe while you experiment.

    5. Click the Edit button to open the editor:
      1. Edit sync rules using Aida (the outgoing script holds the values leaving Jira for Azure DevOps, and the incoming script defines how values arriving from Azure DevOps land in Jira).
      2. Click Save Script to save the version or Start Test Run to test your configuration.
      3. Click Publish Version if you want to activate the configuration.
    6. Hit Switch Direction to set up the rules for the reverse flow (for example, if you want to write the incoming script for Jira and the outgoing script for Azure DevOps). This will create a new version (or draft) for that direction, which also needs to be reviewed and published.
    7. All configuration versions for a connection are available under the Version dropdown below the connection name.
    8. Versions have the following statuses:
      • Active: The currently published configuration.
      • Draft: An editable copy of the Active version.
      • Archived: When a new version is published, the previous Active version is archived. Restore an archived version by selecting Restore version.

    AI-Assisted Configuration with Aida

    1. Navigate to your connection.
    2. Click Add new version (or open the latest draft version).
    3. Click Edit to enter the script editor.
    4. Type your request into the Aida input field in plain English.
    5. Click the send button (or press Enter).
    6. Aida will start drafting the script.
    7. Look over the suggestions. Green lines are additions, red lines are removals.
    8. Click Insert to accept or Discard to reject.
      • For Outgoing scripts: Spell out what data should leave your system. For example, "Exclude attachments".
      • For Incoming scripts: Spell out how data arriving from the other side should be handled. For example, "Set a default assignee if the user can't be found."

    Note: While Aida is helpful, always review the generated code before applying it to production.

    Test Run: Validate Before Production

    When the scripts are ready, click "Start Test Run" to see how they actually behave.

    1. Pick the work items you want to test against (multiple is fine), then click "Start Test Run" to preview the result.
    2. Walk through the incoming and outgoing replicas for each item to confirm that field mappings look right. Anything off? Tweak the scripts and run them again.
    3. Once you're confident, click "Publish Version" to push the configuration live.

    Automate Jira Azure DevOps Integration Using Triggers

    Triggers are the conditions that decide which work items get picked up for sync; no manual nudging required.

    1. Click "+ Add trigger" to create a new trigger.
    2. Add trigger conditions with the query language native to each platform:
      1. Jira Query Language (JQL): project = DEV AND priority in (High, Highest).
      2. Azure DevOps Work Item Query Language (WIQL): [System.WorkItemType] = 'Bug' AND [System.State] = 'New'
    3. Toggle the trigger on to activate it. Save the changes by publishing.

    Troubleshoot with Aida

    1. Navigate to the “Troubleshooting” tab in your workspace.
    2. Hover over any error and click the Aida icon for immediate analysis. Aida shows affected systems, connections, and work items, plus a brief explanation of the error.
    3. For deeper investigation, click “Error Details” to view the impact level, stack trace, error type, and occurrence date.
      Aida diagnosis interface with error details
    4. Use “View Full Analysis” for complete context. Once you’ve resolved the issue, click “Resolve” to clear the error.

    Your integration is now active. Synchronization runs automatically based on your configured sync rules and triggers.

    Advanced Jira and Azure DevOps Integration Use Cases (Using Aida)

    The scripting engine in the configuration panel is what makes AI-powered Jira to Azure DevOps integration possible in Exalate.

    This engine comes with Aida embedded, an AI assistant that converts your natural language prompts to script. Exalate also ships with Script Helpers, so you don't have to write every connection from a blank file.

    Here are a handful of common use cases.

    Use Case 1: Map and Sync Statuses between Jira and Azure DevOps

    Jira and Azure DevOps don't speak the same language when it comes to workflow status. Jira has To Do, In Progress, and Done. Azure DevOps has New, Active, and Closed. To keep them in lockstep, you need a mapping rule.

    A typical setup: Jira's To Do becomes Azure DevOps' New, In Progress becomes Active, and Done becomes Closed.

    You can write the mapping yourself or hand the requirement to Aida and let it generate the Groovy script.

    A prompt for Aida might look like this:

    "I want to map the statuses of a Jira work item and an Azure DevOps work item so that when the Jira work item is "To Do", the Azure DevOps state will be "New", when the Jira work item status is "In Progress", the Azure DevOps state will be "Active", and when the Jira work item is marked "Done", the Azure DevOps state will be "Closed". This should be on the incoming side of the Azure DevOps connection."

    Read through what Aida produces and refine the prompt until the output matches what you actually want.

    def stateMapping = ["To Do" : "New","In Progress" : "Active","Done" : "Closed"]def remoteStatusName = replica.status.nameworkItem.state = stateMapping[remoteStatusName] ?: "New"

    Use Case 2: Sync Text, Dropdown, and Date Custom Fields

    Out-of-the-box fields rarely cover everything a team tracks. Custom fields fill in the gaps, whether that's a technical description, a categorization, or a milestone date. Syncing them keeps both sides looking at the same data.

    Text fields are usually the simplest: a free-form value passed straight across.

    // Jira outgoing sync

    replica.customFields."CF Name" = issue.customFields."CF Name"

    // Azure DevOps incoming sync

    workItem.customFields."CF Name".value = replica.customFields."CF Name".value

    Dropdown (select list) fields carry an option object rather than a plain string. The trick is the extra .value on the receiving side to pull out the selected option:

    // Jira outgoing sync

    replica.customFields."CF Name" = issue.customFields."CF Name"

    // Azure DevOps incoming sync

    workItem.customFields."CF Name".value = replica.customFields."CF Name".value.value

    Date fields keep deadlines and milestones aligned. A small format conversion gets the value into Azure DevOps' expected shape:

    // Jira outgoing sync

    replica.customFields."CF Name" = issue.customFields."CF Name"

    // Azure DevOps incoming sync

    import java.text.SimpleDateFormatdef sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss")def targetDate = sdf.format(new Date())workItem."Microsoft.VSTS.Scheduling.StartDate" = targetDate

    One thing to watch is the compatibility of field types. A text field on one side should map to a text field on the other, and dropdown options should match between platforms, or you'll lose values silently.

    Use Case 3: Maintain Work Item Links, Relations, and Sub-task Hierarchies

    Linked work items only deliver value if the links survive the sync. A Jira Story with attached Tasks and Bugs needs to land in Azure DevOps with all those relationships intact, and the same applies to sub-tasks under their parent Tasks.

    The typical mapping: a "blocks" relationship in Jira shows up as "predecessor" in Azure DevOps, "relates to" becomes "related", and Jira sub-tasks slot in as Tasks under the matching Azure DevOps work item.

    The Jira outgoing script just needs to ship out the links and the parent ID:

    replica.linkedIssues = issue.issueLinksreplica.parentId = issue.parentId

    On the Azure DevOps incoming side, set up the parent-child relationship first:

    workItem.parentId = nullif (replica.parentId) {def localParent = syncHelper.getLocalIssueKeyFromRemoteId(replica.parentId.toLong())if (localParent)workItem.parentId = localParent.id}

    Then translate the link types using a linkTypeMapping and patch them onto the work item:

    def linkTypeMapping = ["blocks": "System.LinkTypes.Dependency-Reverse","relates to": "System.LinkTypes.Related"]

    Adjust the mapping to match the link types your team actually uses. For the full incoming script (which uses httpClient to PATCH the relations endpoint), see the linked work items guide.

    Use Case 4: Sync Jira Priority to an Azure DevOps Picklist Custom Field

    Sometimes the native Azure DevOps priority field isn't where you want Jira priority to land. Maybe you've built reporting around a custom picklist, or you want different teams to see priority through different lenses. Either way, this sync sends the Jira priority value into a custom picklist field on the Azure DevOps side.

    A sample prompt:

    "Map the Jira work item priority to a custom picklist field called 'MindState' in Azure DevOps. Map Highest to Angry, High to Not OK, Medium to OK, Low to Happy, and Lowest to Delighted."

    Aida's output for the Azure DevOps incoming side:

    def priorityMapping = ["Highest" : "Angry","High" : "Not OK","Medium" : "OK","Low" : "Happy","Lowest" : "Delighted"]def remotePriority = replica.priority.namepriorityName = priorityMapping[remotePriority] ?: remotePriorityworkItem."MindState" = priorityName

    Discard, accept, or refine the prompt until the script does what you need.

    Use Case 5: Escalate Customer Bugs from Jira Service Management to Azure DevOps

    This is the classic "support says it's broken, devs need to fix it" scenario. Support runs in Jira Service Management, while engineering runs in Azure DevOps. Without a sync, those bug reports either rot in email or get retyped by hand, losing screenshots, customer details, and urgency along the way.

    An Exalate sync routes high-priority Jira Service Management tickets straight into Azure DevOps as Bugs, complete with descriptions, attachments, customer impact notes, and priority. When a developer updates the Bug, drops a comment, or commits a fix, the Jira ticket reflects it almost instantly.

    A simple priority mapping on the Azure DevOps incoming side might look like this:

    def priorityMapping = ["Highest": "1","High": "2","Medium": "3","Low": "4"]def mappedPriority = priorityMapping[replica.priority?.name]if (mappedPriority) {workItem.customFields."Priority".value = mappedPriority}

    For a SaaS team handling 200+ tickets a day, this means customer-flagged Bugs hit the development backlog within seconds, and resolution details flow back to support so they can update affected customers without bothering the engineers.

    Use Case 6: Multi-Instance MSP Operations

    MSPs deal with the inverse problem at scale: every client has their own Jira instance, but the MSP runs a single Azure DevOps organization for internal development. Jumping between dozens of Jira instances every day to triage and copy work over is a non-starter.

    Exalate fans out connections so multiple client Jira instances can feed into one Azure DevOps organization. Tickets route to the right Azure DevOps projects based on tags, area paths, or whatever client identifier you use, and each client's data stays walled off from the others.

    A 25-person dev team supporting 40 enterprise clients can see all client work in one Azure DevOps view, sorted by SLA tier. When a fix or deployment goes out, the matching client's Jira instance gets updated automatically, which keeps client-specific reporting accurate.

    Routing rules can key off client identifiers, custom fields, or tags. Each connection is independent, so there's no risk of one client's data bleeding into another's.

    If you'd like to walk through a specific use case with our team, book a demo.

    Note: The code snippets might not work precisely as intended due to changes to the environment or other reasons. If you encounter any problems, contact us for clarification.

    Supported Jira and Azure DevOps Entities

    You can sync several work item entities or issues between Jira and Azure DevOps. Check out the comprehensive list of supported Azure DevOps entities.

    Check out the comprehensive list of supported Jira Cloud and On-premise entities.

    This is a sample mapping between Azure DevOps work items and Jira issues:


    Azure DevOps work item <> Jira work item

    • title ↔ summary
    • description ↔ description
    • priority ↔ priority
    • state ↔ status
    • assignee ↔ assignee
    • comments ↔ comments
    • attachments ↔ attachments
    • tags ↔ labels
    • area path ↔ component (or custom field)
    • iteration path ↔ sprint (or custom field)
    • custom fields ↔ custom fields
    • parent-child relationships ↔ work item links
    • any field available via REST APIs

    Other resources 

    • Start a free trial with Exalate, or book a call with our integration engineers to talk through your use case.

    • Still on Exalate Classic? Its documentation lives here. There's also a write-up on the differences between Exalate Classic and New Exalate.

    • For security details, head to our Trust Center.

    • If you’re stuck on a configuration, the Exalate Community is where the answers usually live.

    • Tune into our Webinar series, The Sync Room, for integration deep-dives, AI trends, and answers to common pain points.