Forums

Articles
Create
cancel
Showing results for 
Search instead for 
Did you mean: 

How To Troubleshoot REST API "Bad Request"

Dave Puryear May 12, 2025

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.

https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-issues/#api-rest-api-3-issue-post

https://community.atlassian.com/forums/Jira-questions/how-to-login-jira-cloud-with-python-rest-api-without-importing/qaq-p/1070920

Thank you for any assistance.

1 answer

0 votes
Jim Knepley - ReleaseTEAM
Atlassian Partner
May 12, 2025

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.

Dave Puryear May 12, 2025

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=(",", ": ")))

 

Jim Knepley - ReleaseTEAM
Atlassian Partner
May 12, 2025

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

Dave Puryear May 12, 2025

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)
Jim Knepley - ReleaseTEAM
Atlassian Partner
May 13, 2025

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:

  • The issuetype.id field should be a quoted string of the numeric issue type ID, not a literal number.
  • The project.name field in your example is not valid, it should be project.id, also a quoted string of the project ID number.

ref: https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-issues/#api-rest-api-3-issue-post

Dave Puryear May 13, 2025

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)


Jim Knepley - ReleaseTEAM
Atlassian Partner
May 13, 2025

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.

Dave Puryear May 13, 2025

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

Jim Knepley - ReleaseTEAM
Atlassian Partner
May 14, 2025

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)
Dave Puryear May 14, 2025

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.

Dave Puryear May 14, 2025

New token, but still the same result:

401 Client Error: Unauthorized for url: https://xxxxxxxxxxxxxxxxxxx.atlassian.net/rest/api/3/issue

Dave Puryear May 14, 2025

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?

Jim Knepley - ReleaseTEAM
Atlassian Partner
May 14, 2025

Since you mention scopes, that's an OAuth term, which doesn't use "Basic" authentication. OAuth is fantastic, but it comes with some complexity.

Dave Puryear May 14, 2025

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...

Jim Knepley - ReleaseTEAM
Atlassian Partner
May 19, 2025

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.

Like Dave Puryear likes this

Suggest an answer

Log in or Sign up to answer
DEPLOYMENT TYPE
CLOUD
PRODUCT PLAN
FREE
TAGS
AUG Leaders

Atlassian Community Events