Attachments
This document describes how to upload attachments using the Glue API. The process involves three main steps:
Get an upload ticket - Request a signed URL for uploading
Upload the file - Upload the file content to the signed URL
Create a file object - Register the uploaded file in the system
Use the file - Attach the file to messages or other objects
Overview
Files in Glue are uploaded directly to cloud storage using presigned URLs. The process ensures that only authorized users can upload files and that file integrity is maintained.
API Endpoints
1. Get Upload Ticket
Mutation: uploadTicket
Request a signed URL for uploading a file. This endpoint validates file metadata and returns either an existing file (if the same content was already uploaded) or a new upload ticket.
mutation UploadTicket($input: UploadTicketInput!) {
uploadTicket(input: $input) {
... on File {
id
name
}
... on UploadTicket {
id
url
headers {
name
value
}
formData {
name
value
}
}
}
}
Input Parameters:
name
String
Yes
The filename
contentLength
String
Yes
File size in bytes
contentMD5
String
Yes
Base64-encoded MD5 hash of the file content
contentType
String
Yes
MIME type of the file
metadata
UploadMetadata
No
Additional metadata (width/height for images)
UploadMetadata:
input UploadMetadata {
width: Int
height: Int
}
Response Types:
The uploadTicket
mutation returns a union type UploadTicketResponse
that can be either:
Existing File Response
If a file with the same MD5 hash already exists in the system, the API returns a complete File
object. In this case there is no need to re-upload the file and the file ID can be used immediately as an attachment ID for sending a message.
{
"uploadTicket": {
"__typename": "File",
"id": "fil_1h3c43PfmSQpPb0CXwRJUYs0ker",
"name": "document.pdf",
}
}
New Upload Ticket Response
If the file content is new, the API returns an UploadTicket
object with upload instructions:
{
"uploadTicket": {
"__typename": "UploadTicket",
"id": "upl_2k4m56QgnTRqQc1DXxSKVZt1ler",
"url": "https://storage.glue.com/upload/presigned-url",
"headers": [
{ "name": "Content-Type", "value": "application/pdf" },
{ "name": "x-amz-acl", "value": "private" }
],
"formData": null
}
}
2. Upload File Content
Once you have an UploadTicket
, upload the file content to the provided URL. If FormData is absent then you will nee to perform a PUT request to the specified URL. If FormData is present, then you will need to make a multipart/form-data
POST request to the specified URL. In both cases you will need to supply the headers returned in the UploadTicket
.
For PUT requests (no FormData):
// Upload using PUT
await fetch(uploadTicket.url, {
method: "PUT",
headers: uploadTicket.headers.reduce((acc, header) => {
acc[header.name] = header.value;
return acc;
}, {}),
body: fileBuffer,
});
For POST requests (when formData is provided):
The FormData
array may contain multiple entries that should be used to supply the form data for the POST. One entry will contain a value of @file
which needs to be substituted for for the actual file content. The Content-Type will be multipart/form-data
in order to accommodate the file data. Read more about multipart form data here.
// Upload using POST with form data
const formData = new FormData();
uploadTicket.formData.forEach(({ name, value }) => {
if (value === "@file") {
formData.append(name, fileBuffer, {
contentType: contentType,
filename: filename,
});
} else {
formData.append(name, value);
}
});
await fetch(uploadTicket.url, {
method: "POST",
headers: uploadTicket.headers.reduce((acc, header) => {
acc[header.name] = header.value;
return acc;
}, {}),
body: formData,
});
3. Create File Object
After successful upload, create a file object in the system.
Mutation: createFile
mutation CreateFile($input: CreateFileInput!) {
createFile(input: $input) {
id
name
}
}
Input Parameters:
uploadTicketID
String
Yes
The ID from the upload ticket
File Metadata
For images and videos, provide the following metadata which will be used to the client to show an appropriately size preview of the file before it is loaded.
type FileMetadata {
width: Int # Image/video width in pixels
height: Int # Image/video height in pixels
blurHash: String # Blur hash for image previews
}
Key Points:
Always check
__typename
- The response can be eitherFile
orUploadTicket
Existing files are immediate - No upload step needed, file is ready to use
New files require upload - Must upload content then call
createFile
Using Files in Messages
Once you have a file object, you can attach it to messages:
mutation SendMessage($input: MessageInput!) {
sendMessage(input: $input) {
id
text
attachments {
... on File {
id
name
url
fileType
contentType
}
}
}
}
Message Input:
input MessageInput {
text: String!
attachments: [ID!]! # Array of file IDs
quotedMessageID: ID
}
File Object Properties
type File implements Node {
id: ID! # Unique file identifier
fileType: FileType! # Type classification
name: String! # Original filename
contentLength: String! # File size in bytes
contentMD5: String! # MD5 hash for integrity
contentType: String! # MIME type
metadata: FileMetadata # Additional metadata
previewable: Boolean # Whether file can be previewed
url: String! # Download URL
}
Last updated
Was this helpful?