Use Cases
The iframe returns a JSON payload through the analysis_completed callback, and the full diagnostic report can be pulled from the API using the anonymousDiagnosticReportId it carries. That JSON is the raw material your host application uses to drive workflows.
The host app obtains the report by listening to analysis_completed and then calling the Output → API Endpoint. The schema of the JSON is described in the Output → JSON Schema section.
1. Skin-cancer triage in a patient app​
Objective: When the iframe is embedded inside a patient-facing app, support routing the patient to the appropriate level of care, without ever showing them the raw clinical output.
This pattern combines two iframe parameters:
isForPatient=1: simplifies questionnaire wording for non-clinical users.enableResult=0: hides the diagnostic result from the user, so the host app is the only consumer of the JSON.
The host app receives the report via analysis_completed, evaluates the keys returned under result, and decides what the patient sees next: a self-care message, a primary-care booking screen, or guidance for an urgent dermatology appointment.
Rather than relying on malignancy alone, the triage combines several signals returned by the device:
result.preliminaryFindings.urgentReferral: probability (0 to 100) that the patient may benefit from being seen by a doctor within the next 48 hours. Used by the host app to inform the urgent-referral branch.result.preliminaryFindings.highPriorityReferral: probability (0 to 100) that the patient may benefit from being seen within the next 15 days. Captures cases that are not 48-hour-urgent but may still benefit from a fast-tracked appointment.result.metrics.entropy: a measure of how confident the AI is in its response. Lower entropy means higher confidence; the host app can use cases above the entropy threshold as a safety fallback, so uncertain reports are not routed to self-care.result.scoringSystems[]: when the diagnostic-support algorithm reaches sufficient confidence, the relevant scoring system is computed (for pigmented lesions this is typically the 7-point checklist, codesevenPc). Each entry carries ascore.severity.valueof1(low),2(moderate) or3(high).result.preliminaryFindings.hasCondition: likelihood that a condition is present at all - used at the very end of the cascade to decide between primary care and self-care.
The patient never sees the underlying probabilities; they only see the action your app surfaces.
window.addEventListener("message", async function (event) {
if (event.data.message !== "analysis_completed") return;
const report = await fetchReportFromApi(event.data.id);
const { preliminaryFindings, scoringSystems, metrics } = report.result;
const sevenPc = scoringSystems?.find((s) => s.scoringSystem.code === "sevenPc");
if (preliminaryFindings.urgentReferral > 60) {
showUrgentDermatologistScreen();
} else if (metrics.entropy != null && metrics.entropy > 0.5) {
// Low model confidence - escalate as a safety fallback.
openDermatologyBooking();
} else if (preliminaryFindings.highPriorityReferral > 30) {
openDermatologyBooking();
} else if (sevenPc?.score?.severity?.value === 3) {
openDermatologyBooking();
} else if (preliminaryFindings.hasCondition > 70) {
openPrimaryCareBooking();
} else {
showSelfCareGuidance();
}
});
The values X, Y, Z and E (and the 60 / 30 / 70 / 0.5 shown above) are illustrative. Each managing organisation must choose its own thresholds based on its clinical protocols and the trade-off between false positives and false negatives. See the Thresholding section in the Legit.Health Plus workflows page for guidance, including a worked confusion-matrix example.
2. Longitudinal severity monitoring​
Objective: Track how a patient's condition evolves over time by storing severity scores returned by the iframe and rendering a trend in the host application.
The iframe itself does not retain information about users, so it cannot link two reports for the same patient. To enable longitudinal monitoring, the host app must:
- Pass a stable patient identifier through
extraDataevery time the iframe is launched (see the Customize page). - On
analysis_completed, fetch the report and persist the relevant severity values fromresult.scoringSystems[](thescore.value, thescoringSystem.codesuch assevenPc,apasiLocaloraladinLocal, and thescore.severity.valuebucket) in its own database, keyed by that identifier. - Render a historic chart from the persisted scores. This visualisation is built and maintained by the host application; the iframe does not provide it.
window.addEventListener("message", async function (event) {
if (event.data.message !== "analysis_completed") return;
const report = await fetchReportFromApi(event.data.id);
const patientId = report.extraData;
for (const entry of report.result.scoringSystems ?? []) {
await db.severityScores.insert({
patientId,
scoringSystemCode: entry.scoringSystem.code,
scoringSystemName: entry.scoringSystem.name,
score: entry.score?.value,
severityValue: entry.score?.severity?.value,
reduction: entry.reduction,
timestamp: report.createdAt,
});
}
});
Each scoring-system entry already exposes a reduction field: the per-cent change versus the previous report for the same patient. It is null on the first report and populated thereafter, so the host app can surface a quick "improving / worsening" indicator without computing the delta itself.
Once the data is stored, the host app can build clinical features on top of it. For example, it can compare the latest score against the baseline at treatment start, flag worsening trajectories to a clinician, or show the patient a longitudinal chart of their own condition.
The two patterns are complementary: the smart-triage flow informs the next step right now, while longitudinal monitoring builds the historical context that lets a clinician interpret today's score against the patient's own trajectory.