Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

How to pull external API data to select list custom field Jira DC - Script Runner

Bongani Hermans February 25, 2025

 

 

Hi ,

We are trying to populate a select list field with value's from external API
Our use case involves a select list field as follows -
When a user creates or updates a ticket, there will be a field name (e.g Primary application Name) which is a select list. If a user enters values that are available in the API endpoint, the field will populate or select an existing value from the API or list available from custom field and save it to the field. If the user edits the ticket, they will navigate to the field and update it with a value.

Users can either be searched using the UTR key or the Application Name associated with the UTR. Once selected those value’s will be saved to the field.

The external API use's a token which expires every 8 hours, however we can use the clientID and secret ID to generate the token. Please see below script which I tested but does not execute 

 

Regards,

Bongani

 

import groovy.json.JsonSlurper
import groovy.json.JsonBuilder
import java.net.HttpURLConnection
import java.net.URL
import javax.net.ssl.*

def clientId = "######################"           // Replace with your client ID
def clientSecret = "########################"   // Replace with your client secret
def tokenUrl = "######################"  // Token endpoint
def apiUrl = "####################################"  // API endpoint

def searchFieldName = "Get UTR value's"                          // Your Custom Field name
def jiraUsername = "########################"   // Your Jira username
def jiraPassword = "###########################" // Your Jira password or API token
def jiraUrl = "################################"  // Your Jira instance URL

// -------------------------------
// STEP 1: Disable SSL Verification (for testing only!)
// -------------------------------
def disableSSLVerification() {
    TrustManager[] trustAllCerts = [
        [ getAcceptedIssuers: { -> null },
          checkClientTrusted: { certs, authType -> },
          checkServerTrusted: { certs, authType -> }
        ] as X509TrustManager
    ]

    SSLContext sc = SSLContext.getInstance("SSL")
    sc.init(null, trustAllCerts, new SecureRandom())
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.socketFactory)
    HttpsURLConnection.setDefaultHostnameVerifier({ hostname, session -> true })
}

disableSSLVerification()

// -------------------------------
// STEP 2: Obtain Access Token from External API
// -------------------------------
def getAccessToken(tokenUrl, clientId, clientSecret) {
    def url = new URL(tokenUrl)
    def connection = (HttpsURLConnection) url.openConnection()
    connection.requestMethod = "POST"
    connection.doOutput = true
    connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded")

    def postData = "grant_type=client_credentials&client_id=${URLEncoder.encode(clientId, 'UTF-8')}&client_secret=${URLEncoder.encode(clientSecret, 'UTF-8')}"
    connection.outputStream.withWriter("UTF-8") { it << postData }

    def responseText = connection.inputStream.text
    log.info("Token Response: ${responseText}")

    if (connection.responseCode == 200) {
        def response = new JsonSlurper().parseText(responseText)
        return response.access_token
    } else {
        log.error("❌ Token request failed: ${connection.responseCode} - ${connection.responseMessage}")
        return null
    }
}

def accessToken = getAccessToken(tokenUrl, clientId, clientSecret)
if (!accessToken) return

// -------------------------------
// STEP 3: Call External API to Fetch Data (UTRKey & Title)
// -------------------------------
def callApi(apiUrl, accessToken) {
    def url = new URL(apiUrl)
    def connection = (HttpsURLConnection) url.openConnection()
    connection.requestMethod = "GET"
    connection.setRequestProperty("Authorization", "Bearer ${accessToken}")
    connection.setRequestProperty("Content-Type", "application/json")

    def responseText = connection.inputStream.text
    log.info("API Response: ${responseText}")

    if (connection.responseCode == 200) {
        return new JsonSlurper().parseText(responseText)
    } else {
        log.error("❌ API call failed: ${connection.responseCode} - ${connection.responseMessage}")
        return null
    }
}

def apiResponse = callApi(apiUrl, accessToken)
if (!apiResponse?.results) {
    log.warn("⚠️ No results from API.")
    return
}

// -------------------------------
// STEP 4: Populate the Select List Field for Picker
// -------------------------------
def searchOptions = apiResponse.results.collect { result ->
    return [value: "${result.UTRKey} - ${result.Title}", id: result.UTRKey]
}

return searchOptions

1 answer

0 votes
Stefan Stadler
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
February 26, 2025

Hi @Bongani Hermans 

may I ask a question on this scenario?

Where did you enter this code? Is it a Listener, a Behaviour or even a scripted field?

In the description this is not getting clear.

Actually, Listeners would handle the population of custom fields AFTER a certain event is triggered. This is very similar to Jira Automations and will update the field value based on what is entered in the custom field when the Listener runs.

Scripted fields will be showing some content when the issue is displayed. So they are more or less calculated at runtime.

Behaviours change the appearance of fields while an issue is edited. It can add values/content to a given field or hide options from select lists. This is all running in the client browser and needs JavaScript to work.

Unfortunately, it is not clear what is the intended option you would like to choose and in your sample script above, the only place you are referencing the custom field is in line 12 (when you define the name). After that, it is more or less only about handling the REST API, which I assume is working fine.

Please explain the use case a little further and where you added this code!

Hope this helps!

Thanks!

Stefan

Bongani Hermans February 27, 2025 edited

Hi Stefan,

Currently testing this code using script console, Once I get the code to work I will use script custom picker in jira similar to the below example :


When a user creates a ticket, there will be a select list with value's populated from the external API to choose from, we are hoping to update the field option value in real time, where a user's search action dynamically pulls data from the API.

Regards,

Bongani

https://docs.adaptavist.com/sr4js/8.26.0/features/script-fields/built-in-script-fields/custom-picker

Stefan Stadler
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
February 27, 2025

Hi @Bongani Hermans 

that means all that is important is the return value at the end. Can you check (and maybe log) the values that are returned? 

Such as 

log.error(searchOptions.toString())
return
 searchOptions

instead of

return searchOptions

Maybe this brings some light into this.

Suggest an answer

Log in or Sign up to answer
DEPLOYMENT TYPE
SERVER
TAGS
atlassian, atlassian community, university, on demand, transition to jira cloud

Transition to Jira Cloud

Switch to Jira Cloud with Atlassian University! Explore new navigation, issue views, and Cloud features like team-managed projects and automation. Tailored for Data Center users & admins, these courses ensure a smooth transition. Start your journey today!

Enroll now
AUG Leaders

Upcoming Jira Events