# retoor <retoor@molodetz.nl>
from .._shared import endpoint, field
GROUP = {
"slug": "uploads",
"title": "Uploads",
"intro": """
# Uploads
Attachment storage. Upload a file - or hand the server a public URL to fetch - to receive an
attachment record, then reference its `uid` in an `attachment_uids` field when creating a post,
comment, project, gist, message, or issue - see
[Posts, Comments, Projects, Gists & News](/docs/content.html). Images and videos embed and
play inline once posted; other types render as download links. The record's `is_image` and
`is_video` flags indicate how the file is displayed.
Every endpoint follows the shared [Conventions & Errors](/docs/conventions.html) (auth, content
negotiation, pagination, status codes); see [Authentication](/docs/authentication.html) for the
four ways to sign requests.
""",
"endpoints": [
endpoint(
id="uploads-upload",
method="POST",
path="/uploads/upload",
title="Upload a file",
summary="Store a file and return its attachment record.",
auth="user",
encoding="multipart",
params=[field("file", "form", "file", True, "", "The file to upload.")],
notes=[
"Allowed file types and the size limit are configured by administrators. Images and common video formats (mp4, webm, ogv, mov, m4v) are accepted by default.",
"Returns `201` on success, `413` if too large, `415` if the type is not allowed.",
],
sample_response={
"uid": "ATTACHMENT_UID",
"filename": "clip.mp4",
"url": "/static/uploads/attachments/ab/cd/ATTACHMENT_UID.mp4",
"size": 20480,
"is_image": False,
"is_video": True,
"mime_type": "video/mp4",
},
),
endpoint(
id="uploads-upload-url",
method="POST",
path="/uploads/upload-url",
title="Attach a file from a URL",
summary="Download a public URL on the server and store it as an attachment.",
auth="user",
params=[
field(
"url",
"form",
"string",
True,
"https://example.com/photo.png",
"Public http(s) URL of the file to download and attach.",
),
field(
"filename",
"form",
"string",
False,
"photo.png",
"Optional filename with an allowed extension, used when the URL has no clear name.",
),
],
notes=[
"The server fetches the URL (SSRF-guarded, size-capped) and stores the bytes through the same pipeline as a direct upload; the response is identical to Upload a file.",
"The file type is taken from the URL path or the response Content-Type. Returns `201` on success, `413` if too large, `415` if the type cannot be resolved to an allowed type, `400` for an unreachable or private address.",
],
sample_response={
"uid": "ATTACHMENT_UID",
"filename": "photo.png",
"url": "/static/uploads/attachments/ab/cd/ATTACHMENT_UID.png",
"size": 20480,
"is_image": True,
"is_video": False,
"mime_type": "image/png",
},
),
endpoint(
id="uploads-delete",
method="DELETE",
path="/uploads/delete/{attachment_uid}",
title="Delete an attachment",
summary="Delete an attachment you own; administrators may delete any user's attachment. Soft-deleted (hidden everywhere but restorable; garbage-collected later).",
auth="user",
destructive=True,
params=[
field(
"attachment_uid",
"path",
"string",
True,
"ATTACHMENT_UID",
"UID of the attachment.",
)
],
sample_response={"status": "deleted"},
),
],
}