Simulators
Issue attachments
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:
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.