Trying to use Python & REST API to create an issue in Jira Cloud. Getting response 400, which is "Bad Request." How to tell what's bad? Is it the headers? The payload? Did I mess up the token or base64 steps? Also, I see python examples on the site that don't use the same headers. The first link below is current, but I'm not sure the Python example code is up to date.
Thank you for any assistance.
Hi @Dave Puryear, welcome to the community.
According to the Atlassian documentation, a 400 status code means "the request does not have the required fields, or the fields the request has are invalid in some way."
In my experience, when I get a 400 status code response, the JSON document request body is either syntactically or semantically malformed. There are JSON validators online to check the syntax and structure of your request document.
Checking the request semantics, like required fields, start by looking a the response body of the error message. Some companies put error details in the body, I don't remember if Atlassian does or not.
Thank you, Jim. JSON is solid. No error details, other than "Bad Request." Curious if anyone can connect to their Jira cloud using the snippet provided at https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-issues/#api-rest-api-3-issue-post:
# This code sample uses the 'requests' library: # http://docs.python-requests.org import requests from requests.auth import HTTPBasicAuth import json url = "https://your-domain.atlassian.net/rest/api/3/issue" auth = HTTPBasicAuth("email@example.com", "<api_token>") headers = { "Accept": "application/json", "Content-Type": "application/json" } payload = json.dumps( { "fields": { "assignee": { "id": "5b109f2e9729b51b54dc274d" }, "components": [ { "id": "10000" } ], "customfield_10000": "09/Jun/19", "customfield_20000": "06/Jul/19 3:25 PM", "customfield_30000": [ "10000", "10002" ], "customfield_40000": { "content": [ { "content": [ { "text": "Occurs on all orders", "type": "text" } ], "type": "paragraph" } ], "type": "doc", "version": 1 }, "customfield_50000": { "content": [ { "content": [ { "text": "Could impact day-to-day work.", "type": "text" } ], "type": "paragraph" } ], "type": "doc", "version": 1 }, "customfield_60000": "jira-software-users", "customfield_70000": [ "jira-administrators", "jira-software-users" ], "customfield_80000": { "value": "red" }, "description": { "content": [ { "content": [ { "text": "Order entry fails when selecting supplier.", "type": "text" } ], "type": "paragraph" } ], "type": "doc", "version": 1 }, "duedate": "2019-05-11", "environment": { "content": [ { "content": [ { "text": "UAT", "type": "text" } ], "type": "paragraph" } ], "type": "doc", "version": 1 }, "fixVersions": [ { "id": "10001" } ], "issuetype": { "id": "10000" }, "labels": [ "bugfix", "blitz_test" ], "parent": { "key": "PROJ-123" }, "priority": { "id": "20000" }, "project": { "id": "10000" }, "reporter": { "id": "5b10a2844c20165700ede21g" }, "security": { "id": "10000" }, "summary": "Main order flow broken", "timetracking": { "originalEstimate": "10", "remainingEstimate": "5" }, "versions": [ { "id": "10000" } ] }, "update": {} } ) response = requests.request( "POST", url, data=payload, headers=headers, auth=auth ) print(json.dumps(json.loads(response.text), sort_keys=True, indent=4, separators=(",", ": ")))
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I'm curious about the date format on the customfield_10000 and customfield_20000 attributes.
The API docs show two formats (one for dates, one for datetime) that include four-digit years separated by dashes. If those custom fields are just text, it might work, but if they're date or datetime fields, I could see it being a problem.
ref: https://developer.atlassian.com/server/jira/platform/jira-rest-api-examples/#datepickerfield
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
The Create Issue example I linked to is far more complicated than it needs to be. Let's ignore all the custom fields for now. My test code only uses the minimum "summary" "project name" and "task type." Most examples I find (from the last few years) show base64 encoding of the api token. The api example I linked to does not. Various questions asked over the years are a mix of old and new methods, headers, etc., none of which I can get to work.
Here's where I'm at now:
auth_hdr = f'Basic {b64_auth}'headers = {"Authorization": auth_hdr,"Content Type": "application/json"}payload = json.dumps( {"fields": {"issuetype": {"id": issue_type_id},"project": {"name": project_name},"summary": summary},"update": {}} )print(f'headers = {headers}\n')print(f'payload = {payload}\n')response = requests.request("POST",url,data=payload,headers=headers)print(response)
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Since you're using Python "requests":
import requests
from requests.auth import HTTPBasicAuth
response_json = request.post(
url,
headers={ "Accept": "application/json" },
auth=HTTPBasicAuth("email@example.com", "<api_token>"),
json={
"fields": {
"issuetype": {
"id": "<issue_type_id>"
},
"project": {
"id": "<project_id>"
},
"summary": "summary"
},
"update": {}
}
).raise_for_status().json()
The HTTPBasicAuth call will do the base64 encoding, etc., so you don't have to do it yourself.
Two things I noticed:
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Thanks again. Good to know the HTTPBasicAuth is sufficient. Not sure where to find project id number. I can only find "name" and "key." In my case they're the same. Yep, all my 'numbers' are strings.
With latest advice, I'm not getting 400 now. It's 401:
<Response [401]>
{"errorMessages":["You do not have permission to create issues in this project."],"errors":{}}
I've always had permission to create issues using the browser, so I'm not sure where or what the obstacle is now.
With so many failed attempts, have I locked myself out?
Is programmatic work item creation available on the Jira Cloud free plan? (I'm still tinkering with fields, schemes, workflows, etc. & haven't invited other users yet)
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
The easiest way I've seen to get the project is to extract it from the URL. This method has been discussed at some length in another community post.
Getting the issue type ID is more explicitly documented.
Once you have those ID values, I suspect the error message will be resolved.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Informative links, thanks!
project_id = "10000" # looks to be the 1st project created
With that in place, still getting the 401.
Maybe the free plan doesn't allow it because some admin roles aren't accessible? See https://www.atlassian.com/software/jira/pricing
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Assuming your API token isn't expired, it should work on the free tier. Double-check the email address and token; if that doesn't work, maybe revoke and recreate a new token.
That code snippet I posted above will raise an HTTPError on a response code >= 400, and I think Atlassian includes an error description in the response body. If you wrap the request in a try/except block, the exception .text attribute will have the response body that you can print or whatnot.
e.g.
try:
request.post(...).raise_for_status()
except RequestException as e:
print(e.text)
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Thanks again! I've added the try/except block & a new token was already on the list of things to do today. Will get new token & run some tests this afternoon when time permits.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
New token, but still the same result:
401 Client Error: Unauthorized for url: https://xxxxxxxxxxxxxxxxxxx.atlassian.net/rest/api/3/issue
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Ugh. All of the tokens I've been creating have scopes, and I add the scopes according the the rest docs. For example, create-issue requires classic scope "write:jira-work" and 5 granular scopes. All were added to my tokens. No luck.
Just now I created a token without scope, and my ticket creation code worked. So now the question is what scopes, classic and/or granular, are actually required?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Since you mention scopes, that's an OAuth term, which doesn't use "Basic" authentication. OAuth is fantastic, but it comes with some complexity.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
When creating tokens, atlassian steers you toward using scopes, mentioning future deprecation of scope-free or something like that.
https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-issues/#api-rest-api-3-issue-post contains the following in their example:
# This code sample uses the 'requests' library:
# http://docs.python-requests.org
import requests
from requests.auth import HTTPBasicAuth
import json
url = "https://your-domain.atlassian.net/rest/api/3/issue"
auth = HTTPBasicAuth("email@example.com", "<api_token>")
headers = { "Accept": "application/json", "Content-Type": "application/json" }
and so on...
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I spent some time over the weekend with Jira DC in my lab, and I couldn't use that API endpoint either. It always complained that I was "unauthorized." At this point, I would contact support and see if they can help.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.