//health (SQL Server connectivity)Standard JWT Bearer token authentication:
Authorization: Bearer <access_token>
Token validation:
- Signing: Symmetric key from AUTH__SIGNING_KEY environment variable
- Lifetime: Validated
- Issuer/Audience: Not validated
Persona-based access control applied to all endpoints:
- Personas: DirectSupplyPartner, Customer
- Facility Authorization: Per-request facility-level access validation via FacilityAuthorizationService
Route Prefix: /files
API Version: v1
Authorization: JWT Bearer + Custom (DirectSupplyPartner | Customer)
| Method | Path | Description |
|---|---|---|
| POST | /files |
Upload file with metadata |
| GET | /files/{fileId} |
Download file |
| GET | /files/{fileId}/metadata |
Get file metadata |
| PUT | /files/{fileId}/metadata |
Update file metadata (full) |
| PATCH | /files/{fileId}/metadata |
Update file metadata (partial) |
| DELETE | /files/{fileId} |
Delete file (soft delete) |
| GET | /files/facilities/{facilityId}/metadata |
Search file metadata |
/filesUpload a file with metadata.
Content-Type: multipart/form-data
Request:
- file (IFormFile, required) — The file content
- metadata (FileUploadMetadata, required) — File metadata
FileUploadMetadata:
{
"fileId": "guid (optional, auto-generated if omitted)",
"facilityId": 12345,
"fileGroupId": 1,
"fileDate": "2026-03-11",
"enabledForDocumentation": true,
"externalReferences": [
{
"domain": "Tasks",
"type": "WorkOrder",
"identifier": "67890"
}
]
}
Response (200 OK):
"3fa85f64-5717-4562-b3fc-2c963f66afa6"
Processing:
1. Validates metadata and file content
2. Uploads file content to Unity File Handler (Base64-encoded)
3. Saves file metadata to SQL Server (Files.Files)
4. Creates composite identifier references if provided
/files/{fileId}Download a file by its GUID.
Path Parameters:
- fileId (GUID, required) — File identifier
Response (200 OK): FileStreamResult — File content stream with appropriate content type
Processing: 1. Looks up file metadata from SQL Server 2. Retrieves file content stream from Unity File Handler 3. Returns file with original content type and file name
/files/{fileId}/metadataGet metadata for a specific file.
Path Parameters:
- fileId (GUID, required) — File identifier
Response (200 OK):
{
"fileId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"facilityId": 12345,
"fileName": "report.pdf",
"contentType": "application/pdf",
"fileSize": 1048576,
"fileDate": "2026-03-11",
"uploadedWhenUTC": "2026-03-11T10:00:00Z",
"uploadedWhoName": "John Smith",
"enabledForDocumentation": true,
"fileGroupId": 1,
"searchTerm": "quarterly report",
"externalReferences": [
{
"domain": "Tasks",
"type": "WorkOrder",
"identifier": "67890"
}
]
}
/files/{fileId}/metadataFull update of file metadata.
Path Parameters:
- fileId (GUID, required) — File identifier
Request Body:
{
"fileName": "updated-report.pdf",
"fileGroupId": 2,
"fileDate": "2026-03-15",
"enabledForDocumentation": false,
"searchTerm": "updated quarterly report",
"externalReferences": [
{
"domain": "Tasks",
"type": "WorkOrder",
"identifier": "67890"
}
]
}
Response: 204 No Content
/files/{fileId}/metadataPartial update of file metadata (only specified fields are updated).
Path Parameters:
- fileId (GUID, required) — File identifier
Request Body (PatchFileMetadataRequest — all fields nullable):
{
"facilityId": 12346,
"fileName": "renamed-report.pdf",
"fileGroupId": 3,
"fileDate": "2026-04-01",
"enabledForDocumentation": true,
"searchTerm": "new search term",
"externalReferences": [
{
"domain": "Assets",
"type": "Asset",
"identifier": "A-100"
}
]
}
Response: 204 No Content
/files/{fileId}Soft delete a file (sets IsActive = false).
Path Parameters:
- fileId (GUID, required) — File identifier
Response: 200 OK
/files/facilities/{facilityId}/metadataSearch file metadata for a facility with filtering and pagination.
Path Parameters:
- facilityId (int, required) — Facility identifier
Query Parameters:
- fileGroups (string, optional) — Comma-separated file group IDs to filter by
- minFileDate (date, optional) — Minimum file date filter
- maxFileDate (date, optional) — Maximum file date filter
- excludeFilesWithFileGroups (bool, optional) — Exclude files that belong to a file group
- excludeFilesWithExternalReferences (bool, optional) — Exclude files that have external references
- searchTerm (string, optional) — Text search filter
- nextPageKey (string, optional) — Pagination cursor from previous response
Response (200 OK):
{
"fileMetadata": [
{
"fileId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"facilityId": 12345,
"fileName": "report.pdf",
"contentType": "application/pdf",
"fileSize": 1048576,
"fileDate": "2026-03-11",
"uploadedWhenUTC": "2026-03-11T10:00:00Z",
"uploadedWhoName": "John Smith",
"enabledForDocumentation": true,
"fileGroupId": 1,
"searchTerm": "quarterly report",
"externalReferences": []
}
],
"nextPageKey": "eyJwYWdlIjoyfQ==",
"total": 42
}
Route Prefix: /files/fileGroups
API Version: v1
Authorization: JWT Bearer + Custom (DirectSupplyPartner | Customer)
| Method | Path | Description |
|---|---|---|
| GET | /files/fileGroups |
Get file groups |
| GET | /files/fileGroups/{fileGroupId} |
Get single file group |
| POST | /files/fileGroups |
Create file group |
| PUT | /files/fileGroups/{fileGroupId} |
Update file group |
| PATCH | /files/fileGroups/{fileGroupId} |
Patch file group |
| DELETE | /files/fileGroups/{fileGroupId} |
Delete file group |
/files/fileGroupsGet file groups with optional filtering.
Query Parameters:
- chainId (int, optional) — Filter by chain/organization
- externalReferences (string, optional) — Filter by external references
Response (200 OK):
[
{
"fileGroupId": 1,
"fileGroupName": "Inspection Reports",
"chainId": 100,
"externalReferences": [
{
"domain": "Assets",
"type": "AssetType",
"identifier": "HVAC"
}
]
}
]
/files/fileGroups/{fileGroupId}Get a single file group by ID.
Path Parameters:
- fileGroupId (int, required)
Response (200 OK):
{
"fileGroupId": 1,
"fileGroupName": "Inspection Reports",
"chainId": 100,
"externalReferences": []
}
/files/fileGroupsCreate a new file group.
Request Body:
{
"chainId": 100,
"fileGroupName": "Maintenance Photos",
"externalReferences": [
{
"domain": "Assets",
"type": "AssetType",
"identifier": "Plumbing"
}
]
}
Response (200 OK):
1
/files/fileGroups/{fileGroupId}Full update of a file group.
Path Parameters:
- fileGroupId (int, required)
Request Body:
{
"fileGroupName": "Updated Group Name",
"chainId": 200,
"externalReferences": []
}
Response: 204 No Content
/files/fileGroups/{fileGroupId}Partial update of a file group.
Path Parameters:
- fileGroupId (int, required)
Request Body (all fields nullable):
{
"fileGroupName": "Renamed Group"
}
Response: 204 No Content
/files/fileGroups/{fileGroupId}Delete a file group.
Path Parameters:
- fileGroupId (int, required)
Response: 204 No Content
{
"fileId": "guid",
"facilityId": 12345,
"fileName": "report.pdf",
"contentType": "application/pdf",
"fileSize": 1048576,
"fileDate": "2026-03-11",
"uploadedWhenUTC": "2026-03-11T10:00:00Z",
"uploadedWhoName": "John Smith",
"enabledForDocumentation": true,
"fileGroupId": 1,
"searchTerm": "quarterly report",
"externalReferences": [
{
"domain": "Tasks",
"type": "WorkOrder",
"identifier": "67890"
}
]
}
{
"domain": "Tasks",
"type": "WorkOrder",
"identifier": "67890"
}
{
"fileGroupId": 1,
"fileGroupName": "Inspection Reports",
"chainId": 100,
"externalReferences": []
}
{
"fileMetadata": [],
"nextPageKey": "cursor-string",
"total": 42
}
| Code | Meaning |
|---|---|
| 200 | Success |
| 204 | No Content (successful update/delete) |
| 400 | Bad Request — validation error |
| 401 | Unauthorized — invalid or missing JWT token |
| 403 | Forbidden — insufficient persona or facility access |
| 404 | Not Found — file or file group does not exist |
MaxRequestBodySize is set to int.MaxValue (~2 GB) to support large file uploads.nextPageKey for cursor-based pagination rather than page numbers.FacilityAuthorizationService.