Skip to content
Help Center home
InboxAsk a human

How to display and upload attachments in a headless support portal

Attachments in a headless portal built on Plain's GraphQL API need two mutations: createAttachmentDownloadUrl to display existing attachments and createAttachmentUploadUrl to upload new files.

Display attachments from the timeline

When you query timelineEntries, message entries such as ChatEntry, EmailEntry, SlackMessageEntry and NoteEntry include an attachments field. Each attachment has an id, fileName, fileExtension, fileMimeType and fileSize.

To get a renderable URL, call createAttachmentDownloadUrl.

  • Input: { attachmentId: ID! }
  • Returns: attachmentDownloadUrl.downloadUrl, a signed URL that expires after 3 minutes. Fetch it on demand and do not cache it.
  • Required API key permission: attachment:download

    The response also includes attachmentVirusScanResult. If it is INFECTED or FAILED, do not render the file. null means virus scanning is not configured for the workspace.

    For images, use the downloadUrl as the src. For other file types, render a download link.

Upload files from customers

createAttachmentUploadUrl needs the attachment:create API key permission.

  1. Call createAttachmentUploadUrl to receive an uploadFormUrl and a list of uploadFormData key-value pairs.
  2. POST the file as multipart/form-data to the uploadFormUrl. Add all uploadFormData pairs as form fields first, then the file as the last field.
  3. A successful upload returns HTTP 204.
  4. Use the returned attachment.id in your replyToThread or createThread mutation.

    Upload URLs are valid for 2 hours. Attachments uploaded but never referenced in a message are deleted after 24 hours.