Come for the products,
stay for the community

The Atlassian Community can help you and your team get more value out of Atlassian products and practices.

Atlassian Community about banner
Community Members
Community Events
Community Groups

Jira REST file attachment with Powershell

I'm trying to add an attachment when creating a ticket. My code works great to open a parent ticket and than passing the parent ID to create subtasks, but if I try to add an attachment all hell breaks lose. 

I've seen a few examples trying to add it after the ticket is created, but why not adding it when creating the ticket?

Below is an example of the request and the body. You can sub based on your requirements, but the basic concept is there, plus the important questions, how do I get the something.html attach to the ticket? 


[String] $Body = '{"fields":{"project":{"id":"'+$projectId+'"},"parent":{"id":"'+$parentIssueID+'"}, "issuetype":{"name":"'+$subIssueType+'"},"components":[{"name":"'+$components+'"}], "summary":"'+$summary+'","description":"'+$description+'","attachment": [{"name":"'+$attachment+'"}],"duedate": "'+$duedate+'", "priority":{"name":"'+$priority+'"}}}';


try {

$b64 = ConvertTo-Base64($username + “:” + $password);

$auth = “Basic ” + $b64;

$webRequest = [System.Net.WebRequest]::Create(")

$webRequest.ContentType = “application/json”

$BodyStr = [System.Text.Encoding]::UTF8.GetBytes($Body)

$webrequest.ContentLength = $BodyStr.Length

$webRequest.ServicePoint.Expect100Continue = $false

$webRequest.Headers.Add(“Authorization”, $auth);

$webRequest.PreAuthenticate = $true

$webRequest.Method = “POST”

$requestStream = $webRequest.GetRequestStream()

$requestStream.Write($BodyStr, 0, $BodyStr.length)


[System.Net.WebResponse] $resp = $webRequest.GetResponse()

$rs = $resp.GetResponseStream()

[System.IO.StreamReader] $sr = New-Object System.IO.StreamReader -argumentList $rs

[string] $jsonResults = $sr.ReadToEnd()



catch [System.Net.WebException]{

if ($_.Exception -ne $null -and $_.Exception.Response -ne $null) {

$errorResult = $_.Exception.Response.GetResponseStream()

$errorText = (New-Object System.IO.StreamReader($errorResult)).ReadToEnd()

Write-Warning “The remote server response: $errorText”

Write-Output $_.Exception.Response.StatusCode

} else {

throw $_




Any help will be greatly appreciated!!! smile 

3 answers

Comments for this post are closed

Community moderators have prevented the ability to post new answers.

Post a new question

Jason has the answer here:

A post I made on this a bit ago:


Lastly, for all the other googlers out there that may research this in the future, this is how I got this to work for me after editing the code from Jason.


function Upload-JiraCSV($jiraTicket, $filepath)
$wc = new-object System.Net.WebClient
$wc.Headers.Add("Authorization", $headers.Authorization)
$wc.Headers.Add("X-Atlassian-Token", "nocheck") 
$wc.UploadFile("$URIPath/issue/$jiraTicket/attachments", $filepath)

This is modified from something I found recently.  I have a global variable named $httpheader that includes the authorization code which this strips part of the info out to add to the webclient object.


function Add-Attachment

# Test for filename existence
$result = Test-Path $Filename
if (!($result)) {return $false, "File not found"}
$wc = new-object System.Net.WebClient
$authorizationcode = $httpheader["Authorization"]
$wc.Headers.Add("Authorization", $authorizationcode)
$wc.Headers.Add("X-Atlassian-Token", "nocheck")
$result = $false
$ErrorActionPreference = "SilentlyContinue"
$result = $wc.UploadFile("https://ourinstance/rest/api/latest/issue/$JIRAIssue/attachments", $(Resolve-Path $filename))
$ErrorActionPreference = "Continue"
if (!($result)) {return $false, "File upload failed"}
return $true


Now when I create an issue, I generate one using a POST to /rest/api/latest/issue with the absolute bare minimum of fields needed to generate it, then populate the other fields one by one.  While that generates more spam, I learned that whenever I try to create an issue with a large number of fields populated as part of the issue generation, there was a far greater chance of a single missing piece of data blowing up my issue create process. So rather than do it all at once, I'll:

$newissue = create-issue -project blah -summary blah -reporter blah and 2 or 3 other fields


Transition-Status (if a status other than the default origination status is appropriate)

Set-blahblahfield (such as story points, assignee, etc.)



I can walk you through those, if that's of any benefit; It's a slightly different approach, but the crux is that I'm all Powershell on that part vs. .Net (I think.)

Mike, did you solve this?  Alternatively, there are easier ways to create JIRA issues with Powershell, I can share code if it does any good.

Hi Lee, I got something working, but I'm always open to improve and try a different approach. If you don't mind, yes I could use a fresh new idea.

Comments for this post are closed

Community moderators have prevented the ability to post new answers.

Post a new question

Community showcase
Published in Apps & Integrations

4 Amazing Product and Project Management Apps compete for Best App Demo in July Appy Hours 🥳

Thanks so much to everyone who joined for our July Appy Hours! Product and project management presenter highlights  Checkout - Procurement and asset manager, presented by @Vincent Mutambuki ...

86 views 1 8
Read article

Atlassian Community Events