t work we use JIRA to manage our sprints. I like JIRA, it’s got a nice interface, is easy to use, and has a variety of useful reports.

However, there are certain metrics that management uses to track our team that are not available in any of the default JIRA reports.

This isn’t a problem though, as much of the data in JIRA is available problematically through REST APIs.

The REST APIs return content as JSON, which is easily parsed.

Here’s a sample function to retrieve the data behind the JIRA sprint history report.

public string GetSprintHistory(string authKey,int sprintId, int boardId)
    string responseText = string.Empty;

    string url = string.Format("https://jira.jlion.com/rest/greenhopper/1.0/rapid/charts/sprintreport?rapidViewId={0}&sprintId={1}", boardId, sprintId);

    var request = (HttpWebRequest)WebRequest.Create(url);

    request.Method = "GET";
    request.ContentType = "application/json; charset=utf-8";
    request.Headers.Add(string.Format("Authorization: Basic {0}", authKey));

    var response = (HttpWebResponse)request.GetResponse();

    responseText = new StreamReader(response.GetResponseStream()).ReadToEnd();

    return responseText;

Our JIRA is on-premises and so I’m able to use basic authentication. For basic authentication, the authKey value is simply the base 64 encoded text of username:password. Note that this isn’t very secure and Atlassian promises to depreciate this method of access in a future release. Also, for cloud-hosted JIRA, this won’t work and it’s necessary to use OAuth instead. But for now, for on-premises, it’s easy to implement and works fine for my simple reporting application.

A request to the API will return lots of JSON, most of which you probably don’t care about. Rather than attempting to build a model and deserialize the returned JSON, I use JSON Path to query for the specific values that I’m looking for. This is comfortably for me as I frequently use XPath to query XML.

The nice thing about the REST APIs is that they can be executed from a browser. I do this, get the JSON, and use https://jsonlint.com/ to pretty-print the JSON so I can easily find the data that I’m looking for.

I then use Newtonsoft.Json JObject and JToken to query for specific values.

Here’s an example of using the sprint report API (above) to get a list of completed issues.

string boardHistoryJson = j.GetSprintHistory(authKey, historicalSprint.id, BOARD_ID);
JObject allIssues = JObject.Parse(boardHistoryJson);
JToken contents = allIssues.SelectToken("$.contents");
JToken completedIssues = contents.SelectToken("$.completedIssues");
foreach (JToken oneCurrentIssue in completedIssues)
    SprintIssue thisIssue = new SprintIssue();
    thisIssue.Key = (string)oneCurrentIssue["key"];

    JToken currentIssueStatus = oneCurrentIssue.SelectToken("$.currentEstimateStatistic");
    JToken currentIssueStatusValue = currentIssueStatus.SelectToken("$.statFieldValue");
    thisIssue.CurrentPoints = (int)currentIssueStatusValue["value"];