Reserve an attachment and get a presigned upload URL
const url = 'https://api.aetherplatform.cloud/api/v1/organizations/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/tickets/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/attachments';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"filename":"example","content_type":"example","size_bytes":1}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://api.aetherplatform.cloud/api/v1/organizations/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/tickets/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/attachments \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "filename": "example", "content_type": "example", "size_bytes": 1 }'Reserves a pending attachment slot on the ticket and returns a short-lived presigned PUT URL. The client uploads the file bytes directly to object storage (MinIO/S3) at upload_url with a matching Content-Type; the API never proxies the bytes. The upload is then confirmed by referencing the returned attachment_id in attachment_ids on a subsequent message (see the message endpoint) — that flips the row to attached inside the message transaction. Server-side limits: content_type must be on the allowlist (images, pdf, text, json, yaml, gzip, tar) and size_bytes in (0, 26214400] (25 MiB). Returns 503 when attachment storage is not configured (MINIO_ENDPOINT unset).
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”Organization UUID.
Support ticket UUID.
Request Bodyrequired
Section titled “Request Bodyrequired”object
Must be on the server allowlist (images, application/pdf, text/plain, application/json, yaml, gzip, tar). Other types are rejected (422).
File size in bytes; must be in (0, 26214400] (25 MiB).
Examplegenerated
{ "filename": "example", "content_type": "example", "size_bytes": 1}Responses
Section titled “Responses”Attachment reserved; upload URL issued.
object
Reference this id in a message’s attachment_ids to confirm the upload.
Short-lived presigned PUT URL; upload bytes directly here with the matching Content-Type.
Examplegenerated
{ "attachment_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "upload_url": "https://example.com"}Malformed request — e.g. an invalid path UUID or an unparseable JSON body.
object
object
A stable, machine-readable error code.
object
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": [ { "field": "example", "code": "example", "message": "example" } ] }}Missing or invalid credentials.
object
object
A stable, machine-readable error code.
object
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": [ { "field": "example", "code": "example", "message": "example" } ] }}The requested resource was not found.
object
object
A stable, machine-readable error code.
object
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": [ { "field": "example", "code": "example", "message": "example" } ] }}Request validation failed.
object
object
A stable, machine-readable error code.
object
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": [ { "field": "example", "code": "example", "message": "example" } ] }}Attachment storage is not configured.