Jira Cloud - REST API - Transitions

Context - I have been working on a small locally hosted browser app using JavaScript to parse reporting we receive on a daily basis and upload specific data fields to our tickets via the API.

Currently using the following methods I have been successful with updating individual fields and adding comments etc. However when attempting to transition a status I receive a 403 response.

function updateField(user, token) {
	$.ajax({
		type: "PUT",
		url: "https://{Web Address}/rest/api/2/issue/" + ticketRef,
		dataType: "json",
		headers: { "Authorization": "Basic " + btoa(user+":"+token),
				"Content-Type": "application/json", 					
				'X-Atlassian-Token': 'nocheck' },

		data: JSON.stringify({ "fields":	{
			"description":"Description Update",
			"customfield_10543":"Update Test"
			}
		}),
		
		success: function (json) { console.log(json) },
		error: function (xhr, ajaxOptions, thrownError) { 
			console.log(xhr.status); console.log(thrownError); console.log(ajaxOptions);
		}
	});
}

function addComment(user, pass) {
	$.ajax({
		type: "PUT",
		url: "https://{Web Address}/rest/api/2/issue/" + ticketRef,
		dataType: "json",
		headers: { "Authorization": "Basic " + btoa(user+":"+token), 
		"Content-Type": "application/json", 
		'X-Atlassian-Token': 'nocheck' },
		
		data: JSON.stringify({
		   "update": { "comment": [{"add": {"body": "Comment Test"}}] }
		}),

		success: function (json) { console.log(json) },
		error: function (xhr, ajaxOptions, thrownError) {
		  console.log(xhr.status); console.log(thrownError); console.log(ajaxOptions);
		}
	});
}

This next function is where I am experiencing issues. I am wondering if this could possibly be some form of permissions issue with the Jira server settings, especially as all other information can be modified except for transitions.

I have tried several variations of headers etc.
I am using an API token + user id for auth with base64 encoding.

I do not have direct access to the Server and therefore would need to present information backing my assertions to have any settings updated if it was a permissions issue.

function updateStatus(user, token) {
	$.ajax({
		type: "POST",
		url: "https://{Web Address}/rest/api/3/issue/" + ticketRef + "/transitions",
		dataType: "json",
		headers: { "Authorization": "Basic " + btoa(user+":"+token), "accept": "application/json", 
				"cache-control": "no-cache", "Content-Type": "application/json", 
				'X-Atlassian-Token': 'nocheck'},
		
		data: JSON.stringify({'transition' : {'id': '131' }}),
				
		success: function (json) {
		  console.log(json)
		},
		error: function (xhr, ajaxOptions, thrownError) {
		  console.log(xhr.status);
		  console.log(thrownError);
		  console.log(ajaxOptions);
		}
	});
}

Any insight or assistance would be greatly appreciated.

Hello @KevinGroundwater

Your questions is tagged with Jira CLOUD, but half way through you start referring to Jira SERVER. Which platform type are you making the request again?

Jira Server didn’t have a v3 version of the REST API. You must use the v2 equivalent.

Also, the cache-control and X-Atlassian-Token header entries are not used in this context and can be removed.

Thank you for the comments.

We transitioned to Jira Cloud recently. I had also tried different variations of the the updateStatus function based on research and had previously tried api/2.

Then I suggest it’s probably just a plain old ordinary permissions issue. The user whose credentials you are using to make the request doesn’t have permission to transition issues to the state with the id 131.

You said “I do not have direct access”, so whose credentials are you using if not yours?

You need to log into Jira’s GUI with that user’s credentials, then try to transition the issue to the same state you’re trying via the REST API.

Thanks for the reply.

I have my own credentials and a recently created service account. Both accounts are able to transition within the Jira GUI, just not via the API.

Is there some difference in Jira Cloud settings for API permissions relating to issue transition?

Nope. The API uses the exact same user permissions as the GUI. If the user account can transition the issue to that state in the GUI, then their account can transition to that state via the REST API.

I think you have a more fundamental problem. Something like the id of the transition is wrong or some other aspect of the request itself is wrong. Do some testing with a test tool like Postman first, to confirm the raw request is valid.

Also, apart from getting a 403 error, what is the body of the error message itself?

Message response:
“{“errorMessages”:[“Issue does not exist or you do not have permission to see it.”],“errors”:{}}”

However I know the issue exists as it’s a test ticket that I have already been updating the other fields on, also tried with other ticket ID’s and the id used in the transition was identified from the workflow of the possible states ‘this’ ticket could transition to, from an open state.

What you are describing now sounds some sort of coding mistake. Somehow, your JavaScript is screwing up the request by submitting the wrong key for the issue, or the wrong permission.

Where you changed the JSON body to stringify to use single inverted commas:

data: JSON.stringify({'transition' : {'id': '131'}})

not the correct, double inverted commas:

data: JSON.stringify({"transition" : {"id": "131"}})

might be contributing. I don’t know enough about the stringify command to be certain it can compensate for that.

It’s up to YOU to work your way through the problem. Be methodical. Eliminate what you know is not the problem. Test the raw request first with a test tool like Postman to confirm if it really is a permission issue or it’s a coding issue. Also, don’t assume the issue you are trying to transition is subject to the same workflow of those other issues. Do a GET Transitions lookup for that issue to know exactly what status it can be transitioned to.

I’ll have to leave you with this now. Have fun.

1 Like

Thank you for your feedback.

Ok so, with a few Curl request attempts managed to get the status change required. Although converting back to JavaScript gives the same 403.