06. 12. 2021 Mirko Morandini Service Management

JIRA: Importing Issues from OTRS/EriZone and Other Ticketing Systems

More and more companies are adopting the now “quasi-standard” JIRA Software issue tracking and software project management tool, and the emerging ticketing tool JIRA Service Management. For most of them, when transitioning from their previous system, it is essential to preserve the recent ticket history and to migrate open bugs and issues to the new application.

Here, I will present the three ways that Jira offers for importing ticket,s and describe pros and cons of each of them. Finally, I’ll introduce a script for migrating tickets from OTRS and its fork WürthPhoenix EriZone to Jira.


Let’s first try with the most obvious approach for automating an import to a cloud service (I will mostly refer to the Cloud version of JIRA here): the famous JIRA Rest API. Just start using one of the examples in the online documentation and you’ll get a quick win for creating new issues remotely, at least, once you’ve worked out how to obtain the “Account ID” of each user who should be a reporter, assignee or watcher of the issue. Back in 2019 Atlassian deprecated the use of user names and mail addresses in REST calls, claiming that this would be necessary in order to comply with the European GDPR. So now you need an additional call (rest/api/3/user/search?query=$username) to get the Account ID of each user.

However, after some trying and googling you’ll figure out that not every system field can be set by a REST call:

  • The creation date is always set to the import date and can’t be changed
  • The state can’t be set directly – you would need to send one REST request to trigger each state transition until you reach the state that you have to set
  • Also, each comment needs its very own REST call

You see, the REST API is intended for remote controlling JIRA. The lack of being able to set the creation date is a blocker for importing historical data, so we need to find another way to do this.

External System Import

The menu entry “External System Import” under Settings/System (needs site admin permissions) provides what we need. Jira here no longer offers specific tools to import from 3rd party software, except Atlassian-owned Trello. There are thus two ways to manually import historical data: CSV files and JSON.

Both choices allow you to import issues with a wide array of properties, from custom fields to comments with Markdown format (https://jira.atlassian.com/secure/WikiRendererHelpAction.jspa). However, they cannot be automated, and their performance is not exceptional but just enough for our purposes (I never measured the time but it would be around 100-200 issues per minute). Consider that, on the other hand, the Jira Cloud REST API is limited to more or less 1 request per second, and you would need to perform several requests per issue to add comments, change states, add attachments, etc.

CSV File Import

You just need a text file with a header row and comma (or whatever) separated values. The importer wizard leads you through the mapping of rows to the fields of an issue, and the mapping of values to the ones available. For example, the priority value “5 very high” in your legacy system should be mapped to “Highest” in Jira. The mapping configuration obtained can be saved to a file for reuse.

JSON Import

To use the JSON import, you need to start from a sample file available on Atlassian’s documentation pages. The format is easily readable and parsable. Unfortunately, beyond the sample files, Atlassian doesn’t publish any exhaustive definition of the semantics of the names and structure of the fields. Thus, you’ll end up working by trial and error, analyzing the import log to import fields that are not covered by the examples. I thought: well, this shouldn’t be a problem, the JSON format and the REST API for creating issues should be very similar. And it turns out to be true! The format is similar… but for whatever reason, it’s not exactly the same! E.g., while in a REST call, you can define the project key as a property of the issue, but in the JSON used for the manual import you need to define a list of projects, each with its list of issues.

Moreover, be aware that Jira requires strict JSON without any exceptions, so comments are not allowed and any excessive commas at the end of a list breaks the import. Sample JSON file:

   "projects" : [
      {	 "key" : "CISHSPT",
         "issues" : [
		"summary" : "Import of versions in Jira"
		"status" : "Ready to test",
		"issueType" : "Task",
		"labels" : [
		"affectedVersions" : [
                "fixedVersions" : [
		"description" : "Test with some *bold* and _italics_ \n",               
		"assignee" : "557058:33f24abcd",
		"created" : "2021-11-16T10:00:00.000+0100",
		"customFieldValues" : [
                     "fieldName" : "Area",
                     "fieldType" : "com.atlassian.jira.plugin.system.customfieldtypes:textfield",
                     "value" : "IT"
               "externalId" : "6377",
               "priority" : "Medium",
               "reporter" : "557058:33f2abcabc"             
        "  versions" : [
                 "name" : "4.19"
                 "name" : "4.21"

Setting the Affected and Fixed Version

The import of the version fields deserves its own paragraph. It’s a good example for the difficulties that you’ll encounter with the actual JIRA APIs.

In the REST call for creating an issue, versions are defined in the issue by the properties “versions” and “fixVersions” as a list of objects,

"fixVersions": [ { "name": "4.21" } ],

In the manual import as of summer 2021, these properties were called “AffectsVersion” and “FixVersion”, and are defined in a simple list. Now (in fall 2021) their names in the sample on the documentation page have been silently changed to “affectedVersions” and “fixedVersions”, which finally correspond to the name of these fields in the system.

"fixedVersions" : [ "4.21" ],

 And the version nightmare is not over yet: in contrast to other fields, versions are only accepted if they are also defined in their own section, for each project, regardless of whether they are already present in JIRA or not (in this case they will be created):

"versions" : [{"name" : "4.19"}, {"name" : "4.21"}]

So, Should You Use CSV or JSON for the Import?

If it’s relatively easy for you to export your data from your legacy system or from a DB to a single CSV file, then definitely try if the CSV importer gives the desired results. The mappings applied by the import wizard should be enough for most purposes. You need to switch to the JSON importer whenever you’re having problems with the representation of text fields and special characters in CSV files, and if the data you need to import cannot be flattened to a single table, e.g. if you need to add many comments to each issue, or multi-value fields. If you already need to use a script to prepare your data, and if you need to import thousands of issues, go for the JSON importer.

OTRS/EriZone Import Script

We’ve developed a script which reads ticket data directly from the Perl API of an OTRS/EriZone instance, performs the necessary property and value mappings defined in a configuration file, and then outputs a JSON file that is compatible with the JIRA importer. This tool works in two steps with an intermediary representation of the whole content, and can thus be easily adapted to different sources. It will soon be available on Bitbucket.

Mirko Morandini

Mirko Morandini

Mirko Morandini, PhD, is part of the EriZone team since 2015. As a consultant, he guided the implementation of EriZone in various projects in the DACH area and in Italy.


Mirko Morandini

Mirko Morandini, PhD, is part of the EriZone team since 2015. As a consultant, he guided the implementation of EriZone in various projects in the DACH area and in Italy.

Leave a Reply

Your email address will not be published. Required fields are marked *