File Storage

The File Storage API lets you upload, retrieve, and delete files associated with your organization. Files are stored with organization-scoped isolation. The most common use case is attaching clinical documents, lab reports, imaging files, or signed consent forms to FHIR DocumentReference or Media resources.

Before storing, every upload passes through:

  1. Magic-byte + extension + MIME consistency check — mismatches are rejected with 415.
  2. Antivirus scan — when ClamAV is configured, infected files are rejected with 422.
  3. Tenant binding — files are stored under the caller’s organization; cross-tenant access is not possible.

Upload a File

Files are uploaded via multipart/form-data. Maximum file size is 50 MB.

curl -X POST https://api.esus.health/files/upload \
  -H "Authorization: Bearer TOKEN" \
  -F "file=@/path/to/lab-report.pdf"

Response:

{
  "key": "3fa85f64-5717-4562-b3fc-2c963f66afa6/a1b2c3d4e5f6a7b8.pdf",
  "contentType": "application/pdf",
  "size": 245760,
  "url": "/files/3fa85f64-5717-4562-b3fc-2c963f66afa6/a1b2c3d4e5f6a7b8.pdf"
}

The key is the storage path (<orgId>/<fileId>). The url is the relative path where the file can be downloaded; prefix it with the API host to build an absolute URL. The content-type in the response is the server-detected MIME (not the client-declared one) — it is what you should store in attachment.contentType.

Supported Content Types (examples)

TypeCommon use
application/pdfClinical documents, consent forms, reports
image/jpeg, image/pngMedical photography, wound documentation
text/plainStructured text reports
application/jsonData exports, structured results
video/mp4Procedural recordings

The validator enforces a whitelist of clinical content types. Request additions through support when you have a legitimate use case.

Download a File

curl "https://api.esus.health/files/3fa85f64-5717-4562-b3fc-2c963f66afa6/a1b2c3d4e5f6a7b8.pdf" \
  -H "Authorization: Bearer TOKEN" \
  -o downloaded-report.pdf

By default the response uses Content-Disposition: attachment to prevent HTML/SVG/PDF from being rendered in-origin (XSS via uploaded content). Image-preview flows can opt in via ?disposition=inline. Cross-organization reads are refused with 403.

Delete a File

curl -X DELETE "https://api.esus.health/files/3fa85f64-5717-4562-b3fc-2c963f66afa6/a1b2c3d4e5f6a7b8.pdf" \
  -H "Authorization: Bearer TOKEN"

Returns 204 No Content on success. Deletion is permanent — files are not recoverable afterwards.

Linking Files to FHIR Resources

After uploading, reference the file URL from a FHIR resource. Remember that the patient reference is sent as a flat id (subjectId), not as a nested FHIR reference object.

DocumentReference (lab report)

curl -X POST https://api.esus.health/fhir/DocumentReference \
  -H "Authorization: Bearer TOKEN" \
  -H "Content-Type: application/fhir+json" \
  -d '{
    "status": "current",
    "type": {
      "coding": [{
        "system": "http://loinc.org",
        "code": "11502-2",
        "display": "Laboratory report"
      }]
    },
    "subjectId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "date": "2026-04-21",
    "content": [{
      "attachment": {
        "contentType": "application/pdf",
        "url": "https://api.esus.health/files/3fa85f64-5717-4562-b3fc-2c963f66afa6/a1b2c3d4e5f6a7b8.pdf",
        "title": "Lab report Apr 21",
        "size": 245760
      }
    }]
  }'

Media (clinical image)

curl -X POST https://api.esus.health/fhir/Media \
  -H "Authorization: Bearer TOKEN" \
  -H "Content-Type: application/fhir+json" \
  -d '{
    "status": "completed",
    "type": {
      "coding": [{
        "system": "http://terminology.hl7.org/CodeSystem/media-type",
        "code": "image"
      }]
    },
    "subjectId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "createdDateTime": "2026-04-21",
    "content": {
      "contentType": "image/jpeg",
      "url": "https://api.esus.health/files/3fa85f64-5717-4562-b3fc-2c963f66afa6/b2c3d4e5f6a7b8c9.jpg"
    }
  }'

Upload Limits and Best Practices

LimitValue
Maximum file size50 MB
ProtocolHTTPS only
Tenant isolationScoped to the caller’s organization

Best practices:

  • Link uploaded files to FHIR resources immediately — orphan files consume storage and lose clinical context.
  • Use the server-detected contentType from the upload response when writing the attachment.
  • Delete files when the associated FHIR resource is deleted.
  • For large imaging files (>50 MB), use a dedicated DICOM/PACS system and reference the external URL in Media.content.url.