Forums

Articles
Create
cancel
Showing results for 
Search instead for 
Did you mean: 

Replicating Impact Timings in JSM Incidents When Migrating from Opsgenie

Nat Sacks
I'm New Here
I'm New Here
Those new to the Atlassian Community have posted less than three times. Give them a warm welcome!
July 22, 2026

Hi Everyone

Should others be keen to replicate impact timings in incidents, here's how you can do it.  Upvote the feature request (https://jira.atlassian.com/browse/JSDCLOUD-18998), then follow the below guide.

:)


Issue

Opsgenie has impact durations and timings in incidents that no longer exist as an inbuilt feature in JSM incidents. These are invaluable live data points that we expect to be able to see after migrating to JSM.

Following discussions with Atlassian a feature request has been made for JSM and, they have provided a workaround which we have/will implement.

https://jira.atlassian.com/browse/JSDCLOUD-18998

Challenge

The workaround provides the impact timing fields and duration calculation in JSM incidents. It doesn’t preserve timings from Opsgenie incidents that you wish to migrate.

The below steps will allow you to export the impact timings from Opsgenie incidents, then after migrating to JSM, import them into the respective incidents.

Before Migrating from Opsgenie

Running the script below in PowerShell will do the following:

  • prompt to provide an Opsgenie API key (key must have "Read" & "Create and Update" access)

  • retrieve the following fields from every incident

    • tinyId

    • impactStartDate

    • impactDetectDate

    • impactEndDate

  • they will then be stored in opsgenie-impact-timings.json in the folder from where the script is run

$apiKey=Read-Host "Opsgenie API key"; $headers=@{Authorization="GenieKey $apiKey"; "Content-Type"="application/json"}; $base="https://api.opsgenie.com"; $limit=100; $offset=0; $rows=@(); do { $resp=Invoke-RestMethod -Method Get -Headers $headers -Uri "$base/v1/incidents?offset=$offset&limit=$limit&sort=createdAt&order=asc"; foreach($i in $resp.data){ $tag="tinyId:$($i.tinyId)"; $body=@{tags=@($tag); note="Added tinyId tag for future JSM mapping"} | ConvertTo-Json -Compress; $tagResp=Invoke-RestMethod -Method Post -Headers $headers -Uri "$base/v1/incidents/$($i.tinyId)/tags?identifierType=tiny" -Body $body; $rows += [pscustomobject]@{ tinyId=$i.tinyId; impactStartDate=$i.impactStartDate; impactDetectDate=$i.impactDetectDate; impactEndDate=$i.impactEndDate; addedTag=$tag; tagRequestId=$tagResp.requestId } }; $offset += $limit } while ($resp.data.Count -eq $limit); $rows | ConvertTo-Json -Depth 5 | Set-Content -Path ".\opsgenie-impact-timings.json" -Encoding UTF8; Write-Host "Exported $($rows.Count) incidents and submitted tag updates to .\opsgenie-impact-timings.json"

The script will also add the incident tinyId tag to each incident. This is a necessary step as the JSM migration sequentially imports the Opsgenie incidents into the new JSM space without correlating their issue numbers to the tinyId. Opsgenie tags are migrated as labels in JSM. This step allows us to create a unique identifier in JSM incidents relating to the Opsgenie incidents from where they came.

Importing Impact Timings into JSM

Dependencies

  • you have completed the steps in Before Migrating from Opsgenie 

  • the Opsgenie migration was completed successfully

  • in JSM you have a space where the the newly migrated incidents reside which you have full write access to

  • you have validated that the migrated incidents each have a label starting tinyId: followed by a number

  • you have run the work around to create the impact timing fields and duration automation, as documented in https://jira.atlassian.com/browse/JSDCLOUD-18998

  • you have a valid personal Atlassian API token - https://id.atlassian.com/manage-profile/security/api-tokens

Validate the Impact Timing Fields In JSM Before Running the Import Script

  • In JSM, create a new test incident and ensure that it contains unique timings for Impact Started At, Impact Ended At, and Impact Detected At respectively.

  • using Postman or curl, get the incident you added the unique impact timings to (you have to use the Jira API not the JSM Incident API so that you can see custom fields - https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-issues/#api-rest-api-3-issue-issueidorkey-get )

  • In the incident output, find the custom fields for impact timings from the unique impact times you added to the incident and make a note of the custom field names

Update the Custom Fields in the Script

Below is the script you will run later.

$JsmUrl=(Read-Host "JSM URL, e.g. https://your-domain.atlassian.net").TrimEnd('/');$ProjectKey=Read-Host "JSM space/project key";$Email=Read-Host "Atlassian email";$Token=Read-Host "Atlassian API token";$JsonPath=Read-Host "Path to opsgenie-impact-timings.json";$OutFile="jsm-impact-timing-update-log-$((Get-Date).ToString('yyyyMMdd-HHmmss')).csv";$Auth=[Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("$Email`:$Token"));$Headers=@{Authorization="Basic $Auth";Accept="application/json";"Content-Type"="application/json"};$Rows=Get-Content $JsonPath -Raw|ConvertFrom-Json;$Log=@();foreach($r in $Rows){$tag="tinyId:$($r.tinyId)";$jql="project = `"$ProjectKey`" AND labels = `"$tag`"";$searchBody=@{jql=$jql;maxResults=50;fields=@("labels","summary","customfield_10131","customfield_10133","customfield_10132")}|ConvertTo-Json -Depth 10;try{$s=Invoke-RestMethod -Method Post -Uri "$JsmUrl/rest/api/3/search/jql" -Headers $Headers -Body $searchBody -ErrorAction Stop;$matches=@($s.issues);if($matches.Count -eq 0){$Log+=[pscustomobject]@{tinyId=$r.tinyId;label=$tag;jql=$jql;issueKey="";action="NO_MATCH";status="No matching JSM issue found";updatedFields=""};continue};foreach($i in $matches){$tinyLabels=@($i.fields.labels|Where-Object{$_ -match '^tinyId:\d+$'});if($tinyLabels.Count -gt 1){$Log+=[pscustomobject]@{tinyId=$r.tinyId;label=$tag;jql=$jql;issueKey=$i.key;action="SKIPPED_CONFLICT";status="Issue has multiple tinyId labels: $($tinyLabels -join ',')";updatedFields=""};continue};$fields=@{};if($null -ne $r.impactStartDate){$fields.customfield_10131=$r.impactStartDate};if($null -ne $r.impactDetectDate){$fields.customfield_10133=$r.impactDetectDate};if($null -ne $r.impactEndDate){$fields.customfield_10132=$r.impactEndDate};if($fields.Count -eq 0){$Log+=[pscustomobject]@{tinyId=$r.tinyId;label=$tag;jql=$jql;issueKey=$i.key;action="NO_FIELDS";status="Match found but no non-null timing fields to update";updatedFields=""};continue};$updateBody=@{fields=$fields}|ConvertTo-Json -Depth 10;Invoke-RestMethod -Method Put -Uri "$JsmUrl/rest/api/3/issue/$($i.key)" -Headers $Headers -Body $updateBody -ErrorAction Stop|Out-Null;$Log+=[pscustomobject]@{tinyId=$r.tinyId;label=$tag;jql=$jql;issueKey=$i.key;action="UPDATED";status="Updated successfully";updatedFields=($fields.Keys -join ',')}}}catch{$Log+=[pscustomobject]@{tinyId=$r.tinyId;label=$tag;jql=$jql;issueKey="";action="ERROR";status=$_.Exception.Message;updatedFields=""}}};$Log|Export-Csv -NoTypeInformation -Path $OutFile;Write-Host "Done. Log written to $OutFile"

Carry out the remaining steps before running the script.

  • Using the incident you retrieved via API:

    • find the following phrase in the script {$fields.customfield_10131=$r.impactStartDate}

    • replace customfield_10131 with your Impact Started At custom field name

    • find the following phrase in the script {$fields.customfield_10133=$r.impactDetectDate}

    • replace customfield_10133 with your Impact Detected At custom field name

    • find the following phrase in the script {$fields.customfield_10132=$r.impactEndDate}

    • replace customfield_10132 with your Impact Ended At custom field name

Running The Update Script

  • In Windows, click Start > Terminal

  • Change to the Downloads folder (or wherever you have the opsgenie-impact-timings.json file (cd $HOME\Downloads)

  • Paste the script and press enter

    • When prompted, provide your JSM base URL 

    • When prompted, provide the space/project key 

    • When prompted, provide your Atlassian account email address and 

    • When prompted, provide your API key 

The script will then read your attached JSON structure, search JSM incidents by exact tinyId:<number> label, update the mapped custom fields, and write a CSV audit log (jsm-impact-timing-update-log-yyyymmdd-hhmmss.csv).
Your opsgenie-impact-timings.json contains tinyId, impactStartDate, impactDetectDate, impactEndDate, and addedTag values such as tinyId:1, which this uses directly.

Script Error Handling

  • In JSM, the “space key” is treated as the Jira project key in JQL

  • null timing values in the opsgenie-impact-timings.json are skipped instead of clearing fields in matching incidents

  • If a matching issue has labels like both tinyId:12 and tinyId:34, it does not update that issue and records SKIPPED_CONFLICT in the output log

  • If multiple JSM issues match the same exact label, it processes each one, while still applying the per-issue conflict rule.

1 comment

Comment

Log in or Sign up to comment
Dave Rosenlund _Trundl_
Community Champion
July 23, 2026

Interesting and informative first post, @Nat Sacks  Thanks for the contribution.

TAGS
AUG Leaders

Atlassian Community Events