페이지 트리
메타 데이터의 끝으로 건너뛰기
메타 데이터의 시작으로 이동

Available:

JIRA 4.2 and later

JIRA REST API 개요

JIRA's REST API is for anyone who wants to interact with JIRA in a programmatic fashion. This could be developers who want to integrate their software or other Atlassian applications with JIRA, system administrators who want to automate a JIRA feature or process, or developers who want to write gadgets or mashups for JIRA.

The goal is to make JIRA's REST API a superset of everything one can currently achieve with SOAP and XML-RPC, while gradually adding the rich functionality desired by JIRA developers. SOAP and XML-RPC are not going away anytime soon. However, our goal is to eventually make REST the "Remote API of Choice", when working with JIRA.

This document does not explain everything that can be done with REST. You should always refer to the canonical JIRA REST API documentation for full details on what resources are available, what HTTP methods they support and what the content of requests and responses will be.

JIRA REST API 소개

JIRA's REST API provides access to a number of resources that are accessible via normal URLs. JIRA's response format is JSON. Because REST is built off the same technologies as the web itself, you generally do not need complicated libraries to use it. In fact, you can start exploring JIRAs REST API simply through your web browser.

Why only provide JSON responses and not XML?


Just like everyone else in the real world, we're faced with time and resource constraints. Supporting two serialisation formats requires more time than just a single one. Hence, for our initial release of the JIRA REST API, we decided to provide "more stuff in JSON" rather than "less stuff in JSON and XML".

JIRA's REST API is Evolving

JIRA's REST API covers a handful of functions that return specific details about JIRA issues, users and other JIRA configurations. While full APIs have permanence and stability, we cannot promise this of JIRA's early REST APIs, until we incorporate sufficient feedback from the JIRA development community, after which we can produce a comprehensive and useful API.

While we do not wish to make significant changes to JIRA's REST API 'points', we want to incorporate feedback from the community as early as possible to make a better, stronger and more useful method for interacting with JIRA. Consequently, there is a possibility that some of these points (or their behaviour) might change in subsequent versions.

Throughout this document we'll highlight some of the areas which are still being fine tuned. If you have feedback or suggestions for JIRA's REST API, please submit them through our public JIRA site. Marking them with a component of "Remote API (REST)" is the fastest way to bring them to the attention of JIRA's developers and product managers.

Focus of the Initial JIRA REST API

Since an Issue is the heart of JIRA, this was the focus of our initial JIRA REST API. A JIRA issue itself provides access to a lot of information about a JIRA installation, such as details on users, groups, security levels, worklogs, voting, watching, workflow transitions and so on.

You can access the following details associated with an issue using JIRA's REST API:

  • Issue links (incoming and outgoing)
  • Timetracking information (original estimate, remaining estimate, and time spent)
  • The parent task or subtask of an issue
  • Who is watching an issue or has voted on it
  • The worklog for an issue
  • What workflow transitions are valid for the issue's current status

JIRA REST API Implementation

This section provides some background information about JIRA's REST API:

URI 구조

The format of all REST URIs in JIRA is:

http://hostname/rest/<api-name>/<api-version>/<resource-name>

JIRA's REST API is provided by a plugin that is anchored under the URI path component /rest/. Hence, if your JIRA site is running at:

http://example.com/jira

Then the anchor point for REST will be:

http://example.com/jira/rest

The <api-name> part of the URI is the name of the JIRA REST API, which is simply api. The names of other APIs in JIRA include internal, gadget and auth. With the exception of auth (see User Authentication below for more information), these are intended primarily for internal use within JIRA and not for external consumption.

Each version of a REST API is indicated by the <api-version> part of the URI. Since the JIRA REST API is likely to evolve, we hope to provide as much backward compatibility as possible.

About JIRA REST API versions:


The current version of the JIRA REST API is "2.0.alpha1", which, as the name indicates, is currently in alpha. This is the first true JIRA REST API for external consumption because version "1.0" of the JIRA REST API (released with JIRA 4.0) was intended for internal use and was not widely publicised or documented.

Once we've received enough feedback from the community about this API, we'll move JIRA's REST API out of alpha and declare version "2.0" final and 'frozen in time'. Future versions of the JIRA REST API would be significantly different and incompatible with earlier JIRA REST API versions. Consequently, they would be designated a different api-version, such a "3.0". The shortcut api-version of "latest" will give you the current version, which is "2.0".

The final part of the URI is the <resource-name>. This is the actual REST API "resource" itself that determines what response you will receive. A REST resource is analogous to an object in OO programming or a database row in a database system. JIRA's REST API resources have names like "issue", "user" or "attachment".

Different resources may expect additional path parameters, often to identify an individual resource. For instance, putting all of the above together, the URI to an issue with the key MKY-1 would look like:

http://hostname/rest/api/2.0.alpha1/issue/MKY-1

사용자 인증

JIRA's REST API is protected by the same restrictions which are provided via JIRAs standard web interface. This means that if you do not log in, you are accessing JIRA anonymously. Furthermore, if you log in and do not have permission to view something in JIRA, you will not be able to view it using the JIRA REST API either.

In most cases, the first step in using the JIRA REST API is to authenticate a user account with your JIRA site.

로그인

At the moment there are two ways to authenticate via REST:

  • HTTP BASIC Authorisation
  • HTTP Cookies

BASIC Authorisation is often simpler to use. However, your username and password are sent as headers in every request you make. This means the use of HTTPS is almost always mandatory when using BASIC Authorisation. If you are running on a trusted intranet site and understand and accept the risks associated with user credentials being sent in headers, then standard (unsecured) HTTP may be acceptable.

If you decide to use HTTP Cookies, you need to send the correct cookie header along with every request. Depending on the tools and libraries you use, this may vary in difficulty. The first step is to actually get a cookie from JIRA, which is done via the JIRA "auth" API, which is accessible via the URI anchor point of the JIRA REST API:

http://hostname/rest/auth/

The only "auth" resource available is "session", so you will be interacting with:

http://hostname/rest/auth/latest/session

To log in to JIRA, you need to POST a username and password in JSON format. Here is how you would do this with cURL. (using context path "/jira")

curl -H "Content-Type: application/json" -d '{"username" : "admin", "password" : "admin"}' http://localhost:8090/jira/rest/auth/latest/session

cURL is a useful tool which allows you to call and pass parameters to URLs directly from the command line. For simplicity, the remaining JIRA REST API calls used throughout this document make use of this command line tool.

You will receive a JSON response that looks similar to:

{"session": {
"name":"JSESSIONID",
"value":"3BCEFC7E6EC901DADA2A90CA043BEFB6"},
"loginInfo":{
"loginCount":9,
"previousLoginTime":"2010-07-09T11:25:46.337+1000"
}}

For our purposes, what we care about is the session name and value, which tells us the name of the cookie to send to JIRA and the value to use.

로그아웃

Logging out is pretty simple, just do an HTTP DELETE on /rest/auth/latest/session. (using context path "/jira").

curl -c cookie_jar -X DELETE http://localhost:8090/jira/rest/auth/latest/session

cookie_jar is the name of a file that cURL uses to store the cookies its receives from URLs.

쿠키 만료

One downside of cookies (as opposed to BASIC Authorisation) is that they expire. You have probably noticed this when accessing JIRA through a web browser. Every once in a while, especially if you have not used JIRA in a while, you need to log in again because your cookie has expired. The same phenomenon occurs when using REST. If you are writing a script or code which involves REST API calls and:

  • Only runs for a few minutes, then you should not have to worry about cookies expiring.
  • Runs for a longer period of time due to more complex integration activities, then expiring cookies may cause problems.

If you use REST with a cookie that has expired, you will receive a 401 error response from JIRA. The response body will contain a message telling you that your cookie is invalid. At that point, you will need to re-authenticate to the session resource on the "auth" API.

This may change:


If a cookie has expired, you will receive an error message in text/html, which is not helpful when you expect an application/json Internet media type. We would like to make these responses more obvious in future.

CAPTCHAs

CAPTCHA upon login was a security feature incorporated into JIRA 4.1. This feature is 'triggered' after several consecutive failed log in attempts, after which the user is required to interpret a distorted picture of a word and type that word into a text field with each subsequent log in attempt.

Be aware that you cannot use JIRA's REST API to authenticate with a JIRA site, once JIRA's CAPTCHA upon login feature has been triggered.

When you get an error response from JIRA, you can check for the presence of an X-Seraph-LoginReason header in the response, which will contain more information. A value of AUTHENTICATION_DENIED means the application rejected the login without even checking the password, which most commonly indicates that JIRA's CAPTCHA feature has been triggered.

This may change:


We would like to improve REST API responses from JIRA where the CAPTCHA upon login feature has been triggered. Examining headers is fairly common in HTTP, but we believe it would be better to generate some useful JSON too.

JIRA REST API 응답

This section demonstrates how to use some of the key features of this Alpha release of the JIRA REST API.

We are using cURL in this section to make JIRA REST API calls with user authentication (above) and each call is followed by a typical JSON response.

간단한 이슈 응답

In the following example, BASIC Authorisation is used to retrieve an issue's content. The following call (using context path "/jira"). :

curl -u admin:admin http://localhost:8090/jira/rest/api/2.0.alpha1/issue/MKY-1

Would generate this standard response:

{ "expand" : "html",
"fields" : { "assignee" : { "name" : "assignee",
"type" : "com.opensymphony.user.User",
"value" : { "displayName" : "admin",
"name" : "admin",
"self" : "http://localhost:8090/jira/rest/api/2.0.alpha1/user/admin"
}
},
"attachment" : { "name" : "attachment",
"type" : "attachment",
"value" : [ ]
},
"comment" : { "name" : "comment",
"type" : "com.atlassian.jira.issue.fields.CommentSystemField",
"value" : [ ]
},
"components" : { "name" : "components",
"type" : "com.atlassian.jira.bc.project.component.ProjectComponent",
"value" : [ ]
},
"created" : { "name" : "created",
"type" : "java.util.Date",
"value" : "2010-09-20T15:35:41.173+1000"
},
"description" : { "name" : "description",
"type" : "java.lang.String"
},
"environment" : { "name" : "environment",
"type" : "java.lang.String"
},
"fixVersions" : { "name" : "fixVersions",
"type" : "com.atlassian.jira.project.version.Version",
"value" : [ ]
},
"issuetype" : { "name" : "issuetype",
"type" : "com.atlassian.jira.issue.issuetype.IssueType",
"value" : { "name" : "Bug",
"self" : "http://localhost:8090/jira/rest/api/2.0.alpha1/issueType/1",
"subtask" : false
}
},
"labels" : { "name" : "labels",
"type" : "com.atlassian.jira.issue.label.Label",
"value" : [ ]
},
"links" : { "name" : "links",
"type" : "issuelinks",
"value" : [ ]
},
"priority" : { "name" : "priority",
"type" : "com.atlassian.jira.issue.priority.Priority",
"value" : { "name" : "Major",
"self" : "http://localhost:8090/jira/rest/api/2.0.alpha1/priority/3"
}
},
"project" : { "name" : "project",
"type" : "com.atlassian.jira.project.Project",
"value" : { "key" : "MKY",
"self" : "http://localhost:8090/jira/rest/api/2.0.alpha1/project/MKY"
}
},
"reporter" : { "name" : "reporter",
"type" : "com.opensymphony.user.User",
"value" : { "displayName" : "admin",
"name" : "admin",
"self" : "http://localhost:8090/jira/rest/api/2.0.alpha1/user/admin"
}
},
"security" : { "name" : "security",
"type" : "com.atlassian.jira.issue.security.IssueSecurityLevel"
},
"status" : { "name" : "status",
"type" : "com.atlassian.jira.issue.status.Status",
"value" : { "name" : "Open",
"self" : "http://localhost:8090/jira/rest/api/2.0.alpha1/status/1"
}
},
"sub-tasks" : { "name" : "sub-tasks",
"type" : "issuelinks",
"value" : [ ]
},
"summary" : { "name" : "summary",
"type" : "java.lang.String",
"value" : "Sed ultricies, leo at adipiscing fringilla."
},
"timetracking" : { "name" : "timetracking",
"type" : "com.atlassian.jira.issue.fields.TimeTrackingSystemField"
},
"updated" : { "name" : "updated",
"type" : "java.util.Date",
"value" : "2010-09-20T15:35:41.173+1000"
},
"versions" : { "name" : "versions",
"type" : "com.atlassian.jira.project.version.Version",
"value" : [ ]
},
"votes" : { "name" : "votes",
"type" : "com.atlassian.jira.issue.fields.VotesSystemField",
"value" : { "hasVoted" : false,
"self" : "http://localhost:8090/jira/rest/api/2.0.alpha1/issue/MKY-1/votes",
"votes" : 0
}
},
"watcher" : { "name" : "watcher",
"type" : "watcher",
"value" : { "isWatching" : false,
"self" : "http://localhost:8090/jira/rest/api/2.0.alpha1/issue/MKY-1/watchers",
"watchCount" : 0
}
},
"worklog" : { "name" : "worklog",
"type" : "worklog",
"value" : [ ]
}
},
"html" : { },
"key" : "MKY-1",
"self" : "http://localhost:8090/jira/rest/api/2.0.alpha1/issue/MKY-1",
"transitions" : "http://localhost:8090/jira/rest/api/2.0.alpha1/issue/MKY-1/transitions"
}

확장가능 속성

As you can see from the example above, the very first entry is something called expand. In the JIRA REST API, some of the response information is 'hidden' within expandable properties. In order to see this information, you must explicitly expand it by including the expand query parameter in your REST API call.

To find out what properties are expandable, look at the expand field in the JSON response to see what other information is available.

Expandable properties allow the generation of optimal REST API responses, which avoid the following problems associated with offering 'too much' or 'too little' information:

  • If responses provide too little information, you may require many more HTTP GET REST API calls to collect all the information you require. Overloading a JIRA site with this volume of REST API calls could generate network latency, which in turn could severely impact JIRA's performance.

  • If responses provide too much information, then the network bandwidth, memory usage and processing load of a JIRA server could be severely impacted if the server receives multiple simultaneous REST API calls. For instance, if all we want to know about an issue from a REST API call is its key, then there is no need to retrieve additional information about the issue in the response, such as a potentially extensive list of comments.

Expandable properties give you some control over the data you get back.


In the following example, an issue's content is being retrieved, along with the expanded details of its fields property, which excludes details about comments or attachments. The following call:

curl -u admin:admin http://localhost:8090/jira/rest/api/2.0.alpha1/issue/MKY-1?expand=html

Would generate a response like this (some part of the response have been removed for brevity and clarity):

{
expand: "html",
self: "...",
key: "MKY-1",
fields: { ... },
transitions: "...",
html: {
environment: "",
description: "<p>Sed ac magna ante, et euismod.</p<",
comment: [
"<p>Ut cursus lobortis nunc, venenatis vulputate.</p>"
],
worklog: [ ]
}

This may change:


Finding the right balance in the amount of information that should be retrieved via expandable properties (and the exact representation of each field) is a tricky process and based on feedback gathered from the JIRA developer community, we may amend this in future.

Should we include all of the icons in every response? For the Project field, should we include information such as the Project Lead or should you retrieve this information from the JIRA REST API "project" resource?

What we've chosen for this Alpha is a "reduced" variant of the field that contains the kind of information that 90% of clients (we hope) will want. The other 10% will need to follow the Self link section (below) to see the extra data.

We also want to remove the distinction between system and custom fields as much as possible. For example, your client may only need to deal with a "user" and does not care if the user is from a UserCustomField or the Assignee system field.

Let's take a closer look at the "reporter" field from the example above:

{
"name" : "reporter",
"type" : "com.opensymphony.user.User",
"value" : { "displayName" : "admin",
"name" : "admin",
"self" : "http://localhost:8090/jira/rest/api/2.0.alpha1/user/admin"
}
}

Lots of fields like this one will have a "self" link, which takes you to the canonical location for that resource. Sometimes there will be more information there. For instance, right now we don't know the email address of the user with the "name" of "admin". Hence, if we follow that link (using context path "/jira"):

curl -u admin:admin http://localhost:8090/jira/rest/api/2.0.alpha1/user/admin

Would generate a response like this:

{
"self" : "http://localhost:8090/jira/rest/api/2.0.alpha1/user/admin",
"name" : "admin",
"emailAddress" : "admin@example.com",
"avatarUrl" : "http://localhost:8090/jira/secure/useravatar?size=large&ownerId=admin",
"displayName" : "Administrator",
"groups" : [
"jira-administrators",
"jira-developers",
"jira-users",
"jira-homosapien-devs",
"jira-homosapien-users"
]
}

This gives us the email address of the user "admin", along with their avatar URL and a list of the groups to which this user belongs.

탑레벨 이슈 정보

Here is the information that will be in the top level of the issue:

Top Level Keys

Description

expand

The list of fields that can be expanded in a REST response.

self

Most fields in JIRA's REST API have a "self" attribute. This will be the canonical URI for the resource.

key

The issue key itself.

fields

All of the custom and system fields of the issue.

transitions

The transitions that are currently valid for this issue.

html

if requested, an HTML representation of wiki rendereable text fields (i.e. comments, worklogs, etc.)

The exact details contained within the fields of issue will depend on how your JIRA site is configured. For instance, if you do not have attachments enabled on your JIRA instance, then there will not be an attachment attribute in the response. If the issue you are retrieving information about is not a SubTask, then you will not have a link to a parent issue.

필드

All fields in JIRA have a common representation under the fields key.

field_id: {
name: field_name
type: field_type
value: field_value
}

For system fields the field_id and field_name will be the same. For custom field the field_id will be a unique descriptor in the format of customfield_10040 while the field_name will be the text description provided when it is created (e.g. "Participants").

The field_type is intended to provide some indication about the format and content of field_value. It is intended to be an opaque identifier.

The exact values used for field_type may change in the future as we refactor and improve the internal type system being used by JQL and REST.

The format of field_value will vary depending on the field in question. For description, for instance, it will be a simple string. For comment it will be an array of comment objects.

렌더링

Within the fields section all text will be presented in its raw format. If you have configured a field to use the wiki renderer then you may also want to get the HTML rendered version of the field. This can be accessed via the html expandable entity when you provide the expand=html query parameter.

JIRA 데이터 수정

This Alpha release of JIRA's REST API is primarily focused around viewing an issue. However, it provides a few things which you can use to modify the state of JIRA. Since REST is built on plain HTTP, this means that anything which uses GET is "safe" - that is, you are just viewing a resource. Other HTTP methods – POST, PUT, and DELETE – are for modifying JIRA data. If you look through the JIRA REST API Reference documentation, you will see a few resources that understand these HTTP methods for modifying JIRA data. We have already seen an example of this in action when we logged in and logged out (above), and used a POST to create a new session and DELETE to remove it.

전체 예제

Here are some comprehensive examples that demonstrate how to use and implement the JIRA REST API.

Please Note:


These examples were developed for explanatory purposes only. They are not production-quality and should not be used in a production environment.

Let's write a small python script that will use our REST interface to graph the relationships between issues in our JIRA site.

We'll use the small helper library (restkit) to simplify the REST requests. This library is not strictly necessary — after all, REST is just HTTP. However, restkit can be used for convenience. We also rely on Google Charts to do the actual graphing for us too.

Using the JIRA REST API is fairly simple:

  • you make an HTTP call,
  • get some data back,
  • then do something with that data.

In the following example, 95% of the code is doing something other than interacting with the JIRA REST API. So before we see the full example, let's highlight the actual REST usage out of context to show how simple it usually is. This example uses Python:

resource = Resource(url + '/rest/api/latest/issue/%s' % key, pool_instance=pool, filters=[auth])
response = resource.get(headers = {'Content-Type' : 'application/json'})
if response.status_int == 200:
# Not all resources will return 200 on success. There are other success status codes. Like 204. We've read
# the documentation though and know what to expect here.
issue = json.loads(response.body_string())
return issue

This performs a GET on the issue, checks for a successful response, and the parses the JSON response into a Python dictionary. The filters=[auth] line is how we told restkit to perform BASIC Authorisation. Later on, we'll reach into this Python dictionary to grab the data we want for our work:

fields = issue['fields']
if fields.has_key('sub-tasks') and fields['sub-tasks'].has_key('value'):
for other_issue in issue['fields']['sub-tasks']['value']:
# do work with a subtask

You can view the full source by downloading the attachment: draw-chart.py

You can see the script's command line options using the standard command:

./draw-chart.py --help

You can test this against your JIRA site with:

./draw-chart.py --user=username --password=password --jira=<url-of-your-jira-site>

The output should look similar to:

Fetching JRADEV-1391
Fetching JRADEV-2062
Fetching JRADEV-2063
Fetching JRADEV-1107
Fetching JRADEV-112
Fetching JRADEV-1108
Fetching JRADEV-1218
Fetching JRADEV-1219
Fetching JRADEV-1220
Fetching JRADEV-1221
Fetching JRADEV-1684
Fetching JRADEV-2064
Fetching JRADEV-1390
Fetching JRADEV-1389
Fetching JRADEV-1388
Fetching JRADEV-2125
Fetching JRADEV-1264
Fetching JRADEV-1256
Writing to issue_graph.png

Open up the issue_graph.png to show an image that should look something like this:

Blue lines with arrows denote SubTasks.

예제 #2: Quickview Inline Dialog Plugin

This time, we'll create a JIRA plugin that uses the REST API. We want to look through all the comments on the issue and add a little tooltip that will pop up when you hover over a link to a JIRA issue.

The popup should contain a "quick view" of information about the target issue (similar to the example shown in the following image) so that we do not have to click the issue's link to see this information.

We can achieve this using a Web Resource Context. This lets our plugin put JavaScript just on the View Issue page of JIRA.

First, we define the Web Resource Context in our atlassian-plugin.xml:

<web-resource key="remote-link" name="Remote Issue Linking">
<resource name="linker.js" type="download" location="linker.js"/>
<context>jira.view.issue</context>
</web-resource>

Then we have linker.js look in the comment body for URLs that 'look like' they might point to JIRA issues. Next, obtain the JSON representation of the issue using JIRA's REST API, do some quick formatting on it and put it into an AUI InlineDialog.

jQuery(document).ready(function() {
var i=new Date().getTime()
jQuery("#issue_actions_container").find('.action-body a').each(function() {
if (this.href.match(/\/browse\/[A-Z]+\-\d+$/)) {
var split = this.href.split('/browse/')
var base = split[0]
var key = split[1]
var options = { cacheContent: true, onHover: true, showDelay: 400, hideDelay: 400, closeOthers: false, width: 500 }
var draw = function(contents, trigger, showPopup) {
jQuery.getJSON(base + '/rest/api/latest/issue/' + key, function(data) {
var fields = data["fields"]
contents.empty()
contents.append(
"<ul class=\"item-details\">"
+ "<li>"
+ "<dl><dt>Summary: </dt>" + "<dd>" + fields["summary"]["value"] + "</dd></dl>"
+ "<dl><dt>Type: </dt>" + "<dd>" + fields["issuetype"]["value"]["name"] + "</dd></dl>"
+ "<dl><dt>Priority: </dt>" + "<dd>" + fields["priority"]["value"]["name"] + "</dd></dl>"
+ "<dl><dt>Status: </dt>" + "<dd>" + fields["status"]["value"]["name"] + "</dd></dl>"
+ "<dl><dt>Assignee: </dt>" + "<dd>" + fields["assignee"]["value"]["name"] + "</dd></dl>"
+ "<dl><dt>Description: </dt>" + "<dd>" + fields["description"]["value"] + "</dd></dl>"
+ "</li></ul>")
contents.append("<form id=\"add-watch\" name=\"watch\" action=\"\">")
jQuery("<input type=\"button\" name=\"button\" value=\"Watch\"/>").click(function() {
// We don't actually know our own username...and we need it to add a Watcher. So we get it from the
// "current user" resource
jQuery.getJSON(base + '/rest/auth/latest/session', function(data) {
jQuery.ajax({ type: "POST", url: base + "/rest/api/latest/issue/" + key + "/watchers", data: data['name'], dataType: "json", contentType: "application/json" })
})
}).appendTo(contents)
contents.append("</form>")
showPopup()
})
}
AJS.InlineDialog(jQuery(this), "issue-linking-" + (i++), draw, options)
}
})
})

You can download the full demo plugin here: demo-plugin-src.zip

추가 참조문서

  • The Atlassian REST API space is the central point for all Atlassian REST API documentation. providing overviews and links to product-specific APIs.
  • The Atlassian REST API Design Guidelines is a general, cross-product explanation of Atlassian's overall approach to REST. You can read that later to learn more about what is guiding our overall approach in JIRA.

JIRA REST clients

  • JIRA REST Java Client Library is a sample implementation of JIRA REST client, which should help all Java and JVM-based languages developers take advantage of JIRA REST API easily and quickly.
  • 레이블 없음