Upload a file (multipart, "file" field, ≤15MB)
multipart/form-data upload to R2. Any linked issue (directly via issueId, or via the target comment's issue) must belong to the caller's org (else 404). 400 when the file is missing or larger than ~15MB; 501 when storage is not configured. Returns 200 (not 201).
View as MarkdownAuthorization
bearer In: header
Request Body
multipart/form-data
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/v1/attachments" \ -F file="string"{ "attachment": { "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "url": "string", "filename": "string", "contentType": "string", "rendersInline": true, "size": 0, "created": "2019-08-24T14:15:22Z" }}List an issue's attachments
Newest first. Each url is GET /v1/attachments/{id}/content, which serves the bytes to a caller with a session.
Delete an attachment and its stored file
Authenticated and org-scoped: holding the link must not be enough to destroy the file. Removes the object from storage inline, so the file stops being served at once. Reach follows the parent — the attachment's issue, or its comment's issue — so an attachment outside the caller's workspace answers 404, never 403. So does one already deleted, which makes a repeated delete idempotent, and one whose parent is already gone: there is no workspace left to authorize it, and a background sweeper reclaims those. 200 even when storage refuses the delete: the attachment has left every view the caller can see, and the row stays marked so the sweeper finishes the file. 501 when storage is not configured, since marking the row would hide the only record of a file that could never be removed.