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

Next challenges

Recent achievements

  • Global
  • Personal


  • Give kudos
  • Received
  • Given


  • Global

Trophy case

Kudos (beta program)

Kudos logo

You've been invited into the Kudos (beta program) private group. Chat with others in the program, or give feedback to Atlassian.

View group

It's not the same without you

Join the community to find out what other Atlassian users are discussing, debating and creating.

Atlassian Community Hero Image Collage

How to programmatically add Epic links to Jira Tickets?

I have developed an add-on which has the capability to connect to our remote application and import security vulnerabilities into Jira server as Jira issues(Story and bug tickets). 

However I need to link these stories to epics and bugs to stories (programmatically) respectively. Anyone here who has tried this before or have an idea on how to proceed with this?

Below are two approaches I have tried 

Approach 1- Update the epic link of an issue that is already created.  

MutableIssue missue = issueManager.getIssueObject(jiraIssue.getKey());
CustomFieldManager cfMgr = ComponentAccessor.getCustomFieldManager();
CustomField epicCustomField = cfMgr.getCustomFieldObjectByName("Epic Link");
MutableIssue epicIssue = issueManager.getIssueObject("B1-976");// This is my epic

 epicCustomField.updateValue(null, missue,
new ModifiedValue(missue.getCustomFieldValue(epicCustomField), epicIssue),
new DefaultIssueChangeHolder()); 

Approach 2- Set Epic link when a new issue is being created 

MutableIssue newJIRAIssue = ComponentAccessor.getIssueFactory().getIssue();
CustomFieldManager cfMgr = ComponentAccessor.getCustomFieldManager();
CustomField epicCustomField = cfMgr.getCustomFieldObjectByName("Epic Link");

MutableIssue epicIssue = ComponentAccessor.getIssueManager().getIssueObject("B1-976");// This is my epic

newJIRAIssue.setCustomFieldValue(epicCustomField, epicIssue);



Both approaches are not working. The issues are created/updated successfully with all other custom fields except the Epic Link. 

Any help on this will be highly appreciated.

2 answers

0 votes
brbojorque Community Leader Jan 07, 2020

Hi @kavindha ranasinghe ,

I'm looking at the code and they seem alright, one problem I can point out is the saving of the custom field / issue.

You have to save it in order for the changes to persist.

Something like this should do it.

issueManager.updateIssue(userObj, issue, Event...)

Hi @brbojorque

Thank you for the suggestion. I am doing this later on in the code once I have completed adding the rest of the fields such as assignee and reporter as well. All the default Jira fields and custom fields are created successfully in the ticket except the Epic Link.   

I'm trying to link Epics as well. Up to now I wasn't succesfull.

I found some examples during my research. But only with Groovy scripts.
I'm wondering how the relation between the Epic issue and the issues IN the Epic works.
In your example (Approach 2) you set the custom field only at the new created issue. I could imagine that an update of the custom field at the EPIC is needed too.
I'll continue today finding a solution. Each hint is very welcome and for sure I'll post my solution - if I found one ;-)

Hi @Andreas Didion

I tried the same thing out on Jira Cloud using the REST API and it is working fine with Jira Cloud looks like the issue is with Jira Server. Here is my approach if you want to try it out as well. 

Approach 1 - Create issue and then add the issue/s to the relevant Epic.

This can be achieved using the below  end point and JSON body 


POST -  /rest/agile/1.0/epic/{epicKey}/issue
Body -   {  {  "issues": [    "issue-1, issue-2, issue-3"  ]}



Approach 2 - Add the epic to the Epic link custom field during or after issue creation

This can be achieved using the below  end point and JSON body 


PUT - /rest/api/2/issue/{issueKey}
Body - { "fields": {"customfield_10008" : "EpicKey" } } //customfield_10008 represents Epic Link

Hi @kavindha ranasinghe 

Thank you. I need to do it programmatically with Java on Jira Server. (we implemented an own plugin which must be extended by this function)

If the logic in code is the same as via webservice I think

- during creation: add the Key of the EPIC to the customfield at new issue
- after creation: add the issue(s) to the EPIC

But how does the EPIC "knows" during creation of a new Issue that the new Issue is an issue within this EPIC? It sounds unlogical to me that the EPIC needs no update.

Hi @Andreas Didion

I don't think there's any problem with the logic there because if we were doing this manually we only have to give the name of the EPIC on the issue creation page nothing to update on the Epic side.

@kavindha ranasinghe 

Programmatically (with Java) I was able to link a new issue to an existing EPIC issue by seeting the "Epic Link" Custom field at both issues and call ".updateValue"


newIssue.setCustomFieldValue(epicLinkCustomField, epicIssue);
epicLinkCustomField.updateValue(null, newIssue, new ModifiedValue<Object>(null, epicIssue), new DefaultIssueChangeHolder());


and the same for the epicLinkIssue:


epicIssue.setCustomFieldValue(epicLinkCustomField, newIssue);
epicLinkCstField.updateValue(null, epicIssue, new ModifiedValue<Object>(null, newIssue), new DefaultIssueChangeHolder());

Hi @Andreas Didion 

I tried this out it didn't work. Would you mind sharing the full code snippet with me to see if I am doing anything wrong.

Hi @kavindha ranasinghe 

I simplified the code (no logging, no relation to "own" parts/code). Here is the important part:

void setEpicLink() {
CustomField epicLinkCstField = getCustomFieldByName("Epic Link");
if(epicLinkCstField != null)
getIssueObject().setCustomFieldValue(epicLinkCstField, originIssue);
epicLinkCstField.updateValue(null, getIssueObject(), new ModifiedValue<Object>(null, originIssue), new DefaultIssueChangeHolder());

originIssue.setCustomFieldValue(epicLinkCstField, getIssueObject());
epicLinkCstField.updateValue(null, originIssue, new ModifiedValue<Object>(null, getIssueObject()), new DefaultIssueChangeHolder());

Helper Method to get the custom field:

CustomField getCustomFieldByName(String customFieldName)
CustomField returnObject = null;
Collection<CustomField> customFieldList = ComponentAccessor.getCustomFieldManager().getCustomFieldObjectsByName(customFieldName);
for(CustomField custField : customFieldList)
returnObject = custField;
return returnObject;


  • this code is part of an extension of com.atlassian.jira.web.action.issue.CreateIssueDetails
  • we do create a new issue with relation to an origin one
  • therefore the method <code>getIssueObject()</code> in this class returns an <code>com.atlassian.jira.issue.MutableIssue</code>-Object which is the one we newly created and link to the originIssue
  • originIssue is the Epic (or better, the existing issue)


I hope this solves your problem ;-)


Best Andreas

Like VICTORIA_HOYT likes this

Thank you for your solution, Andreas.  It worked for me!

Suggest an answer

Log in or Sign up to answer

Community Events

Connect with like-minded Atlassian users at free events near you!

Find an event

Connect with like-minded Atlassian users at free events near you!

Unfortunately there are no Community Events near you at the moment.

Host an event

You're one step closer to meeting fellow Atlassian users at your local event. Learn more about Community Events

Events near you