---
# System prepended metadata

title: TMA document upload flow

---

# TMA document upload flow

## 1. Allow the user to upload a file using a file input
The file input `File.type` will have the content type of the file that the user uploaded. This will be needed for validation for the next step.

Max file size of 10 MiB

Allowed file types: .avif, .bmp, .doc, .docx, .gif, .jpg, .jpeg, .pdf, .png, .tif, .tiff, .webp

## 2. Get a signed URL and form data fields from the API
Using this API
```graphql
mutation CreateDocumentUploadUri($input: CreateDocumentUploadUriInput!) {
  createDocumentUploadUri(input: $input) {
    fields
    path
    uri
  }
}
```

with this `$input`:
```json
{
  "contentType": file.type, // From file that the user uploaded
  "userId": "user-123"
}
```

there will be this response:
```json
{
  "data": {
    "createDocumentUploadUri": {
      "fields": {
        "bucket": "...",
        "key": "...",
        "etc": "..."
      },
      "path": "tm/user-123/document-456.pdf",
      "uri": "https://..."
    }
  }
}
```

## 3. Upload the file that the user uploaded to the signed URL
Simple example in plain JavaScript
```js
// Create the form to POST
const formData = new FormData();
Object.keys(createDocumentUploadUri.fields).forEach(fieldName => {
  formData.append(fieldName, fields[fieldName]);
});
formData.append('Content-Type', file.type);
formData.append('file', file); // This MUST come last

// POST the form
const response = await fetch(createDocumentUploadUri.uri, {
  method: 'POST',
  body: formData,
});
```

## 4. Call the provide document API with the `path` from above
```graphql
mutation ProvideDocument($input: ProvideDocumentInput!) {
  provideDocument(input: $input) {
    document {
      id
    }
  }
}
```
