Files API
Versioned file attachments with S3 presigned URLs, SHA-256 integrity verification, and version history.
Files API
ProBeya provides a versioned document management system for file attachments on any entity (items, actions, problem sheets, etc.). Files are stored in S3-compatible storage (MinIO for development, any S3 for production); this API manages metadata records and generates presigned URLs for secure upload and download.
Versioning Model
Each file maintains a version chain where only the latest version is shown by default:
v1 (isLatest: false) --> v2 (isLatest: false) --> v3 (isLatest: true)
- Uploading a new version automatically marks the previous version as non-latest
- Full version history is available via
getVersionHistory - Previous versions can be restored, creating a new version entry
SHA-256 Integrity
For regulated environments, ProBeya supports end-to-end file integrity verification:
- The client computes a SHA-256 hash of the file content before upload
- The hash is sent as
x-amz-checksum-sha256header during the S3 PUT - On upload confirmation, the hash is stored in the database for auditing
- Downstream processes can verify file integrity against the stored hash
Endpoints
GET /api/v1/files
List the latest version of all file attachments for a specific entity.
tRPC: fileAttachments.listForEntity
Auth: Bearer token required (scope: read:items) or session cookie
Org context: Required
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
entityType | string | Yes | Entity type (e.g., “item”, “action”, “problem_sheet”) |
entityId | string | Yes | Entity ID |
Response:
{
"data": [
{
"id": "clx9fa001",
"entityType": "item",
"entityId": "clx9it001",
"filename": "deviation-report-2847.pdf",
"mimeType": "application/pdf",
"sizeBytes": 245760,
"version": 2,
"isLatest": true,
"createdAt": "2026-04-01T14:00:00.000Z",
"uploadedBy": {
"id": "clx9us003",
"name": "Jane Doe",
"image": "https://cdn.probeya.com/avatars/jane.jpg"
}
}
]
}
GET /api/v1/files/:id/versions
List all versions of a file chain ordered by version number descending.
tRPC: fileAttachments.getVersionHistory
Auth: Bearer token required (scope: read:items) or session cookie
Org context: Required
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Any file ID in the version chain |
Response:
{
"data": [
{ "id": "clx9fa003", "version": 3, "isLatest": true, "filename": "report-v3.pdf" },
{ "id": "clx9fa002", "version": 2, "isLatest": false, "filename": "report-v2.pdf" },
{ "id": "clx9fa001", "version": 1, "isLatest": false, "filename": "report-v1.pdf" }
]
}
POST /api/v1/files/upload-url
Generate a presigned PUT URL for direct-to-S3 upload. The client uploads the file directly to S3 using this URL, then confirms the upload via the upload endpoint.
tRPC: fileAttachments.getUploadUrl
Auth: Bearer token required (scope: write:items) or session cookie
Org context: Required
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
filename | string | Yes | Original filename |
mimeType | string | Yes | MIME type of the file |
sizeBytes | number | Yes | File size in bytes |
entityType | string | Yes | Target entity type |
entityId | string | Yes | Target entity ID |
Response:
{
"uploadUrl": "https://s3.amazonaws.com/probeya-uploads/...",
"s3Key": "attachments/clx9org/clx9it001/abc123.pdf",
"s3Bucket": "probeya-uploads",
"expiresIn": 3600
}
POST /api/v1/files
Record a new file attachment after the S3 upload completes. This confirms the upload and creates the metadata record.
tRPC: fileAttachments.upload
Auth: Bearer token required (scope: write:items) or session cookie
Org context: Required
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
entityType | string | Yes | Entity type |
entityId | string | Yes | Entity ID |
filename | string | Yes | Original filename |
mimeType | string | Yes | MIME type |
sizeBytes | number | Yes | File size in bytes |
s3Key | string | Yes | S3 object key (from upload-url response) |
s3Bucket | string | Yes | S3 bucket name |
sha256 | string | No | SHA-256 hash for integrity verification |
POST /api/v1/files/:id/new-version
Upload a new version of an existing file. Marks the current version as non-latest and creates a new version entry.
tRPC: fileAttachments.uploadNewVersion
Auth: Bearer token required (scope: write:items) or session cookie
Org context: Required
GET /api/v1/files/:id/download
Generate a presigned GET URL for downloading or previewing a file.
tRPC: fileAttachments.getDownloadUrl
Auth: Bearer token required (scope: read:items) or session cookie
Org context: Required
Response:
{
"downloadUrl": "https://s3.amazonaws.com/probeya-uploads/...?X-Amz-Signature=...",
"filename": "deviation-report-2847.pdf",
"mimeType": "application/pdf",
"expiresIn": 3600
}
DELETE /api/v1/files/:id
Hard-delete a file attachment. Only the uploader can delete their own files.
tRPC: fileAttachments.delete
Auth: Bearer token required (scope: write:items) or session cookie
Org context: Required
POST /api/v1/files/:id/restore
Restore a previous version as the new current version. Creates a new version entry by copying the S3 object.
tRPC: fileAttachments.restoreVersion
Auth: Bearer token required (scope: write:items) or session cookie
Org context: Required
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Yes | The version ID to restore |
Allowed MIME Types
File uploads are restricted to safe MIME types. The full list is defined in @probeya/shared as ALLOWED_MIME_TYPES. Common allowed types include:
application/pdfimage/png,image/jpeg,image/gif,image/webpapplication/vnd.openxmlformats-officedocument.*(Office documents)text/csv,text/plain
Error Codes
| Code | Description |
|---|---|
| 400 | Invalid MIME type or file size |
| 401 | Missing or invalid authentication |
| 403 | Only the uploader can delete their own files |
| 404 | File attachment not found in this organization |
Was this page helpful?