# Issue attachments

Upload files to an issue as Jira's multipart form does, download them through a signed redirect and delete them.

An attachment is a file on an issue, uploaded as a multipart form and downloaded through a redirect. On the default scenario, read the upload limit, upload a file to an issue, read it back and delete it:

```bash
curl -s "$RYSTIC_URL/rest/api/3/attachment/meta" -u me@example.com:token | jq -c .
# -> {"enabled":true,"uploadLimit":10485760}
printf 'Release notes draft\n' | curl -s "$RYSTIC_URL/rest/api/3/issue/PLAT-1/attachments" -u me@example.com:token -F 'file=@-;filename=notes.txt;type=text/plain'
# -> XSRF check failed
printf 'Release notes draft\n' | curl -s "$RYSTIC_URL/rest/api/3/issue/PLAT-1/attachments" -u me@example.com:token -H 'X-Atlassian-Token: no-check' -F 'file=@-;filename=notes.txt;type=text/plain' | jq -c '.[0] | {id, filename, size, mimeType}'
# -> {"id":"14003","filename":"notes.txt","size":20,"mimeType":"text/plain"}
curl -sL "$RYSTIC_URL/rest/api/3/attachment/content/14003" -u me@example.com:token
# -> Release notes draft
curl -s "$RYSTIC_URL/rest/api/3/issue/PLAT-1?fields=attachment" -u me@example.com:token | jq -c '[.fields.attachment[].filename]'
# -> ["notes.txt"]
curl -s -o /dev/null -w '%{http_code}\n' -X DELETE "$RYSTIC_URL/rest/api/3/attachment/14003" -u me@example.com:token
# -> 204
```

### Uploading

`POST /rest/api/3/issue/{issueIdOrKey}/attachments` takes a multipart form whose `file` parts become attachments, one record each, and answers the list of records it made. Like Jira, it refuses a request without `X-Atlassian-Token: no-check` with 404 `XSRF check failed`, and an upload to an issue that does not exist with 404. A record carries `filename`, `size`, `mimeType`, an `author` (the account every request acts as) and `created` from the simulator's clock. `GET /rest/api/3/attachment/meta` reports whether uploads are enabled and the limit in bytes.

### Downloading

`GET /rest/api/3/attachment/content/{id}` answers 303 with a signed link under `/_rystic/files/`, and following it returns the bytes you uploaded; pass `-L` to curl or let your client follow redirects. `GET /rest/api/3/attachment/{id}` reads the record and `DELETE` on it removes the file from the issue.

A seeded attachment, such as the two `jira_sprint_board` holds, lists its filename and size but has no bytes: its content link redirects back to itself.

---

Source: https://www.rystic.ai/docs/simulators/jira/features/attachments · Markdown: https://www.rystic.ai/docs/simulators/jira/features/attachments.md
