---
title: Java | Avara
description: Handle AutoScribe webhooks in Java.
---

You almost never need all six webhooks. Read [What webhooks should I configure](/integration/autoscribe/what-webhooks-should-i-configure/index.md) first — it maps each integration profile to the endpoints you should set, based on the products you or your customer use and the end behavior you want. Leave unused endpoints blank.

This page is the Java implementation guide: verify signatures, then handle only the events you enabled.

## Webhook security

All webhook requests from Avara are signed using HMAC-SHA256 with Standard Webhooks headers (`webhook-id`, `webhook-timestamp`, `webhook-signature`). Copy the webhook secret from [API Config](/integration/autoscribe/api-config/index.md) (**View Webhook Secret**) and set it as the `AVARA_WEBHOOK_KEY` environment variable. The SDK’s `unwrap()` method reads that variable, verifies the signature, and returns a typed event. Every Avara→partner POST expects **HTTP 200** with a JSON body matching that event’s response schema. Synchronous hooks should respond within about **30 seconds**.

You can use `unsafeUnwrap()` instead of `unwrap()` to skip signature verification, but this is not recommended for production as it bypasses security checks.

```
import com.avara.client.AvaraClient;
import com.avara.client.okhttp.AvaraOkHttpClient;
import com.avara.models.webhooks.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.http.ResponseEntity;
import javax.servlet.http.HttpServletRequest;
import java.util.*;


@RestController
@RequestMapping("/webhooks")
public class WebhookController {


    private final AvaraClient client = AvaraOkHttpClient.fromEnv();


    @PostMapping("/avara")
    public ResponseEntity<?> handleWebhook(
        @RequestBody String body,
        HttpServletRequest request
    ) {
        WebhookEvent event = client.webhooks().unwrap(body, getHeaders(request));


        if (event instanceof StudyAccessRequestedWebhookEvent e) {
            // Handle study access request
            String studyId = e.getData().getStudyId();
            // ...
        }


        if (event instanceof SecondaryCaptureAccessRequestedWebhookEvent e) {
            // Handle secondary capture upload request
            String studyId = e.getData().getStudyId();
            // ...
        }


        if (event instanceof ReportDeliveredWebhookEvent e) {
            // Handle report delivery
            String reportId = e.getData().getReportId();
            // ...
        }


        if (event instanceof ModalityWorklistRequestedWebhookEvent e) {
            // Handle modality worklist request
            String clinicId = e.getData().getClinicId();
            // ...
        }


        if (event instanceof PatientStudyEnrichmentRequestedWebhookEvent e) {
            // Handle patient/study enrichment
            String studyInstanceUid = e.getData().getStudyInstanceUid();
            // ...
        }


        if (event instanceof ClinicalContextEnrichmentRequestedWebhookEvent e) {
            // Handle clinical context enrichment
            String studyId = e.getData().getStudyId();
            // ...
        }


        return ResponseEntity.ok().build();
    }


    private Map<String, List<String>> getHeaders(HttpServletRequest request) {
        Map<String, List<String>> headers = new HashMap<>();
        var headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String name = headerNames.nextElement();
            headers.put(name, Collections.list(request.getHeaders(name)));
        }
        return headers;
    }
}
```

## Study Image Access

The `study.access_requested` webhook is sent when Avara needs presigned URLs for DICOM images (and optional non-DICOM media). This is a **synchronous (hard) webhook** — you must respond within about 30 seconds. This webhook is sent before a study can be viewed in the Avara interface.

When Avara needs to access study images, it sends a POST request to your webhook endpoint. Your endpoint must respond with presigned GET URLs. The SDK’s `unwrap()` method returns a typed `StudyAccessRequestedWebhookEvent` that you can use directly.

Return `authorized: false` with an `error` when the caller must not access the study. Returning `authorized: true` with an empty `urls` array (and omitted or empty `mediaUrls`) is treated as no data available, not as a denial.

```
import com.avara.client.AvaraClient;
import com.avara.client.okhttp.AvaraOkHttpClient;
import com.avara.models.webhooks.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.http.ResponseEntity;
import javax.servlet.http.HttpServletRequest;
import java.util.*;


@RestController
@RequestMapping("/webhooks")
public class WebhookController {


    private final AvaraClient client = AvaraOkHttpClient.fromEnv();


    @PostMapping("/avara")
    public ResponseEntity<?> handleWebhook(
        @RequestBody String body,
        HttpServletRequest request
    ) {
        WebhookEvent event = client.webhooks().unwrap(body, getHeaders(request));


        if (event instanceof StudyAccessRequestedWebhookEvent e) {
            String studyId = e.getData().getStudyId();
            String studyInstanceUid = e.getData().getStudyInstanceUid();


            // This is your internal business logic
            List<String> presignedUrls = generatePresignedUrlsForStudy(studyInstanceUid);


            if (presignedUrls.isEmpty()) {
                return ResponseEntity.ok(Map.of(
                    "authorized", false,
                    "error", "Study not found in PACS"
                ));
            }


            return ResponseEntity.ok(Map.of(
                "authorized", true,
                "urls", presignedUrls
            ));
        }
        return ResponseEntity.ok().build();
    }


    // This is your internal business logic
    private List<String> generatePresignedUrlsForStudy(String studyInstanceUid) {
        // Query your PACS/RIS system for the study
        // Generate presigned URLs for each DICOM image
        // Return a flat list of all image URLs
        return List.of(
            "https://storage.example.com/dicom/image1.dcm?token=abc123",
            "https://storage.example.com/dicom/image2.dcm?token=def456"
        );
    }


    private Map<String, List<String>> getHeaders(HttpServletRequest request) {
        Map<String, List<String>> headers = new HashMap<>();
        var headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String name = headerNames.nextElement();
            headers.put(name, Collections.list(request.getHeaders(name)));
        }
        return headers;
    }
}
```

**Response Format**

```
public class StudyAccessRequestedWebhookResponse {
    private boolean authorized;
    private List<String> urls; // Flat list of DICOM GET URLs (may be empty)
    private List<StudyAccessRequestedMediaUrl> mediaUrls;
    private String error; // Error message if authorization failed
}


public class StudyAccessRequestedMediaUrl {
    private String url;
    private String mimeType;
    private String fileName;
}
```

## Secondary Capture Upload

The `secondary_capture.access_requested` webhook is sent when a viewer user creates a secondary capture. This is a **synchronous (hard) webhook** — you must return presigned PUT URLs in-request, within about 30 seconds.

Avara asks for upload URLs before writing the generated DICOM to your storage. The SDK’s `unwrap()` method returns a typed `SecondaryCaptureAccessRequestedWebhookEvent`. Respond `authorized: false` with an `error` if the study cannot be written. `uploadUrls` must be PUT-capable; the client uploads with `Content-Type: application/dicom` and writes the same object to every URL. Series and SOP UIDs are provided when available so you can pre-compute object keys. If you send `contentCreatorName`, Avara ignores it and derives the creator name server-side.

```
import com.avara.client.AvaraClient;
import com.avara.client.okhttp.AvaraOkHttpClient;
import com.avara.models.webhooks.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.http.ResponseEntity;
import javax.servlet.http.HttpServletRequest;
import java.util.*;


@RestController
@RequestMapping("/webhooks")
public class WebhookController {


    private final AvaraClient client = AvaraOkHttpClient.fromEnv();


    @PostMapping("/avara")
    public ResponseEntity<?> handleWebhook(
        @RequestBody String body,
        HttpServletRequest request
    ) {
        WebhookEvent event = client.webhooks().unwrap(body, getHeaders(request));


        if (event instanceof SecondaryCaptureAccessRequestedWebhookEvent e) {
            String studyId = e.getData().getStudyId();
            String studyInstanceUid = e.getData().getStudyInstanceUid();
            String seriesInstanceUid = e.getData().getSeriesInstanceUid();
            String sopInstanceUid = e.getData().getSopInstanceUid();


            // This is your internal business logic
            List<String> uploadUrls = generateSecondaryCaptureUploadUrls(
                studyInstanceUid,
                seriesInstanceUid,
                sopInstanceUid
            );


            if (uploadUrls.isEmpty()) {
                return ResponseEntity.ok(Map.of(
                    "authorized", false,
                    "error", "Study cannot be written"
                ));
            }


            return ResponseEntity.ok(Map.of(
                "authorized", true,
                "uploadUrls", uploadUrls
            ));
        }
        return ResponseEntity.ok().build();
    }


    // This is your internal business logic
    private List<String> generateSecondaryCaptureUploadUrls(
        String studyInstanceUid,
        String seriesInstanceUid,
        String sopInstanceUid
    ) {
        // Generate presigned PUT URLs for the secondary capture DICOM
        return List.of(
            "https://storage.example.com/dicom/sc/image.dcm?token=abc123"
        );
    }


    private Map<String, List<String>> getHeaders(HttpServletRequest request) {
        Map<String, List<String>> headers = new HashMap<>();
        var headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String name = headerNames.nextElement();
            headers.put(name, Collections.list(request.getHeaders(name)));
        }
        return headers;
    }
}
```

**Response Format**

```
public class SecondaryCaptureAccessRequestedWebhookResponse {
    private boolean authorized;
    private List<String> uploadUrls;
    private String contentCreatorName; // Ignored if provided
    private String error;
}
```

## Report Delivery

The `report.delivered` webhook is sent when a report is completed and delivered. This is an **asynchronous notification** — respond with a simple success acknowledgment. The webhook includes plain text content, a presigned URL for PDF download, and `isCritical` (whether the report was marked critical at sign-off).

When a report is completed, Avara sends a POST request to your webhook endpoint. Your endpoint should process the report and respond with a success acknowledgment. The SDK’s `unwrap()` method returns a typed `ReportDeliveredWebhookEvent` that you can use directly.

```
import com.avara.client.AvaraClient;
import com.avara.client.okhttp.AvaraOkHttpClient;
import com.avara.models.webhooks.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.http.ResponseEntity;
import javax.servlet.http.HttpServletRequest;
import java.util.*;


@RestController
@RequestMapping("/webhooks")
public class WebhookController {


    private final AvaraClient client = AvaraOkHttpClient.fromEnv();


    @PostMapping("/avara")
    public ResponseEntity<?> handleWebhook(
        @RequestBody String body,
        HttpServletRequest request
    ) {
        WebhookEvent event = client.webhooks().unwrap(body, getHeaders(request));


        if (event instanceof ReportDeliveredWebhookEvent e) {
            String reportId = e.getData().getReportId();
            String studyId = e.getData().getStudyId();
            String plainText = e.getData().getPlainText();
            String presignedUrl = e.getData().getPresignedUrl();
            boolean isCritical = e.getData().isCritical();


            // This is your internal business logic
            processCompletedReport(reportId, studyId, plainText, presignedUrl, isCritical);


            return ResponseEntity.ok(Map.of("success", true));
        }
        return ResponseEntity.ok().build();
    }


    // This is your internal business logic
    private void processCompletedReport(
        String reportId,
        String studyId,
        String plainText,
        String presignedUrl,
        boolean isCritical
    ) {
        // Download the PDF from the presigned URL
        // Store the report in your system
        // Update your PACS/RIS with the completed report
        // Notify relevant users or systems
    }


    private Map<String, List<String>> getHeaders(HttpServletRequest request) {
        Map<String, List<String>> headers = new HashMap<>();
        var headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String name = headerNames.nextElement();
            headers.put(name, Collections.list(request.getHeaders(name)));
        }
        return headers;
    }
}
```

**Response Format**

```
public class ReportDeliveredWebhookResponse {
    private boolean success;
}
```

## Modality Worklist

The `modality_worklist.requested` webhook is sent when an on-prem modality (via an Avara PACS box) issues a C-FIND MWL. This is a **synchronous (hard) webhook** — the C-FIND path waits on your response, which should return within about 30 seconds.

Avara forwards the query window to your endpoint. Only one active API key per organization may have the Modality Worklist Webhook Endpoint set. The SDK’s `unwrap()` method returns a typed `ModalityWorklistRequestedWebhookEvent`. Return `authorized: false` with an `error` to surface a worklist failure to the modality. `items` is required and may be empty when there are no scheduled exams.

Item field names are PascalCase DICOM-style (not camelCase). `StudyInstanceUID` is required from the partner RIS today — do not omit it. `PatientName`, `PatientID`, and `Modality` must be non-empty. `ScheduledProcedureStepSequence` must contain at least one step.

```
import com.avara.client.AvaraClient;
import com.avara.client.okhttp.AvaraOkHttpClient;
import com.avara.models.webhooks.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.http.ResponseEntity;
import javax.servlet.http.HttpServletRequest;
import java.util.*;


@RestController
@RequestMapping("/webhooks")
public class WebhookController {


    private final AvaraClient client = AvaraOkHttpClient.fromEnv();


    @PostMapping("/avara")
    public ResponseEntity<?> handleWebhook(
        @RequestBody String body,
        HttpServletRequest request
    ) {
        WebhookEvent event = client.webhooks().unwrap(body, getHeaders(request));


        if (event instanceof ModalityWorklistRequestedWebhookEvent e) {
            String clinicId = e.getData().getClinicId();
            String callingAe = e.getData().getCallingAe();
            String sourceIp = e.getData().getSourceIp();
            String dateStart = e.getData().getDateStart();
            String dateEnd = e.getData().getDateEnd();
            String modality = e.getData().getModality();


            // This is your internal business logic
            List<Map<String, Object>> items = queryModalityWorklist(
                clinicId, callingAe, sourceIp, dateStart, dateEnd, modality
            );


            Map<String, Object> response = new HashMap<>();
            response.put("authorized", true);
            response.put("items", items);
            return ResponseEntity.ok(response);
        }
        return ResponseEntity.ok().build();
    }


    // This is your internal business logic
    private List<Map<String, Object>> queryModalityWorklist(
        String clinicId,
        String callingAe,
        String sourceIp,
        String dateStart,
        String dateEnd,
        String modality
    ) {
        Map<String, Object> step = new LinkedHashMap<>();
        step.put("ScheduledProcedureStepStartDate", "20260813");
        step.put("ScheduledProcedureStepStartTime", "090000");
        step.put("ScheduledProcedureStepID", "SPSID-1");
        step.put("Modality", "CT");
        step.put("ScheduledProcedureStepDescription", "CT CHEST WO CONTRAST");


        Map<String, Object> item = new LinkedHashMap<>();
        item.put("PatientName", "DOE^JANE");
        item.put("PatientID", "MRN12345");
        item.put("PatientBirthDate", "19800115");
        item.put("PatientSex", "F");
        item.put("PatientSize", "1.65");
        item.put("PatientWeight", "62");
        item.put("Modality", "CT");
        item.put("AccessionNumber", "ACC-1001");
        item.put("StudyInstanceUID", "1.2.840.113619.2.55.3.604688119.868.1234567890.123");
        item.put("RequestedProcedureDescription", "CT CHEST WO CONTRAST");
        item.put("StudyDescription", "CT CHEST WO CONTRAST");
        item.put("ProtocolName", "CHEST_WO");
        item.put("ScheduledProcedureStepSequence", List.of(step));


        return List.of(item);
    }


    private Map<String, List<String>> getHeaders(HttpServletRequest request) {
        Map<String, List<String>> headers = new HashMap<>();
        var headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String name = headerNames.nextElement();
            headers.put(name, Collections.list(request.getHeaders(name)));
        }
        return headers;
    }
}
```

**Response Format**

```
public class ModalityWorklistRequestedWebhookResponse {
    private boolean authorized;
    private List<ModalityWorklistItem> items;
    private String error;
}


public class ModalityWorklistItem {
    private String PatientName;
    private String PatientID;
    private String PatientBirthDate;
    private String PatientSex;
    private String PatientSize;
    private String PatientWeight;
    private String Modality;
    private String AccessionNumber;
    private String StudyInstanceUID;
    private String RequestedProcedureDescription;
    private String StudyDescription;
    private String ProtocolName;
    private List<ModalityWorklistScheduledStep> ScheduledProcedureStepSequence;
}


public class ModalityWorklistScheduledStep {
    private String ScheduledProcedureStepStartDate;
    private String ScheduledProcedureStepStartTime;
    private String ScheduledProcedureStepID;
    private String Modality;
    private String ScheduledProcedureStepDescription;
}
```

## Patient / Study Enrichment

The `patient_study.enrichment_requested` webhook is sent after Avara PACS receives the first C-STORE and seeds the study. This is a **synchronous (soft) webhook** — failures, timeouts, and invalid bodies are treated as empty enrichment and do **not** hard-fail study creation.

Avara asks your EHR/RIS for demographic and study header fields to merge into AutoScribe study creation. The SDK’s `unwrap()` method returns a typed `PatientStudyEnrichmentRequestedWebhookEvent`. There is no `authorized` field; HTTP 2xx plus JSON that parses is enough. Returning `{}` is valid. Avara merges per-field with DICOM light metadata, then defaults. Do not rely on this webhook for hard access control.

```
import com.avara.client.AvaraClient;
import com.avara.client.okhttp.AvaraOkHttpClient;
import com.avara.models.webhooks.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.http.ResponseEntity;
import javax.servlet.http.HttpServletRequest;
import java.util.*;


@RestController
@RequestMapping("/webhooks")
public class WebhookController {


    private final AvaraClient client = AvaraOkHttpClient.fromEnv();


    @PostMapping("/avara")
    public ResponseEntity<?> handleWebhook(
        @RequestBody String body,
        HttpServletRequest request
    ) {
        WebhookEvent event = client.webhooks().unwrap(body, getHeaders(request));


        if (event instanceof PatientStudyEnrichmentRequestedWebhookEvent e) {
            String clinicId = e.getData().getClinicId();
            String studyInstanceUid = e.getData().getStudyInstanceUid();
            String patientId = e.getData().getPatientId();
            String accessionNumber = e.getData().getAccessionNumber();


            // This is your internal business logic
            Map<String, Object> enrichment = enrichPatientStudy(
                clinicId, studyInstanceUid, patientId, accessionNumber
            );


            return ResponseEntity.ok(enrichment);
        }
        return ResponseEntity.ok().build();
    }


    // This is your internal business logic
    private Map<String, Object> enrichPatientStudy(
        String clinicId,
        String studyInstanceUid,
        String patientId,
        String accessionNumber
    ) {
        // Look up demographics and study headers in your EHR/RIS
        // Return any subset of fields — or Collections.emptyMap()
        Map<String, Object> height = new LinkedHashMap<>();
        height.put("value", 165);
        height.put("unit", "cm");


        Map<String, Object> weight = new LinkedHashMap<>();
        weight.put("value", 62);
        weight.put("unit", "kg");


        Map<String, Object> enrichment = new LinkedHashMap<>();
        enrichment.put("patientName", "Jane Doe");
        enrichment.put("dateOfBirth", "1980-01-15");
        enrichment.put("sex", "female");
        enrichment.put("height", height);
        enrichment.put("weight", weight);
        enrichment.put("mrn", "MRN12345");
        enrichment.put("externalPatientId", "EHR-PT-1001");
        enrichment.put("procedure", "CT CHEST WO CONTRAST");
        enrichment.put("studyDescription", "CT CHEST WO CONTRAST");
        enrichment.put("facilityName", "South Tampa Imaging");
        enrichment.put("referringPhysicianName", "Dr. Alan Smith");
        enrichment.put("studyDate", "2026-08-13");
        enrichment.put("studyTime", "09:00");
        enrichment.put("severity", "normal");
        return enrichment;
    }


    private Map<String, List<String>> getHeaders(HttpServletRequest request) {
        Map<String, List<String>> headers = new HashMap<>();
        var headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String name = headerNames.nextElement();
            headers.put(name, Collections.list(request.getHeaders(name)));
        }
        return headers;
    }
}
```

**Response Format**

```
public class PatientStudyEnrichmentRequestedWebhookResponse {
    private String patientName;
    private String dateOfBirth;
    private String sex; // "male" | "female" | "other"
    private Height height;
    private Weight weight;
    private String mrn;
    private String externalPatientId;
    private String procedure;
    private String studyDescription;
    private String facilityName;
    private String referringPhysicianName;
    private String studyDate;
    private String studyTime;
    private String severity; // "normal" | "high" | "stat"
}


public class Height {
    private double value;
    private String unit; // "in" | "cm"
}


public class Weight {
    private double value;
    private String unit; // "lbs" | "kg"
}
```

## Clinical Context Enrichment

The `clinical_context.enrichment_requested` webhook is sent when AutoScribe needs clinical context for a study (for example, a radiologist opens the study). This is a **synchronous (soft) webhook** — failures are treated as empty enrichment.

Avara asks your EHR for indication, technique, priors, and supporting documents. The SDK’s `unwrap()` method returns a typed `ClinicalContextEnrichmentRequestedWebhookEvent`. There is no `authorized` field. Returning `{}` is valid.

`data.studyId` on this event is a raw UUID v4, not a branded `stu_…` id. Most other study webhooks use `stu_…`.

`documents` are verbatim text chunks. `documentUrls` are fetched and summarized by Avara — prefer `https://` URLs.

```
import com.avara.client.AvaraClient;
import com.avara.client.okhttp.AvaraOkHttpClient;
import com.avara.models.webhooks.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.http.ResponseEntity;
import javax.servlet.http.HttpServletRequest;
import java.util.*;


@RestController
@RequestMapping("/webhooks")
public class WebhookController {


    private final AvaraClient client = AvaraOkHttpClient.fromEnv();


    @PostMapping("/avara")
    public ResponseEntity<?> handleWebhook(
        @RequestBody String body,
        HttpServletRequest request
    ) {
        WebhookEvent event = client.webhooks().unwrap(body, getHeaders(request));


        if (event instanceof ClinicalContextEnrichmentRequestedWebhookEvent e) {
            String clinicId = e.getData().getClinicId();
            String studyInstanceUid = e.getData().getStudyInstanceUid();
            String studyId = e.getData().getStudyId();
            String externalPatientId = e.getData().getExternalPatientId();
            String mrn = e.getData().getMrn();


            // This is your internal business logic
            Map<String, Object> enrichment = enrichClinicalContext(
                clinicId, studyInstanceUid, studyId, externalPatientId, mrn
            );


            return ResponseEntity.ok(enrichment);
        }
        return ResponseEntity.ok().build();
    }


    // This is your internal business logic
    private Map<String, Object> enrichClinicalContext(
        String clinicId,
        String studyInstanceUid,
        String studyId,
        String externalPatientId,
        String mrn
    ) {
        // Pull indication, technique, priors, and documents from your EHR
        // Return any subset of fields — or Collections.emptyMap()
        Map<String, Object> prior = new LinkedHashMap<>();
        prior.put("studyDescription", "CT CHEST WO CONTRAST");
        prior.put("modality", "CT");
        prior.put("studyDate", "2025-11-02");
        prior.put("reportText", "No acute cardiopulmonary process.");


        Map<String, Object> enrichment = new LinkedHashMap<>();
        enrichment.put("clinicalIndication", "Shortness of breath, evaluate for PE");
        enrichment.put("technologistTechnique", "Helical CT chest, 1.25 mm, IV contrast");
        enrichment.put("priorReports", List.of(prior));
        return enrichment;
    }


    private Map<String, List<String>> getHeaders(HttpServletRequest request) {
        Map<String, List<String>> headers = new HashMap<>();
        var headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String name = headerNames.nextElement();
            headers.put(name, Collections.list(request.getHeaders(name)));
        }
        return headers;
    }
}
```

**Response Format**

```
public class ClinicalContextEnrichmentRequestedWebhookResponse {
    private String clinicalIndication;
    private String technologistTechnique;
    private List<String> technologistNotes;
    private List<ClinicalContextEnrichmentPriorReport> priorReports;
    private List<ClinicalContextEnrichmentDocument> documents;
    private List<ClinicalContextEnrichmentDocumentUrl> documentUrls;
}


public class ClinicalContextEnrichmentPriorReport {
    private String externalStudyId;
    private String studyDescription;
    private String modality;
    private String studyDate;
    private String reportText;
}


public class ClinicalContextEnrichmentDocument {
    private String fileName;
    private List<String> content;
}


public class ClinicalContextEnrichmentDocumentUrl {
    private String fileName;
    private String url;
}
```
