Aller au contenu principal

Get an Anonymous Diagnostic Report

Besides getting the DiagnosticReports linked to patients between your system and our, you can also fetch the AnonymousDiagnosticReports that you had sent, ie, those which are not linked to any patient.

We provide an endpoint to fetch an anonymous diagnostic report already present in the system. You only need the encrypted id of the diagnostic report in Legit.Health. This identifier is received from the message posted by our Iframe to your app.

To get a diagnostic report, you must use the endpoint getAnonymousDiagnosticReport.

A Anonymous Diagnostic Report contains all the information related to an image uploaded for a not-linked patient and the corresponding result data generated by our AI algorithms.

JSON Structure

The typical JSON structure we will send to your servers is the following:

Raw

/anonymous-diagnostic-reports/{encryptedId}?format=raw

The raw format is the default JSON payload returned by GET /s2s-api/v3/anonymous-diagnostic-reports/{encryptedId}. It is a flat, integrator-friendly shape designed to be consumed directly without FHIR tooling.

Strings tagged (translated) in this schema follow the locale query parameter on the request (?locale=es, ?locale=fr, ?locale=de). The default is English.

Envelope fields

Every response is wrapped in the standard ApiResponseData envelope:

{
"success": true,
"message": "Diagnostic report <id>",
"errorCode": null,
"data": { ... }
}
  • success: boolean. Indicates whether the request was successfully processed.
  • message: short text describing the action performed. Usually includes the diagnostic report identifier.
  • errorCode: null on success; an error code string when something fails.
  • data: the diagnostic report payload described below.

Full example

{
"success": true,
"message": "Diagnostic report <0189bafa-0610-7349-a0ab-eb53695b27fd>",
"errorCode": null,
"data": {
"id": "0189bafa-0610-7349-a0ab-eb53695b27fd",
"url": "https://iframe.legit.health?companyId=XXXX&diagnosticReportId=signedId",
"pdf": "https://utils.legit.health/pdf/anonymous-diagnostic-report?diagnosticReportIdEncrypted=<encryptedId>&apiKey=<apiKey>&authKey=<authKey>&locale=en",
"visitIdentifier": "visit identifier",
"extraData": {
"internalCaseId": "ABC-123",
"department": "dermatology"
},
"pathology": {
"name": "Acne",
"code": "Acne",
"icd11": "ED80"
},
"bodySite": {
"code": "headFront",
"name": "Face and neck"
},
"createdAt": "2023-08-03T12:38:10+02:00",
"anamnesisGeneral": [
{
"question": "What is the reason for the consultation? How did the problem start? Describe the origin.",
"answer": "I have acne on my face and neck. It started 2 months ago."
},
{
"question": "Do you have any allergies, especially to medications? If yes, list allergies.",
"answer": "No"
},
{
"question": "Are you taking any medication or treatment? If yes, explain what treatment you are taking.",
"answer": "No"
},
{
"question": "Do you have any major illness? Have you had anything operated on?",
"answer": "No"
},
{
"question": "Is there a history of any major illness in your family?",
"answer": "No"
}
],
"macroscopicMedia": {
"url": "https://bucket/diagnostic-report-medias/bbb.png",
"type": "Image",
"annotations": []
},
"result": {
"id": "0189bafa-0610-7349-a0ab-eb536a2185f6",
"metrics": {
"sensitivity": 83.31,
"specificity": 99.53,
"entropy": null
},
"preliminaryFindings": {
"hasCondition": 100,
"malignancy": 0.02,
"adjustedMalignancy": null,
"pigmentedLesion": 0,
"urgentReferral": 100,
"highPriorityReferral": 100
},
"iaSeconds": 0.88,
"observations": [
{
"media": {
"type": "Image",
"modality": "Clinical",
"diqaScore": 86,
"url": "https://bucket/diagnostic-report-medias/bbb.png"
}
}
],
"conclusions": [
{
"probability": 99.65,
"pathology": {
"name": "Acne",
"code": "Acne",
"icd11": "ED80"
}
},
{
"probability": 0.06,
"pathology": {
"name": "Varicella",
"code": "Varicella",
"icd11": "1E90"
}
}
],
"scoringSystems": [
{
"scoringSystem": {
"name": "Acne lesion estimation grading index",
"code": "alegi"
},
"score": {
"value": 8,
"severity": {
"value": 1,
"interpretations": [
{
"min": 0.0,
"max": 0.0,
"text": "None",
"coding": [
{
"code": 1,
"display": "low"
}
]
},
{
"min": 0.0,
"max": 2.1,
"text": "Mild",
"coding": [
{
"code": 1,
"display": "low"
}
]
},
{
"min": 2.1,
"max": 4.5,
"text": "Moderate",
"coding": [
{
"code": 2,
"display": "moderate"
}
]
},
{
"min": 4.5,
"max": 21.6,
"text": "Severe",
"coding": [
{
"code": 3,
"display": "high"
}
]
}
]
}
},
"reduction": null,
"facets": [
{
"facet": {
"name": "Acne lesion density",
"description": ""
},
"value": {
"display": "None (0)",
"raw": 0
}
},
{
"facet": {
"name": "Number of lesions",
"description": ""
},
"value": {
"display": "Mild (0-10)",
"raw": 5
}
}
],
"explainabilityMedia": {
"url": "https://bucket/diagnostic-report-medias/explainability/aaa.png"
}
}
]
}
}
}

Top-level fields

  • id: unique identifier of the diagnostic report (encrypted DiagnosticReportId).
  • url: iframe URL to visualize the diagnostic report inside Legit.Health. null when the company has no valid app key configured.
  • pdf: URL to download a printable PDF of the report. Calling the endpoint with ?format=pdf issues an HTTP 302 redirect to this same URL. Treat it as an opaque, authenticated URL; refetch the diagnostic report if the link stops working.
  • visitIdentifier: the visit or encounter identifier supplied by the integrator when the iframe was loaded (null when not provided). Use it to map the diagnostic report back to your own scheduling system.
  • extraData: free-form JSON object (or null) passed by the integrator when the iframe was loaded. Use it to round-trip your own identifiers, tags, or context back into the diagnostic report.
  • createdAt: ISO-8601 timestamp indicating when the diagnostic report was created.

Body site and pathology

These fields contain information about the location (bodySite) and type (pathology) of the lesion captured in the image. The bodySite object is ALWAYS present in the response (never null). The pathology object is null until the most-probable conclusion crosses the confidence threshold, or until an integrator supplied a value at image submission.

"bodySite": {
"code": "headFront",
"name": "Face and neck"
},
"pathology": {
"name": "Acne",
"code": "Acne",
"icd11": "ED80"
}
  • bodySite.code: camelCase identifier for the body site, for example headFront, trunkFront, armLeft. Match on the exact camelCase string; do not assume SCREAMING_SNAKE_CASE.
  • bodySite.name: human-readable label for the body site. Translated by the locale query parameter.
  • The bodySite object is ALWAYS present in the response (never null).

The complete list of supported body-site codes and their multilingual names can be fetched from a public, unauthenticated endpoint:

GET https://medical-device-params.legit.health/v2.0/body-sites

The response is an array of objects with two fields:

  • code: the camelCase identifier emitted under bodySite.code (e.g. headFront, armLeft, trunkFront).
  • name: an object keyed by locale (en_GB, es_ES, pt_BR, it_IT, fr_FR, de_DE, bg_BG, pl_PL, ko_KO, ca_ES) with the translated display name.

Use this endpoint as the source of truth: the list can grow over time as new body sites are added.

For pathology (the whole object may be null):

  • pathology.code: stable, human-readable internal identifier such as Acne, Psoriasis, Cutaneous melanoma. Drawn from a database-backed catalog of roughly 309 conditions, plus any custom condition a tenant has added via the admin. Treat it as a known-list-with-extensions: do not assume a closed set for validation, but you can switch on the well-known codes for routing.
  • pathology.name: human-readable condition label. Translated by the locale query parameter.
  • pathology.icd11: ICD-11 code for the condition; null when no ICD-11 mapping has been recorded for that condition. A single pathology may carry several ICD-11 codes comma-separated, e.g. "EA90.42, EA90.5Y".
  • The whole pathology object is null until the most-probable conclusion crosses the confidence threshold, or until an integrator supplied a value at image submission.

Anamnesis general

The anamnesisGeneral field is an array of questions and their corresponding answers. These questions are asked to the patient before the image is submitted for analysis and their objective is to gather information about the patient's medical history:

"anamnesisGeneral": [
{
"question": "What is the reason for the consultation? How did the problem start? Describe the origin.",
"answer": "I have acne on my face and neck. It started 2 months ago."
},
...
]

Macroscopic media

Details the image of the lesion or body part that was submitted for analysis. The whole object is null when no image was captured.

"macroscopicMedia": {
"url": "https://bucket/diagnostic-report-medias/bbb.png",
"type": "Image",
"annotations": []
}
  • url: signed S3 URL to the captured image. Time-limited (about 30 minutes).
  • type: media format. One of "Image" or "Video". null when no media was attached (in that case the whole macroscopicMedia object is itself null).
  • annotations: array of detection objects overlaid on the image, possibly empty []. Each entry has the shape:
    • id: opaque 32-character identifier for the detection.
    • rect.topLeft.x, rect.topLeft.y, rect.width, rect.height: pixel-space bounding box.
    • type: detection label string. Opaque values with mixed casing, for example: "Lesion", "Suspicious lesion", "Acne lesion", "Actinic keratosis lesion", "New actinic keratosis lesion", "Treatment", "acne", "wheal", "drainingTunnel", "nonDrainingTunnel", "nodule", "abscess". Match on the exact string.
    • confidence: number between 0 and 1, or null.
  • Note: the whole macroscopicMedia object is null when no image was captured.

Diagnostic result

The result field encapsulates the comprehensive results of the diagnostic process.

  • id: UUID of the result record. Stable for a given diagnostic report; useful for client-side caching and deduplication.
Metrics

metrics reports classifier performance for the case. All values are percentages from 0 to 100, and any of them can be null if the metric is not applicable to this body site or pathology.

  • sensitivity and specificity: classifier accuracy expressed as percentages.
  • entropy: how confident the AI is in its own response. Entropy is computed over the probability distribution of the diagnostic hypotheses; lower entropy means higher confidence, and higher entropy means lower confidence. Triage flows often use entropy as an uncertainty gate.
"metrics": {
"sensitivity": 83.31,
"specificity": 99.53,
"entropy": null
}
Preliminary findings

preliminaryFindings is a set of preliminary suspicions and their likelihoods, expressed as percentages from 0 to 100. Any field can be null when not applicable to the case.

  • hasCondition: likelihood that a condition is present.
  • malignancy: likelihood that the condition is malignant.
  • adjustedMalignancy: malignancy probability after applying clinical adjustments (for example, lesion-density or context-based corrections). A number between 0 and 100 when the adjustment model has run for the case, or null otherwise. Note: in the FHIR view this field is hard-coded null; the raw view is the only place where a numeric value can appear.
  • pigmentedLesion: likelihood that the lesion is pigmented.
  • urgentReferral: probability that the patient should be seen by a doctor within the next 48 hours. Higher values indicate a stronger recommendation to bring the patient forward into urgent care.
  • highPriorityReferral: probability that the patient should be seen by a doctor within the next 15 days. It complements urgentReferral by capturing cases that are not 48-hour-urgent but still warrant a fast-tracked appointment ahead of the routine queue.
"preliminaryFindings": {
"hasCondition": 100,
"malignancy": 0.02,
"adjustedMalignancy": null,
"pigmentedLesion": 0,
"urgentReferral": 100,
"highPriorityReferral": 100
}
iaSeconds

iaSeconds: wall-clock seconds the inference pipeline spent processing the case (image plus AI calls). Number with decimals; can be null if timing was not recorded.

Observations

The observations field is an array of medias, each containing one field: media.

media: the media sent to the algorithm to be analyzed. It includes:

  • url: signed S3 URL to the image. Time-limited (about 30 minutes); download within the window if you plan to use it later.
  • type: media format. One of "Image" or "Video". Always present.
  • modality: how the image was captured. One of "None", "Clinical", "Dermoscopic", or null. null for video uploads or when image-validity (DIQA + modality detection) did not run. The value is "Dermoscopic", not "Dermoscopy".
  • diqaScore: Dermatology Image Quality Assessment score on a 0 to 100 scale (float). null for videos or when DIQA was not computed.
  • Each entry contains only the media key. The v3 response does not emit originalMedia (that field is v2-only).
"observations": [
{
"media": {
"type": "Image",
"modality": "Clinical",
"diqaScore": 86,
"url": "https://bucket/diagnostic-report-medias/bbb.png"
}
},
...
]

Diagnostic conclusions

The conclusions field is an array of diagnostic outcomes, each containing a pathology type and its associated probability. Conclusions are sorted by probability (descending). Probabilities are percentages from 0 to 100.

"conclusions": [
{
"probability": 99.65,
"pathology": {
"name": "Acne",
"code": "Acne",
"icd11": "ED80"
}
},
...
]

Scoring systems

The scoringSystems field houses one or more scoring models for the identified pathology. These models come into play when the likelihood of the most probable conclusion surpasses a certain threshold. They are used to estimate the severity of the most probable condition:

"scoringSystems": [
{
"scoringSystem": {
"name": "Acne lesion estimation grading index",
"code": "alegi"
},
"score": {
"value": 8,
"severity": {
"value": 1,
"interpretations": [
{
"min": 0.0,
"max": 0.0,
"text": "None",
"coding": [
{
"code": 1,
"display": "low"
}
]
},
...
]
}
},
"reduction": null,
"facets": [
{
"facet": {
"name": "Acne lesion density",
"description": ""
},
"value": {
"display": "None (0)",
"raw": 0
}
},
...
],
"explainabilityMedia": {
"url": "https://bucket/diagnostic-report-medias/explainability/aaa.png"
}
}
]

In each scoring system:

  • scoringSystem includes the name and code of the scoring methodology. code is a camelCase identifier (e.g. alegi, apasiLocal, pasiLocal, scoradLocal, ihs4Local, hiscr, dlqi). Match on the exact camelCase string; do not assume SCREAMING_SNAKE_CASE.

Naming pattern:

  • Local suffix: the scoring system runs on a single body-site image.
  • Global suffix: the scoring system aggregates across all body sites for the same encounter.
  • a-prefix (e.g. apasiLocal, ascoradLocal, aihs4Local): AI-computed variants of the parent scoring system.

The complete list of supported scoring systems for a given pathology, together with their facet questionnaires, can be fetched from a public, unauthenticated endpoint:

GET https://medical-device-params.legit.health/v2.0/questionnaires?pathology=<ICD-11 code>

Pass the ICD-11 code of the pathology of interest as the pathology query parameter (e.g. EA90 for Psoriasis). The response is an array of objects describing each scoring system applicable to that pathology, with the following fields:

  • identifier: the camelCase scoring-system code emitted under scoringSystem.code (e.g. apasiLocal, pure4).
  • code: short identifier used internally by the severity-assessment endpoint (e.g. apasi, pure4).
  • mode: "local" or "global".
  • path: the severity-assessment endpoint path.
  • title, description: multilingual objects keyed by locale (en_GB, es_ES, ...).
  • questionnaire: an array of facet objects, each with code, name (multilingual), description (multilingual), and input (type, min/max, options). These correspond to the facets emitted under facets[] in the diagnostic-report response.

Use this endpoint as the source of truth: the catalog of scoring systems can grow over time.

  • score.value indicates the calculated score according to the system's rules. Can be null if the score could not be computed.
  • score.severity.value: integer severity code. One of 1 (low), 2 (moderate), 3 (high), or null when the scoring system has no severity band for this body site or locale. The English string label is exposed under score.severity.interpretations[].coding[0].display ("low", "moderate", "high"); the localized BAND label (such as "None", "Mild", "Moderate", "Severe", "Grade 1", "Stage 0") is exposed under score.severity.interpretations[].text.
  • score.severity.interpretations is an array describing every severity band defined for this scoring system at the relevant body site and locale. Each entry contains:
    • min: lower bound (inclusive) of the score range that maps to this band.
    • max: upper bound of the score range that maps to this band.
    • text: human-friendly label for the band (translated), e.g. "Mild", "Moderate", "Severe".
    • coding[]: machine-readable severity coding for the band, with each entry exposing a code and display.
  • reduction: object (or null) describing automatic score reductions (for example, lesion-density adjustments). Most scoring systems return null here.
  • facets is an array of facets used in score calculation, with each object containing the facet's information and the corresponding raw and displayed values.
  • explainabilityMedia: an object with a single url field. The object is always emitted; url is null when the scoring system did not produce an annotated overlay. When present, url is a signed S3 URL to a heatmap or bounding-box image explaining how the score was produced.

Comprehensive scoring systems information

For an exhaustive understanding of scoring systems, their identifiers, and facets, you can download the detailed documentation:

FHIR

/anonymous-diagnostic-reports/{encryptedId}?format=fhir
{
"success": true,
"message": "Diagnostic report <0194b1e2-d73e-71ba-9360-7b7a0ffa551b>",
"data": {
"resourceType": "DiagnosticReport",
"id": "cUVHY3lUcEFSdzdhVklrMXFKS2k5ZzBxaHBYWXNERTNFWjBqR0Rwd3AxeXkrc2hqNDNCdC8rM1NtUVhobEk0eQ==",
"presentedForm": {
"practitioner": {
"url": "https://iframe.legit.health?companyId=XXXX&diagnosticReportId=signedId",
"pdf": "https://utils.legit.health/pdf/anonymous-diagnostic-report?diagnosticReportIdEncrypted=<encryptedId>&apiKey=<apiKey>&authKey=<authKey>&locale=en"
},
"patient": {
"url": null,
"pdf": null
}
},
"encounter": {
"identifier": {
"value": "XYZ"
}
},
"issued": "2025-01-29T12:46:57+01:00",
"condition": {
"pathology": null,
"bodySite": {
"coding": [
{
"system": "https:\/\/legit.health\/integration\/json-only\/codes\/body-sites",
"code": "trunkFront",
"display": "Chest and belly"
}
]
}
},
"extraData": {
"externalCaseId": "CASE-123",
"referrer": "telemedicine-portal"
},
"anamnesisGeneral": {
"resourceType": "QuestionnaireResponse",
"status": "completed",
"item": [
{
"linkId": 1,
"text": "Question one?",
"answer": [
{
"valueString": "answer"
}
]
}
]
},
"macroscopicMedia": {
"resourceType": "Media",
"content": {
"url": "https://bucket/diagnostic-report-medias/bbb.png"
},
"type": "Image",
"annotations": null
},
"result": {
"id": "0194b1e2-d740-70d6-9435-a3606f0fa491",
"performanceIndicators": {
"resourceType": "Observation",
"component": [
{
"code": {
"coding": [
{
"code": "sensitivity",
"display": "Sensitivity"
}
]
},
"valueQuantity": {
"value": 91.16,
"unit": "%"
}
},
{
"code": {
"coding": [
{
"code": "specificity",
"display": "Specificity"
}
]
},
"valueQuantity": {
"value": 96.58,
"unit": "%"
}
},
{
"code": {
"coding": [
{
"code": "entropy",
"display": "Entropy"
}
]
},
"valueQuantity": {
"value": null,
"unit": "%"
}
}
]
},
"clinicalIndicators": {
"resourceType": "Observation",
"component": [
{
"code": {
"coding": [
{
"code": "hasCondition",
"display": "Has condition"
}
]
},
"valueQuantity": {
"value": 100.0,
"unit": "%"
}
},
{
"code": {
"coding": [
{
"code": "malignancy",
"display": "Malignancy"
}
]
},
"valueQuantity": {
"value": 0.0,
"unit": "%"
}
},
{
"code": {
"coding": [
{
"code": "adjustedMalignancy",
"display": "Adjusted malignancy"
}
]
},
"valueQuantity": {
"value": null,
"unit": "%"
}
},
{
"code": {
"coding": [
{
"code": "pigmentedLesion",
"display": "Pigmented lesion"
}
]
},
"valueQuantity": {
"value": null,
"unit": "%"
}
},
{
"code": {
"coding": [
{
"code": "urgentReferral",
"display": "Urgent referral"
}
]
},
"valueQuantity": {
"value": null,
"unit": "%"
}
},
{
"code": {
"coding": [
{
"code": "highPriorityReferral",
"display": "High priority referral"
}
]
},
"valueQuantity": {
"value": null,
"unit": "%"
}
}
]
},
"analysisDuration": 0.916,
"observations": [
{
"media": {
"resourceType": "Media",
"content": {
"url": "https://bucket/diagnostic-report-medias/bbb.png"
},
"type": "Image",
"modality": "Clinical",
"diqaScore": 86.0
}
},
{
"media": {
"resourceType": "Media",
"content": {
"url": "https://bucket/diagnostic-report-medias/bbb.png"
},
"type": "Image",
"modality": "Clinical",
"diqaScore": 92.0
}
}
],
"conclusions": [
{
"pathology": {
"coding": [
{
"code": "Psoriasis",
"display": "Psoriasis",
"system": "https:\/\/legit.health\/integration\/json-only\/codes\/conditions"
},
{
"code": "EA90",
"display": "Psoriasis",
"system": "ICD-11"
}
]
},
"probability": 80.0
},
{
"pathology": {
"coding": [
{
"code": "Palmoplantar psoriasis",
"display": "Palmoplantar psoriasis",
"system": "https:\/\/legit.health\/integration\/json-only\/codes\/conditions"
},
{
"code": "EA90.42, EA90.5Y",
"display": "Palmoplantar psoriasis",
"system": "ICD-11"
}
]
},
"probability": 20.0
}
],
"questionnaires": [
{
"resourceType": "QuestionnaireResponse",
"questionnaire": "apasiLocal",
"scoringSystem": {
"text": "Local automatic psoriasis area and severity index",
"coding": [
{
"code": "apasiLocal",
"display": "Local automatic psoriasis area and severity index"
}
]
},
"score": {
"valueQuantity": {
"value": 6.3
},
"system": "http:\/\/unitsofmeasure.org",
"unit": "points",
"interpretation": {
"coding": [
{
"code": 3,
"display": "Severe"
}
],
"text": "Severe"
},
"interpretations": [
{
"min": 0.0,
"max": 0.0,
"text": "None",
"coding": [
{
"code": 1,
"display": "low"
}
]
},
{
"min": 0.0,
"max": 2.1,
"text": "Mild",
"coding": [
{
"code": 1,
"display": "low"
}
]
},
{
"min": 2.1,
"max": 4.5,
"text": "Moderate",
"coding": [
{
"code": 2,
"display": "moderate"
}
]
},
{
"min": 4.5,
"max": 21.6,
"text": "Severe",
"coding": [
{
"code": 3,
"display": "high"
}
]
}
]
},
"explainabilityMedia": {
"resourceType": "Media",
"content": {
"url": "https://bucket/diagnostic-report-medias/bbb.png"
},
"annotations": [],
"type": "Image"
},
"item": [
{
"linkId": 30,
"text": "This value corresponds to the shedding intensity of the outermost layer of skin of the affected zone",
"code": [
{
"code": "Scaling",
"display": "Scaling"
}
],
"answer": [
{
"valueCoding": {
"code": 2,
"display": "Moderate (2)"
}
}
]
},
{
"linkId": 27,
"text": "This value corresponds to the redness intensity of the lesion",
"code": [
{
"code": "Erythema",
"display": "Erythema"
}
],
"answer": [
{
"valueCoding": {
"code": 3,
"display": "Severe (3)"
}
}
]
},
{
"linkId": 29,
"text": "This value corresponds to the hardening intensity of the lesion",
"code": [
{
"code": "Induration",
"display": "Induration"
}
],
"answer": [
{
"valueCoding": {
"code": 2,
"display": "Moderate (2)"
}
}
]
},
{
"linkId": 52,
"text": "This value corresponds to the percentage of involvement of the specific area of the body you are reporting",
"code": [
{
"code": "Affected area",
"display": "Affected area"
}
],
"answer": [
{
"valueCoding": {
"code": 3,
"display": "50% (3)"
}
}
]
}
],
"reduction": null,
"history": null
}
]
},
"patient": null,
"previousDiagnosticReportId": null,
"nextDiagnosticReportId": null,
"helpDiagnoseQuestionnaireAnswers": null,
"isPriority": null,
"isReviewed": null,
"patientVisibility": null
},
"errorCode": null
}

Top-level fields

The response begins with three fundamental fields that indicate the request’s outcome and location of data:

{
"success": true,
"message": "Diagnostic report <id>",
"data": { ... },
"errorCode": null
}
  • success: Indicates whether the request was successfully processed.
  • message: A short text message describing the action performed. Often includes the diagnostic report’s internal identifier.
  • data: Holds the main content of the diagnostic report in FHIR format.
  • errorCode: Used to return an error code if something fails.

data object

Within "data", the diagnostic report follows the FHIR specification. It encloses all information about the patient’s encounter, clinical findings, images, and conclusions.

"data": {
"resourceType": "DiagnosticReport",
"id": "cUVHY3lUcEFSdzdhVklrMXFKS2k5ZzBxaHBYWXNERTNFWjBqR0Rwd3AxeXkrc2hqNDNCdC8rM1NtUVhobEk0eQ==",
"presentedForm": { ... },
"encounter": { ... },
"issued": "2025-01-29T12:46:57+01:00",
"condition": { ... },
"extraData": null,
"anamnesisGeneral": { ... },
"macroscopicMedia": { ... },
"result": { ... },
"patient": null,
"previousDiagnosticReportId": null,
"nextDiagnosticReportId": null,
"helpDiagnoseQuestionnaireAnswers": null,
"isPriority": null,
"isReviewed": null,
"patientVisibility": null
}

Below is a breakdown of its main sections:

  • resourceType: Specifies the FHIR resource type, which is "DiagnosticReport".
  • id: An encrypted, URL-safe identifier for this Diagnostic Report. This is the same opaque encryptedId value used in the API path; treat it as an opaque string.
  • presentedForm: Contains links that allow viewing the diagnostic report in different forms (browser or PDF). Typically includes:
    • practitioner.url: A link where a practitioner can view the diagnostic report. null if the company does not have a valid iframe app key configured.
    • practitioner.pdf: A link to download the PDF of the report. Calling the API endpoint with ?format=pdf issues an HTTP 302 redirect to this same URL; most HTTP clients follow it automatically and receive the PDF. Treat the URL as opaque and refetch the diagnostic report if it stops working.
    • patient.url / patient.pdf: If relevant to the patient, these fields may provide them with URLs for viewing or downloading their report. If unused, they may remain null.
"presentedForm": {
"practitioner": {
"url": "...",
"pdf": "..."
},
"patient": {
"url": null,
"pdf": null
}
}
  • encounter: Contains the identifier that links this diagnostic report to a particular healthcare encounter or visit. value is the visit/encounter identifier passed in when the diagnostic report was created. null if no visit identifier was provided.
"encounter": {
"identifier": {
"value": "some-unique-encounter-id"
}
}
  • issued: ISO-8601 timestamp (with timezone offset) indicating when the diagnostic report was issued or finalized, e.g. 2025-01-29T12:46:57+01:00.
  • condition: Describes the suspected or most likely condition and the body site:
    • pathology: May contain the name or code for a confirmed condition. pathology is null when no condition has been set on the report. When set, it follows the same coding[] array shape as result.conclusions[].pathology: two entries, one in the proprietary legit.health/integration/json-only/codes/conditions system and one in ICD-11.
    • bodySite: Provides standardized information about the anatomical location using code, display, and a system that references a coding standard.
"condition": {
"pathology": null,
"bodySite": {
"coding": [
{
"system": "https://legit.health/integration/json-only/codes/body-sites",
"code": "trunkFront",
"display": "Chest and belly"
}
]
}
}

When pathology is populated, it looks like this:

"condition": {
"pathology": {
"coding": [
{
"code": "Psoriasis",
"display": "Psoriasis",
"system": "https://legit.health/integration/json-only/codes/conditions"
},
{
"code": "EA90",
"display": "Psoriasis",
"system": "ICD-11"
}
]
},
"bodySite": { ... }
}

pathology.coding[0] is the proprietary legit.health/integration/json-only/codes/conditions entry. pathology.coding[0].code is a stable, human-readable internal identifier ("Psoriasis", "Cutaneous melanoma", "Acne", ...) drawn from a database-backed catalog of roughly 309 base conditions, plus any per-tenant custom condition. Treat it as a known-list-with-extensions.

pathology.coding[1] is the ICD-11 mapping (system is the literal string "ICD-11" with a hyphen). pathology.coding[1].code may be a single ICD-11 code (e.g. "EA90") or several comma-separated codes when one proprietary condition maps to multiple ICD-11 entries (e.g. "EA90.42, EA90.5Y"). code is null when no ICD-11 mapping exists for that condition.

bodySite is always present in the response (never null). bodySite.coding[0].code is a camelCase identifier (e.g. headFront, trunkFront, armLeft). Match on the exact camelCase string; do not assume SCREAMING_SNAKE_CASE. bodySite.coding[0].display is the human-readable label, translated by the locale query parameter.

The complete list of supported body-site codes and their multilingual names can be fetched from a public, unauthenticated endpoint:

GET https://medical-device-params.legit.health/v2.0/body-sites

The response is an array of objects with two fields:

  • code: the camelCase identifier emitted under bodySite.coding[0].code (e.g. headFront, armLeft, trunkFront).
  • name: an object keyed by locale (en_GB, es_ES, pt_BR, it_IT, fr_FR, de_DE, bg_BG, pl_PL, ko_KO, ca_ES) with the translated display name.

Use this endpoint as the source of truth: the list can grow over time as new body sites are added.

  • extraData: An optional free-form JSON object (or null) that the client passed in when loading the iframe. Whatever structure was set on the source side is echoed back verbatim.
  • anamnesisGeneral: Stores general Q&A information about the patient’s history in FHIR’s QuestionnaireResponse format. It can contain items representing the questions and their answers.
"anamnesisGeneral": {
"resourceType": "QuestionnaireResponse",
"status": "completed",
"item": [
{
"linkId": 1,
"text": "Question one?",
"answer": [
{
"valueString": "answer"
}
]
},
...
]
}
  • resourceType: Always "QuestionnaireResponse".
  • status: Indicates the status of the questionnaire (e.g. "completed").
  • item: An array of question-answer pairs. Each entry has a linkId (the question's identifier, emitted as a JSON integer; note that the FHIR R4 standard usually types linkId as a string, but this API emits an integer primary key), a text (the human-readable question) and an answer[] with valueStrings.
  • macroscopicMedia: Details an image or other media of the lesion or body part. Here, it references a resource of type "Media":
    • resourceType: Always "Media".
    • content.url: A direct URL to access the uploaded file, typically a signed URL valid for a limited time.
    • type: media format. One of "Image" or "Video". null when the original upload had no recorded type (which happens together with the whole macroscopicMedia object being itself null).
    • annotations: always null in the FHIR view, even when the raw view exposes detections for the same image. Detection data is exposed instead per scoring system, in result.questionnaires[].explainabilityMedia.annotations.
"macroscopicMedia": {
"resourceType": "Media",
"content": {
"url": "https://...jpg"
},
"type": "Image",
"annotations": null
}

result

The core field that captures the diagnostic process output. It includes identifiers, metrics, conclusions, and any scoring systems or questionnaires used to evaluate the condition.

"result": {
"id": "0194b1e2-d740-70d6-9435-a3606f0fa491",
"performanceIndicators": { ... },
"clinicalIndicators": { ... },
"analysisDuration": 0.916,
"observations": [ ... ],
"conclusions": [ ... ],
"questionnaires": [ ... ]
}

Below are its main subfields:

  • result.id: UUID for this specific result row (distinct from the top-level id, which identifies the encrypted DiagnosticReport).
  • performanceIndicators: A FHIR Observation that shows performance metrics such as sensitivity, specificity, and entropy:
    • code.coding: An array containing the codes that describe the metric name (e.g. "sensitivity", "specificity", "entropy").
    • valueQuantity.value: The numeric value of the metric.
    • valueQuantity.unit: Usually "%" or other relevant units.
    • entropy (component code "entropy"): a measure of how confident the AI is in its own response. Entropy is computed over the probability distribution of the diagnostic hypotheses; lower entropy means higher confidence, and higher entropy means lower confidence. Triage flows often use entropy as an uncertainty gate.
"performanceIndicators": {
"resourceType": "Observation",
"component": [
{
"code": {
"coding": [
{
"code": "sensitivity",
"display": "Sensitivity"
}
]
},
"valueQuantity": {
"value": 91.16,
"unit": "%"
}
},
...
]
}
  • clinicalIndicators: Another FHIR Observation describing clinical aspects such as the probability of having the condition or malignancy suspicion. Each component focuses on a specific clinical clue, with the value carried in valueQuantity.value (percentage from 0 to 100):
    • hasCondition: Likelihood that a condition is present.
    • malignancy: Likelihood that the condition is malignant.
    • urgentReferral: probability that the patient should be seen by a doctor within the next 48 hours. Higher values indicate a stronger recommendation to bring the patient forward into urgent care.
    • highPriorityReferral: probability that the patient should be seen by a doctor within the next 15 days. It complements urgentReferral by capturing cases that are not 48-hour-urgent but still warrant a fast-tracked appointment ahead of the routine queue.
    • pigmentedLesion: Likelihood that the lesion is pigmented.
    • adjustedMalignancy: In the FHIR view, the adjustedMalignancy component's valueQuantity.value is HARD-CODED null for v3 anonymous reports, even when the raw view (result.preliminaryFindings.adjustedMalignancy) returns a number. Treat it as always null in FHIR responses.
"clinicalIndicators": {
"resourceType": "Observation",
"component": [
{
"code": {
"coding": [
{
"code": "hasCondition",
"display": "Has condition"
}
]
},
"valueQuantity": {
"value": 100.0,
"unit": "%"
}
},
...
]
}
  • analysisDuration: Seconds the AI engine spent analysing the images (floating-point). null if the diagnostic engine did not record a duration.
  • observations: An array of observations that reference each media file examined:
    • media.resourceType: always "Media".
    • media.content.url: signed S3 URL to the file. Time-limited (about 30 minutes).
    • media.type: media format. One of "Image" or "Video". Always present.
    • media.modality: how the image was captured. One of "None", "Clinical", "Dermoscopic", or null. null for video uploads or when image-validity did not run. The value is "Dermoscopic", not "Dermoscopy".
    • media.diqaScore: Dermatology Image Quality Assessment score on a 0 to 100 scale (float). null for videos or when DIQA was not computed.
    • Each observation contains only the media key. The v3 FHIR response does not emit originalMedia (that field is v2-only).
"observations": [
{
"media": {
"resourceType": "Media",
"content": { "url": "..." },
"type": "Image",
"modality": "Clinical",
"diqaScore": 86.0
}
},
...
]
  • conclusions: Represents the list of possible conditions identified, each with a probability and standardized coding:
"conclusions": [
{
"pathology": {
"coding": [
{
"code": "Psoriasis",
"display": "Psoriasis",
"system": "https://legit.health/integration/json-only/codes/conditions"
},
{
"code": "EA90",
"display": "Psoriasis",
"system": "ICD-11"
}
]
},
"probability": 100.0
},
...
]
  • pathology.coding[0].code: The code that identifies the condition (e.g. "Psoriasis"). Stable, human-readable internal identifier from the proprietary catalog.
  • pathology.coding[0].display: Human-friendly label for the condition (e.g. "Psoriasis").
  • pathology.coding[1]: The ICD-11 mapping of the same condition. system is the literal string "ICD-11" (with hyphen). code may be a single ICD-11 code (e.g. "EA90") or several comma-separated codes when one proprietary condition maps to multiple ICD-11 entries (e.g. "EA90.42, EA90.5Y"). code is null when no ICD-11 mapping has been recorded for that condition. display mirrors the proprietary display.
  • probability: The likelihood of this condition being correct, expressed as a percentage.

questionnaires

An array of QuestionnaireResponse objects, each containing details about a scoring system applied to the images:

"questionnaires": [
{
"resourceType": "QuestionnaireResponse",
"questionnaire": "apasiLocal",
"scoringSystem": {
"text": "Local automatic psoriasis area and severity index",
"coding": [
{ "code": "apasiLocal", "display": "Local automatic psoriasis area and severity index" }
]
},
"score": { ... },
"explainabilityMedia": { ... },
"item": [ ... ]
}
]
  • resourceType: Always "QuestionnaireResponse".
  • questionnaire: The internal code/name of the scoring system (e.g., "apasiLocal"). A camelCase identifier; match on the exact string. Do not assume SCREAMING_SNAKE_CASE.
  • scoringSystem: Contains the name (text) and coding[] array for the scoring methodology. coding[0].code is the same camelCase identifier as questionnaire.

Naming pattern:

  • Local suffix: the scoring system runs on a single body-site image.
  • Global suffix: the scoring system aggregates across all body sites for the same encounter.
  • a-prefix (e.g. apasiLocal, ascoradLocal, aihs4Local): AI-computed variants of the parent scoring system.

The complete list of supported scoring systems for a given pathology, together with their facet questionnaires, can be fetched from a public, unauthenticated endpoint:

GET https://medical-device-params.legit.health/v2.0/questionnaires?pathology=<ICD-11 code>

Pass the ICD-11 code of the pathology of interest as the pathology query parameter (e.g. EA90 for Psoriasis). The response is an array of objects describing each scoring system applicable to that pathology, with the following fields:

  • identifier: the camelCase scoring-system code emitted under questionnaire and scoringSystem.coding[0].code (e.g. apasiLocal, pure4).
  • code: short identifier used internally by the severity-assessment endpoint (e.g. apasi, pure4).
  • mode: "local" or "global".
  • path: the severity-assessment endpoint path.
  • title, description: multilingual objects keyed by locale (en_GB, es_ES, ...).
  • questionnaire: an array of facet objects, each with code, name (multilingual), description (multilingual), and input (type, min/max, options). These correspond to the FHIR item[] entries emitted under each questionnaire in the diagnostic-report response.

Use this endpoint as the source of truth: the catalog of scoring systems can grow over time.

  • score: The numeric outcome of the scoring system along with its severity interpretation. Note: unit ("points") and system ("http://unitsofmeasure.org") are emitted as siblings of valueQuantity inside score, not inside valueQuantity itself.
    • score.interpretation: The interpretation that applies to this particular score value (a single band).
      • score.interpretation.coding[0].code: integer severity code. One of 1 (low), 2 (moderate), 3 (high), or null.
      • score.interpretation.coding[0].display: English string label for the severity tier. One of "low", "moderate", "high".
      • score.interpretation.text: the localized BAND label, translated by the locale query parameter. Examples (English): "None", "Mild", "Moderate", "Severe", "Very severe", "Grade 1" to "Grade 9", "Stage 0" to "Stage 4", plus PROM-specific labels for DLQI, UCT, PURE4, and apulsi.
    • score.interpretations: All defined severity bands for this scoring system, in order. Each band has min (inclusive), max (exclusive), text (band label, translated) and coding[] (machine code + display: code is the integer severity 1/2/3/null; display is the English string label "low"/"moderate"/"high"). Use these to render a band scale or to map a score onto a category client-side.
  • explainabilityMedia: an annotated Media resource that highlights how the score was determined. The whole object is null when no annotated explainability media is available for this scoring system run. When present:
    • resourceType: always "Media".
    • content.url: signed S3 URL. Time-limited (about 30 minutes).
    • type: always "Image" (scoring-system explainability is never a video).
    • annotations: array of detection objects, possibly empty. Each entry has id, rect.topLeft.{x,y}, rect.width, rect.height, type (a detection label string from the same fixed set used in the raw view: "Lesion", "Suspicious lesion", "Acne lesion", "Actinic keratosis lesion", "New actinic keratosis lesion", "Treatment", "acne", "wheal", "drainingTunnel", "nonDrainingTunnel", "nodule", "abscess"), and confidence (number 0 to 1 or null).
  • item: An array of question-answer objects relevant to the scoring, each containing:
    • linkId: the stable, locale-independent identifier for the facet. Emitted as a JSON integer (a primary key from the backing entity). Note that the FHIR R4 standard usually types linkId as a string; this API emits an integer.
    • code[]: an array with one coding entry whose code and display both carry the TRANSLATED facet name (e.g. "Erythema" in English, "Eritema" in Spanish). Important: code[].code CHANGES with the locale query parameter; do not use it as a stable identifier in your integration logic. The stable, locale-independent identifier is item[].linkId. Switch on linkId, not on code[].code.
    • answer: The recorded response, often including a numeric level (e.g., "Moderate (2)"). answer[].valueCoding.code is the facet value as a JSON number; whole-number values serialize WITHOUT a trailing .0 (e.g. 2, not 2.0), while non-integer values serialize normally (e.g. 2.5).
  • reduction: Reserved for a future "score change vs previous report" payload. Always null for anonymous reports.
  • history: Reserved for a future "previous scores" payload. Always null for anonymous reports.

Always-null top-level fields

After result, the FHIR response always emits these sibling keys at the top of data:

"patient": null,
"previousDiagnosticReportId": null,
"nextDiagnosticReportId": null,
"helpDiagnoseQuestionnaireAnswers": null,
"isPriority": null,
"isReviewed": null,
"patientVisibility": null
  • patient
  • previousDiagnosticReportId
  • nextDiagnosticReportId
  • helpDiagnoseQuestionnaireAnswers
  • isPriority
  • isReviewed
  • patientVisibility

These keys are always present in the response and currently always null for v3 anonymous diagnostic reports. They are reserved for future authenticated/non-anonymous flows; integrators should ignore them but parsers must tolerate them.


Obtaining a PDF

You can generate a PDF with the contents of anonymous diagnostic report by calling the endpoint getAnonymousDiagnosticReport with the query param format=pdf:

/anonymous-diagnostic-reports/{encryptedId}?format=pdf