zAgileConnect stores Case (or other Salesforce object integrated with Jira Issue) data in JIRA Issue entity properties which can be accessed through the JIRA REST API. 

It stores one entity property for each Case associated to a Jira Issue. Each entity property name starts with "SF_ENTITY_", as shown here:



The content of an entity property that stores Case info looks as shown in the example below (for Case attributes shared with Jira):



Please note that only Case properties (fields) are stored in Jira Issue Entity Properties.  Properties associated with Case-related objects, such as Account (ex: Name), Contact (ex: Name, Email), etc. must be passed through a Case formula field to Jira.


To search for issues that have at least one related Case we can use the following JQL query.  The JQL query can be executed using JIRA REST API https://docs.atlassian.com/jira/REST/cloud/#api/2/search-search


issue.property[relatedSalesforceEntities].total>0


CODE


Atlassian provides some tutorials about how to access Jira using the Jira REST API

Example:

Following is a sample python script that uses a small 'optional' helper library (restkit) to simplify the REST requests.  

The example.py script executes a JQL query to:

  1. retrieve issues with at least one related Case 
  2. access the Entity Properties for the first issue in the response
  3. retrieve the values for the CaseNumber attributes from the entity properties for all the related Cases for that Issue


Example.py

import optparse
import json
from restkit import Resource, BasicAuth, request
import ast

"""This scripts logins to the specified Jira, retrieves any issue
    with more than 4 linked cases, selects the first of those issues and
    prints the linked cases' ids."""

def getLinkedCaseNumbers(issuekey, auth):
    """Returns the case numbers linked to the issuekey."""
    resource = Resource(options.jira_url+('/rest/api/2/issue/%s/properties' % issuekey), filters=[auth])
    response = resource.get(headers={'Content-Type': 'application/json'}) # Retrieves the issue's properties.
    if response.status_int == 200:  # Verifies the response has content in it.
        entity_properties = json.loads(response.body_string())  # Turns the json response into a python dict.

    casenumbers_list = []
    for entity in entity_properties['keys']:
        if entity['key'].startswith('SF_ENTITY_') :
            resource = Resource(entity['self'], filters=[auth])
            response = resource.get(headers={'Content-Type': 'application/json'})  # Retrieves the linked cases.
            if response.status_int == 200:# Verifies the response has content in it.
                caseInfo = ast.literal_eval(response.body_string())  # Turns the obtained string into a python dict.
                casenumbers_list.append(caseInfo['value']['CaseNumber']) #Retrieves casenumber attribute, it could be any other case attribute stored in the entity property
    
    return casenumbers_list  # Returns the case numbers.


def getResolvedIssueKeysWithRelatedCases(auth):
    """Returns the issue keys for resolved issues that have at least 1 linked case."""
    resource = Resource(options.jira_url+'/rest/api/2/search?fields=Key&jql=issue.property[relatedSalesforceEntities].total>0+AND+resolved!=null', filters=[auth])
    response = resource.get(headers={'Content-Type': 'application/json'})
    #TODO: JIRA search REST API returns a max of 50 issues in the response, so we will need iterate over all the paginated results
    if response.status_int == 200:  # Verifying the response has content in it.
        issues = json.loads(response.body_string())  # Turn the json response into a python dict.
        issue_list = [issue['key'] for issue in issues['issues']]  # Cleans any issue info that's not its key.
        return issue_list


def parse_args():
    """Generates command line arguments for the script."""
    parser = optparse.OptionParser()
    parser.add_option('-u', '--user', dest='user',
                      help='Username to access Jira')
    parser.add_option('-p', '--password', dest='password',
                      help='Password to access  Jira')
    parser.add_option('-j', '--jira', dest='jira_url',
                      help='Jira URL')
    return parser.parse_args()  # Returns the user defined command line arguments.


if __name__ == '__main__':

    (options, args) = parse_args()

    auth = BasicAuth(options.user, options.password)  # Script uses basic auth to login to Jira.

    issue_list = getResolvedIssueKeysWithRelatedCases(auth)
    print ('Unresolved Issues with at least 1 related case:')
    print ', '.join(issue_list)
    cases = getLinkedCaseNumbers(issue_list[0], auth)
    print ('The issue %s has the following associated cases:' % issue_list[0])
    print cases

PY


Example output

$ python example.py --user xxxyyy --password yyyxxx --jira https://jira-stg.atlassian.net
Unresolved Issues with at least one related Case:
SEL-25118, SEL-24879, SEL-24752, SEL-24611, SEL-24463, SEL-24299, SEL-24209, SEL-24042, SEL-23916, SEL-23756, SEL-23537, SEL-23427, SEL-23424, SEL-23422, SEL-23421, SEL-23420, SEL-23419, SEL-21919, SEL-21732, SEL-21314, SEL-21145, SEL-21000, SEL-20893, SEL-20730, SEL-20336, SEL-19952, SEL-19564, SEL-19365, SEL-18959, SEL-18865, SEL-18719, SEL-18637, SEL-18635, SEL-18634, SEL-18586, SEL-18457, SEL-18350, SEL-18248, SEL-17955, SEL-17760, SEL-17757, SEL-17601, SEL-17403, SEL-17284, SEL-17183, SEL-17094, SEL-16995, SEL-16603, SEL-16495, SEL-16391
The issue SEL-25118 has the following associated Cases:
['00080747']