File Upload Flow
Attaching a file to a document is a 4-step process:
- Get a pre-signed URL — Request a temporary upload URL from the server
- Upload the file to S3 — PUT the file directly to the pre-signed URL
- Register the file — Call
UploadFilemutation to create aFilerecord - Attach to a document — Pass the file ID when creating/updating a document
Step 1: Get a pre-signed URL
POST https://api.erplain.app/vapor/signed-storage-url
Authorization: Bearer {token}Response:
{
"uuid": "e0fce13b-368f-4e93-8ebb-a7c7a357118a",
"bucket": "erplain-production-files",
"key": "tmp/e0fce13b-368f-4e93-8ebb-a7c7a357118a",
"url": "https://erplain-production-files.s3.eu-west-3.amazonaws.com/tmp/e0fce13b-368f-4e93-8ebb-a7c7a357118a?x-amz-acl=private&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Security-Token=IQoJb3JpZ2luX2Vj...&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ASIAYCJYY36A6TLOM3VH%2F20260622%2Feu-west-3%2Fs3%2Faws4_request&X-Amz-Date=20260622T152040Z&X-Amz-SignedHeaders=host%3Bx-amz-acl&X-Amz-Expires=300&X-Amz-Signature=c728702e07c332ff209749b404b04800e80b01b56c7bbb2f1a0fe50b888b660b",
"headers": {
"Host": ["erplain-production-files.s3.eu-west-3.amazonaws.com"],
"x-amz-acl": ["private"],
"Content-Type": "application/octet-stream"
}
}Save the uuid, bucket, and key — you will need them in step 3.
Step 2: Upload the file to S3
Use the url from step 1 to upload the file directly to S3 via a PUT request. Include the headers returned in step 1:
PUT https://erplain-production-files.s3.eu-west-3.amazonaws.com/tmp/e0fce13b-368f-4e93-8ebb-a7c7a357118a?x-amz-acl=private&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Security-Token=...&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=...&X-Amz-Date=20260622T152040Z&X-Amz-SignedHeaders=host%3Bx-amz-acl&X-Amz-Expires=300&X-Amz-Signature=...
x-amz-acl: private
Content-Type: application/pdf
{raw file bytes}Response:
HTTP/1.1 200 OK
x-amz-server-side-encryption: AES256A 200 OK response means the file was uploaded successfully. You can now proceed to step 3.
Step 3: Register the file via GraphQL
Once the file is in S3, call UploadFile to create a permanent File record. Pass the uuid, bucket, and key from step 1 in the TmpBucketFileInput:
mutation UploadFile($file: TmpBucketFileInput!, $type: DocumentFile!) {
UploadFile(file: $file, type: $type) {
id
label
mime
size
public_path
}
}{
"file": {
"uuid": "e0fce13b-368f-4e93-8ebb-a7c7a357118a",
"bucket": "erplain-production-files",
"key": "tmp/e0fce13b-368f-4e93-8ebb-a7c7a357118a",
"name": "bon-de-livraison.pdf",
"content_type": "application/pdf"
},
"type": "documentFile"
}→ Returns a File object with its id. Save this ID for step 4.
Step 4: Attach to a document
When creating or updating a document, pass the file's id in the files array:
mutation UpdateShippingOrder($id: ID!, $input: ShippingOrderInput!) {
UpdateShippingOrder(id: $id, input: $input) {
id
files { id label mime size }
}
}{
"id": 123,
"input": {
"files": [{ "id": 100003 }]
}
}To remove a file from a document, omit it from the files array. Only the files included in the array will remain attached.
File data type
Returned when querying files on any document type:
| Field | Type | Description |
|---|---|---|
id | ID | Unique identifier |
label | String | Original filename |
type | String | File type category |
mime | String | MIME type (e.g. application/pdf) |
size | Int | File size in bytes |
created_at | DateTime | Upload timestamp |
expires_at | Date | Expiration date (null for permanent files) |
public_path | String | Temporary download URL (valid 5 minutes) |
path | String | S3 storage path |
UploadFile
Upload a file to the system
Parameters
| file - TmpBucketFileInput |
|---|
| File data to upload |
| type - DocumentFile |
|---|
| Type of document file (documentFile) |
mutation UploadFile($file: TmpBucketFileInput!, $type: DocumentFile!) {
UploadFile(file: $file, type: $type) {
id
label
type
created_at
size
mime
public_path
}
}{
"file": {
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"bucket": "erplain-production-files",
"key": "tmp/550e8400-e29b-41d4-a716-446655440000",
"name": "invoice_2025_001.pdf",
"content_type": "application/pdf"
},
"type": "documentFile"
}{
"data": {
"UploadFile": {
"id": 268796,
"label": "mon-logo.png",
"mime": "image/png",
"size": 10562
}
}
}TmpBucketFileInput data type
| uuid - String |
|---|
| Unique identifier for the file upload |
| bucket - String |
|---|
| Bucket name for temporary storage |
| key - String |
|---|
| Key/path of the file in the bucket |
| name - String |
|---|
| Original filename |
| content_type - String |
|---|
| MIME type of the file |
| max_size - Int |
|---|
| Maximum allowed file size in bytes |
DocumentFile enum
| Value | Description |
|---|---|
| documentFile | Document file type |
FileInput data type
| id - ID |
|---|
| File identifier |
ImageStyle enum
| Value | Description |
|---|---|
| pdfLogo | Logo for PDF documents |
| productThumbnail | Small thumbnail for products |
| productSmall | Small product image |
| productMedium | Medium product image |
| productLarge | Large product image |
Accepted MIME types
The following MIME types are accepted for file uploads:
| Category | MIME types |
|---|---|
| Images | image/jpeg, image/png, image/gif, image/webp |
| Documents | application/pdf, application/msword, application/vnd.openxmlformats-officedocument.wordprocessingml.document |
| Spreadsheets | application/vnd.ms-excel, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet |
| Presentations | application/vnd.ms-powerpoint, application/vnd.openxmlformats-officedocument.presentationml.presentation |
| Text | text/csv, text/plain |
Maximum file size: 5 MB.
