Skip to main content

Sending a file

Operations that take a File are sent as multipart/form-data following the GraphQL multipart request spec. The server accepts this format natively. The request body has three kinds of fields:
  1. operations: a JSON string of the normal { query, variables } payload, with null in place of each file.
  2. map: a JSON string mapping each file field name to the dotted path(s) in operations it should fill, for example { "0": ["variables.file"] }.
  3. One form field per file, named as in map.
The server rejects a multipart body without an operations field, and requires both operations and map to be JSON strings. Client libraries that implement the spec (for example apollo-upload-client for Apollo) produce this format automatically when a variable holds a File or Blob; plain JSON is used when no variable holds a file. Operations that accept a File include uploadChemicalSds, uploadEquipmentManual, uploadUserAvatar, uploadUserDocument, uploadIbcMeetingDocument, uploadMarkdownImage, processChemicalLabel, parseWasteManifest (a list of files) and CreateIncidentInput.photos. The reference lists every field typed File.

Validation

Every upload is validated before it is stored. A failed check is returned as a GraphQL error with extensions.code set as shown. Each operation validates against one of five contexts:
image/png, image/jpeg, image/gif, image/webp. Used for incident photos.
application/pdf.
application/pdf, application/msword, application/vnd.openxmlformats-officedocument.wordprocessingml.document, application/x-iwork-pages-sffpages, image/png, image/jpeg.
image/png, image/jpeg, image/gif, image/webp, video/mp4, video/webm. Used for the images and videos embedded in protocol steps.
application/pdf, application/vnd.openxmlformats-officedocument.wordprocessingml.document, video/mp4, video/quicktime, video/webm, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.apple.numbers, text/csv.
The MIME check uses the type the browser reports for the file. A file with the right extension but an empty or unexpected type is rejected with a message listing the types the context expects.

Reading a file back

Every uploaded file is identified by an opaque key that the API returns as a string. Incident.photos, for example, is declared as [File!]! on output as well as input, and on output it lists the keys of the incident’s photos. Treat keys as identifiers: their format is not part of the API and may change. A file is read back from GET /files/<key> on the app host, using the same authentication as the API: PNG, JPEG, GIF, WebP, PDF, MP4 and QuickTime files are served inline; every other type is served as a download. The same pattern applies to every file the API hands back by key, such as protocol files and embedded images.