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:

  1. The client computes a SHA-256 hash of the file content before upload
  2. The hash is sent as x-amz-checksum-sha256 header during the S3 PUT
  3. On upload confirmation, the hash is stored in the database for auditing
  4. 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:

NameTypeRequiredDescription
entityTypestringYesEntity type (e.g., “item”, “action”, “problem_sheet”)
entityIdstringYesEntity 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:

NameTypeRequiredDescription
idstringYesAny 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:

NameTypeRequiredDescription
filenamestringYesOriginal filename
mimeTypestringYesMIME type of the file
sizeBytesnumberYesFile size in bytes
entityTypestringYesTarget entity type
entityIdstringYesTarget 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:

NameTypeRequiredDescription
entityTypestringYesEntity type
entityIdstringYesEntity ID
filenamestringYesOriginal filename
mimeTypestringYesMIME type
sizeBytesnumberYesFile size in bytes
s3KeystringYesS3 object key (from upload-url response)
s3BucketstringYesS3 bucket name
sha256stringNoSHA-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:

NameTypeRequiredDescription
idstringYesThe 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/pdf
  • image/png, image/jpeg, image/gif, image/webp
  • application/vnd.openxmlformats-officedocument.* (Office documents)
  • text/csv, text/plain

Error Codes

CodeDescription
400Invalid MIME type or file size
401Missing or invalid authentication
403Only the uploader can delete their own files
404File attachment not found in this organization